Merge "Baseline global lint errors in telephony" into main am: cd7765fd49 am: 0f271bcc7c
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/3282654
Change-Id: I35aa01c34b2a243a3ee529f2e2e00fcdc92d03df
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 1885032..edcfc3f 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -33,6 +33,7 @@
"subscription.aconfig",
"uicc.aconfig",
"satellite.aconfig",
- "iwlan.aconfig"
+ "iwlan.aconfig",
+ "carrier.aconfig",
],
}
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index c1dc7e7..906abfc 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -4,7 +4,6 @@
# 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"
@@ -21,6 +20,17 @@
# OWNER=stevestatia TARGET=24Q4
flag {
+ name: "national_country_code_formatting_for_local_calls"
+ namespace: "telephony"
+ description: "Make requests and bug fixes for formatting local calls based on country codes easier with a more scalable solution."
+ bug: "293993310"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=stevestatia TARGET=24Q4
+flag {
name: "remove_country_code_from_local_singapore_calls"
namespace: "telephony"
description: "Fix bug where the country code is being shown when merging in local Singapore numbers to conference calls."
@@ -29,3 +39,34 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=grantmenke TARGET=25Q1
+flag {
+ name: "remap_disconnect_cause_sip_request_cancelled"
+ namespace: "telephony"
+ description: "Fix dialer UI bug by remapping disconnect CODE_SIP_REQUEST_CANCELLED to DisconnectCause.NORMAL"
+ bug: "351258918"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+ is_exported: true
+}
+
+# OWNER=breadley TARGET=24Q4
+flag {
+ name: "delay_phone_account_registration"
+ namespace: "telephony"
+ description: "Fix bug where telephony would try to register for PhoneAccounts when Telecom isn't ready yet"
+ bug: "349731543"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=yongnamcha TARGET=25Q2
+flag {
+ name: "emergency_callback_mode_notification"
+ namespace: "telephony"
+ description: "Used to notify the emergency callback mode for call/SMS to other applications."
+ bug:"359064059"
+}
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
new file mode 100644
index 0000000..265d258
--- /dev/null
+++ b/flags/carrier.aconfig
@@ -0,0 +1,23 @@
+package: "com.android.internal.telephony.flags"
+container: "system"
+
+# OWNER=nharold TARGET=24Q4
+flag {
+ name: "async_init_carrier_privileges_tracker"
+ is_exported: true
+ namespace: "telephony"
+ description: "Offload the heavyweight initialization of CarrierPrivilegesTracker to a worker thread"
+ bug:"357096337"
+}
+
+# OWNER=melhuishj TARGET=25Q1
+flag {
+ name: "cleanup_carrier_app_update_enabled_state_logic"
+ is_exported: true
+ namespace: "telephony"
+ description: "Improve readability of update state logic"
+ bug:"232141900"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index d956104..ccd5db4 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -34,53 +34,6 @@
}
}
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "use_alarm_callback"
- namespace: "telephony"
- description: "Use alarm callback instead of broadcast."
- bug: "311476875"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "refine_preferred_data_profile_selection"
- namespace: "telephony"
- description: "Upon internet network connect, refine selection of preferred data profile."
- bug: "311476883"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "unthrottle_check_transport"
- namespace: "telephony"
- description: "Check transport when unthrottle."
- bug: "303922311"
-}
-
-# OWNER=linggm TARGET=24Q1
-flag {
- name: "relax_ho_teardown"
- namespace: "telephony"
- description: "Relax handover tear down if the device is currently in voice call."
- bug: "270895912"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "allow_mmtel_in_non_vops"
- namespace: "telephony"
- description: "Allow bring up MMTEL in nonVops area specified by carrier config."
- bug: "241198464"
-}
-
-# OWNER=jackyu TARGET=24Q2
-flag {
- name: "metered_embb_urlcc"
- namespace: "telephony"
- description: "Force networks that have PRIORITIZE_BANDWIDTH or PRIORITIZE_LATENCY to be metered."
- bug: "301310451"
- }
# OWNER=sarahchin TARGET=24Q3
flag {
@@ -109,14 +62,6 @@
bug:"286171724"
}
-# OWNER=nagendranb TARGET=24Q2
-flag {
- name: "notify_data_activity_changed_with_slot"
- namespace: "telephony"
- description: "notify data activity changed for slot id"
- bug: "309896936"
-}
-
# OWNER=qingqi TARGET=24Q3
flag {
name: "vonr_enabled_metric"
@@ -125,14 +70,6 @@
bug:"288449751"
}
-# OWNER=willycwhu TARGET=24Q2
-flag {
- name: "ignore_existing_networks_for_internet_allowed_checking"
- namespace: "telephony"
- description: "Ignore existing networks when checking if internet is allowed"
- bug: "284420611"
-}
-
# OWNER=apsankar TARGET=24Q3
flag {
name: "data_call_session_stats_captures_cross_sim_calling"
@@ -141,14 +78,6 @@
bug: "313956117"
}
-# OWNER=jackyu TARGET=24Q2
-flag {
- name: "force_iwlan_mms"
- namespace: "telephony"
- description: "When QNS prefers MMS on IWLAN, MMS will be attempted on IWLAN if it can, even though if existing cellular network already supports MMS."
- bug: "316211526"
-}
-
# OWNER=sewook TARGET=24Q3
flag {
name: "reconnect_qualified_network"
@@ -172,3 +101,41 @@
description: "Write DataRatStateChanged atom"
bug:"318519337"
}
+
+# OWNER=jackyu TARGET=24Q4
+flag {
+ name: "dds_callback"
+ namespace: "telephony"
+ description: "Adding new callback when DDS changed"
+ bug:"353723350"
+}
+
+# OWNER=jackyu TARGET=25Q1
+flag {
+ name: "support_network_provider"
+ namespace: "telephony"
+ description: "Deprecate network factory and adapt the new network provider model from connectivity service"
+ bug: "343370895"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jackyu TARGET=25Q1
+flag {
+ name: "sim_disabled_graceful_tear_down"
+ namespace: "telephony"
+ description: "Gracefully tear down the networks when SIM is disabled."
+ bug: "362372940"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=TBD TARGET=TBD
+flag {
+ name: "oem_paid_private"
+ namespace: "telephony"
+ description: "Support OEM_PAID and OEM_PRIVATE networks"
+ bug: "366194627"
+}
diff --git a/flags/domainselection.aconfig b/flags/domainselection.aconfig
index 623c3b6..4b1ad4a 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -33,3 +33,11 @@
description: "This flag controls domain selection metrics."
bug:"258112541"
}
+
+# OWNER=jdyou TARGET=24Q4
+flag {
+ name: "hangup_emergency_call_for_cross_sim_redialing"
+ namespace: "telephony"
+ description: "This flag controls the behavior of terminating an emergency call for cross SIM redialing."
+ bug:"336398541"
+}
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4eff505..4426933 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -115,3 +115,33 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=joonhunshin TARGET=24Q4
+flag {
+ name: "prevent_hangup_during_call_merge"
+ namespace: "telephony"
+ description: "This flag prevents hangup call during call merge"
+ bug:"317070933"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=joonhunshin TARGET=24Q4
+flag {
+ name: "avoid_deleting_ims_object_from_cache"
+ namespace: "telephony"
+ description: "This flag controls deleting cached object to synchronize part of application callback and part of ImsFeature behavior"
+ bug:"353577279"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=meghapatil TARGET=25Q2
+flag {
+ name: "support_sms_over_ims_apis"
+ namespace: "telephony"
+ description: "Used to expose SMS related hidden APIs for SMS over IMS to public API."
+ bug:"359721349"
+}
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 1030ba7..905dc94 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -38,4 +38,12 @@
metadata {
purpose: PURPOSE_BUGFIX
}
+}
+
+# OWNER=nykkumar TARGET=25Q2
+flag {
+ name: "sms_mms_deliver_broadcasts_redirect_to_main_user"
+ namespace: "telephony"
+ description: "This flag controls the redirection of SMS_DELIVER AND WAP_PUSH_DELIVER broadcasts to the MAIN user."
+ bug: "314321617"
}
\ No newline at end of file
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 862aa33..2d6992a 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -78,46 +78,6 @@
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: "add_anomaly_when_notify_config_changed_with_invalid_phone"
- namespace: "telephony"
- description: "Report anomaly when CarrierConfigLoader received config change with sub that maps to invalid phoneId"
- bug:"270757342"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-# OWNER=rambowang TARGET=24Q3
-flag {
- name: "hide_preinstalled_carrier_app_at_most_once"
- namespace: "telephony"
- description: "Fix bug when preloaded carrier app is uninstalled and lose provisioning data"
- bug:"158028151"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
# OWNER=sangyun TARGET=24Q3
flag {
name: "roaming_notification_for_single_data_network"
@@ -206,3 +166,48 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=joonhunshin TARGET=24Q4
+flag {
+ name: "use_carrier_config_for_cfnry_time_via_mmi"
+ namespace: "telephony"
+ description: "This flag allows the no reply timer to be referenced in the carrier config when setting up call forward via MMI code and there is no timer value."
+ bug:"342346827"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+ name: "hsum_broadcast"
+ namespace: "telephony"
+ description: "Fixed the bug that broadcast intent is only sent to the system user."
+ bug:"362554272"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=rambowang TARGET=25Q2
+flag {
+ name: "support_carrier_services_for_hsum"
+ namespace: "telephony"
+ description: "Support Carrier Services (APIs) for HSUM."
+ bug:"345522246"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+ name: "hsum_package_manager"
+ namespace: "telephony"
+ description: "Fixed the bug that package manager is not for the right user"
+ bug:"356827794"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 2eea80a..4806789 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -33,4 +33,32 @@
namespace: "telephony"
description: "This flag enables satellite persistent logging"
bug:"339877723"
+}
+
+# OWNER=hyosunkim TARGET=24Q3
+flag {
+ name: "carrier_roaming_nb_iot_ntn"
+ namespace: "telephony"
+ description: "This flag enables satellite carrier roaming to nb iot ntn."
+ bug:"348253735"
+}
+
+# OWNER=tnd TARGET=24Q4
+flag {
+ name: "oem_enabled_satellite_phase_2"
+ is_exported: true
+ namespace: "telephony"
+ description: "This flag controls satellite communication supported by OEMs in phase 2."
+ bug:"349624547"
+}
+
+# OWNER=youngtaecha TARGET=24Q4
+flag {
+ name: "geofence_enhancement_for_better_ux"
+ namespace: "telephony"
+ description: "Enhance geofence to improve UX experience"
+ bug: "347711329"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
\ No newline at end of file
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 9a5dabc..543aa20 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -19,23 +19,6 @@
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"
- description: "Support emergency call only for data only cellular service."
- bug: "296097429"
-}
-
# OWNER=hhshin TARGET=24Q3
flag {
name: "support_psim_to_esim_conversion"
@@ -77,3 +60,15 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=jackyu TARGET=24Q4
+flag {
+ name: "uicc_phone_number_fix"
+ namespace: "telephony"
+ description: "Fixed that empty phone number when getLine1Number returns empty"
+ bug: "302437869"
+
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index 2679cfe..ad0c59f 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -43,14 +43,6 @@
bug:"318348580"
}
-# OWNER=rambowang TARGET=24Q3
-flag {
- name: "cleanup_open_logical_channel_record_on_dispose"
- namespace: "telephony"
- description: "This flag cleans up the OpenLogicalChannelRecord once SIM is removed"
- bug:"335046531"
-}
-
# OWNER=arunvoddu TARGET=24Q4
flag {
name: "set_carrier_restriction_status"
@@ -58,3 +50,33 @@
description: "This flag controls the visibility of the setCarrierRestrictionStatus API in carrierRestrictionRules class."
bug:"342411308"
}
+
+# OWNER=arunvoddu TARGET=24Q4
+flag {
+ name: "uicc_app_count_check_to_create_channel"
+ namespace: "telephony"
+ description: "This flag controls to create the open channel when uicc application count is greater than 0."
+ bug:"349966950"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=mewan TARGET=24Q4
+flag {
+ name: "optimization_apdu_sender"
+ namespace: "telephony"
+ description: "This flag controls optimization of apdu sender class."
+ bug:"335257880"
+}
+
+# OWNER=arunvoddu TARGET=24Q4
+flag {
+ name: "ignore_carrierid_reset_for_sim_removal"
+ namespace: "telephony"
+ description: "This flag controls the carrierId reset while imsi key deletion time upon sim ejection."
+ bug:"366178705"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/proto/Android.bp b/proto/Android.bp
index 15c0aea..adc9b5e 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -31,3 +31,12 @@
// Pin java_version until jarjar is certified to support later versions. http://b/72703434
java_version: "1.8",
}
+
+java_library_static {
+ name: "telephony-config-update-proto-lite",
+ proto: {
+ type: "lite",
+ },
+ srcs: ["src/**/telephony_config_update.proto"],
+ host_supported: true,
+}
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 48e7b0d..9dbdcb0 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -320,6 +320,7 @@
optional bool is_ntn = 41;
optional bool supports_business_call_composer = 42;
optional int32 call_composer_status = 43;
+ optional int32 precise_call_state_on_setup = 44;
// Internal use only
optional int64 setup_begin_millis = 10001;
@@ -717,6 +718,11 @@
optional int32 count_of_allowed_satellite_access = 26;
optional int32 count_of_disallowed_satellite_access = 27;
optional int32 count_of_satellite_access_check_fail = 28;
+ optional bool is_provisioned = 29;
+ optional int32 carrier_id = 30;
+ optional int32 count_of_satellite_allowed_state_changed_events = 31;
+ optional int32 count_of_successful_location_queries = 32;
+ optional int32 count_of_failed_location_queries = 33;
}
message SatelliteSession {
@@ -733,6 +739,10 @@
optional int32 count_of_incoming_datagram_failed = 11;
optional bool is_demo_mode = 12;
optional int32 max_ntn_signal_strength_level = 13;
+ optional int32 carrier_id = 14;
+ optional int32 count_of_satellite_notification_displayed = 15;
+ optional int32 count_of_auto_exit_due_to_screen_off = 16;
+ optional int32 count_of_auto_exit_due_to_tn_network = 17;
}
message SatelliteIncomingDatagram {
@@ -740,6 +750,7 @@
optional int32 datagram_size_bytes = 2;
optional int64 datagram_transfer_time_millis = 3;
optional bool is_demo_mode = 4;
+ optional int32 carrier_id = 5;
}
message SatelliteOutgoingDatagram {
@@ -748,6 +759,7 @@
optional int32 datagram_size_bytes = 3;
optional int64 datagram_transfer_time_millis = 4;
optional bool is_demo_mode = 5;
+ optional int32 carrier_id = 6;
}
message SatelliteProvision {
@@ -755,6 +767,7 @@
optional int32 provisioning_time_sec = 2;
optional bool is_provision_request = 3;
optional bool is_canceled = 4;
+ optional int32 carrier_id = 5;
}
message SatelliteSosMessageRecommender {
@@ -766,6 +779,8 @@
optional bool is_multi_sim = 6;
optional int32 recommending_handover_type = 7;
optional bool is_satellite_allowed_in_current_location = 8;
+ optional bool is_wifi_connected = 9;
+ optional int32 carrier_id = 10;
}
message DataNetworkValidation {
@@ -805,6 +820,8 @@
optional int32 satellite_session_gap_min_sec = 5;
optional int32 satellite_session_gap_avg_sec = 6;
optional int32 satellite_session_gap_max_sec = 7;
+ optional int32 carrier_id = 8;
+ optional bool is_device_entitled = 9;
}
message SatelliteEntitlement {
@@ -832,4 +849,6 @@
optional int32 result_code = 7;
repeated string country_codes = 8;
optional int32 config_data_source = 9;
+ optional int32 carrier_id = 10;
+ optional int32 triggering_event = 11;
}
diff --git a/src/java/com/android/internal/telephony/CarrierActionAgent.java b/src/java/com/android/internal/telephony/CarrierActionAgent.java
index 6d74c18..c4ba77d 100644
--- a/src/java/com/android/internal/telephony/CarrierActionAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierActionAgent.java
@@ -186,7 +186,8 @@
mPhone.getServiceStateTracker().registerForDataRoamingOff(
this, EVENT_DATA_ROAMING_OFF, null, false);
}
- } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(iccState)) {
+ } else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(iccState)
+ || IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(iccState)) {
log("EVENT_SIM_STATE_CHANGED status: " + iccState);
carrierActionReset();
mSettingsObserver.unobserve();
@@ -257,6 +258,8 @@
return mCarrierActionOnRadioEnabled;
case CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS:
return mCarrierActionReportDefaultNetworkStatus;
+ case EVENT_APN_SETTINGS_CHANGED:
+ return null; // we don't know if it's enabled, but this is not "unsupported" action
default:
loge("Unsupported action: " + action);
return null;
diff --git a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
index 10a3a32..1667b7d 100644
--- a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
+++ b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
@@ -120,7 +120,7 @@
private boolean mAllowedOverMeteredNetwork = false;
private boolean mDeleteOldKeyAfterDownload = false;
private boolean mIsRequiredToHandleUnlock;
- private final TelephonyManager mTelephonyManager;
+ private TelephonyManager mTelephonyManager;
private UserManager mUserManager;
@VisibleForTesting
public String mMccMncForDownload = "";
@@ -146,13 +146,14 @@
.createForSubscriptionId(mPhone.getSubId());
if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
- } else {
- mUserManager = mContext.getSystemService(UserManager.class);
}
+ 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,
+ if (carrierConfigManager != null) {
+ carrierConfigManager.registerCarrierConfigChangeListener(this::post,
(slotIndex, subId, carrierId, specificCarrierId) -> {
if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
logd("CarrierConfig changed slotIndex = " + slotIndex + " subId = " + subId
@@ -162,17 +163,36 @@
if ((slotIndex == mPhone.getPhoneId()) && (carrierId > 0
|| !TextUtils.isEmpty(
mMccMncForDownload))) {
- mCarrierId = carrierId;
+ if (mTelephonyManager == null
+ || mTelephonyManager.getSubscriptionId() != subId) {
+ logd("recreating TelManager with SubId = " + subId);
+ mTelephonyManager = mContext.getSystemService(
+ TelephonyManager.class)
+ .createForSubscriptionId(subId);
+ }
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ if (carrierId > 0) {
+ mCarrierId = carrierId;
+ }
+ } else {
+ 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");
+ printDeviceLockStatus();
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ if (!mUserManager.isUserUnlocked()) {
+ mIsRequiredToHandleUnlock = true;
+ return;
+ }
+ } else if (mKeyguardManager.isDeviceLocked()) {
mIsRequiredToHandleUnlock = true;
- } else {
- logd("Carrier Config changed: slotIndex=" + slotIndex);
- sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ return;
}
+ logd("Carrier Config changed: slotIndex=" + slotIndex);
+ sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+
}
} else {
boolean isUserUnlocked = mUserManager.isUserUnlocked();
@@ -187,9 +207,15 @@
}
}
});
+ }
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
}
+ private void printDeviceLockStatus() {
+ logd(" Device Status: isDeviceLocked = " + mKeyguardManager.isDeviceLocked()
+ + " iss User unlocked = " + mUserManager.isUserUnlocked());
+ }
+
// TODO remove this method upon imsiKeyRetryDownloadOnPhoneUnlock enabled.
private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@Override
@@ -298,11 +324,16 @@
if (downloadStartedSuccessfully) {
unregisterDefaultNetworkCb(slotIndex);
} else {
- // If download fails due to the device lock, we will reattempt once the
- // device is unlocked.
- mIsRequiredToHandleUnlock = mKeyguardManager.isDeviceLocked();
+ // If download fails due to the device user lock, we will reattempt once
+ // the device is unlocked.
+ if (Flags.ignoreCarrieridResetForSimRemoval()) {
+ mIsRequiredToHandleUnlock = !mUserManager.isUserUnlocked();
+ } else {
+ mIsRequiredToHandleUnlock = mKeyguardManager.isDeviceLocked();
+ }
+
loge("hasActiveDataConnection = " + hasActiveDataNetwork
- + " isDeviceLocked = " + mIsRequiredToHandleUnlock);
+ + " isDeviceUserLocked = " + mIsRequiredToHandleUnlock);
if (!hasActiveDataNetwork) {
registerDefaultNetworkCb(slotIndex);
}
@@ -529,14 +560,19 @@
carrierKeyDownloadIdentifier);
}
parseJsonAndPersistKey(jsonStr, mccMnc, carrierId);
+ logd("Completed downloading keys");
} catch (Exception e) {
loge( "Error in download:" + carrierKeyDownloadIdentifier
+ ". " + e);
} finally {
mDownloadManager.remove(carrierKeyDownloadIdentifier);
}
+ } else {
+ loge("Download Failed reason = " + cursor.getInt(columnIndex)
+ + "Failed Status reason" + cursor.getInt(
+ cursor.getColumnIndex(DownloadManager.COLUMN_REASON)));
+ printDeviceLockStatus();
}
- logd("Completed downloading keys");
}
cursor.close();
}
@@ -787,6 +823,7 @@
} catch (Exception e) {
loge( "exception trying to download key from url: " + mURL + ", Exception = "
+ e.getMessage());
+ printDeviceLockStatus();
return false;
}
return true;
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index 67be1b6..6326d6c 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -31,6 +31,7 @@
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -45,6 +46,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
@@ -66,7 +68,7 @@
import android.util.Pair;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.telephony.Rlog;
@@ -78,7 +80,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -93,6 +94,7 @@
* Registered Telephony entities will receive notifications when the UIDs with these privileges
* change.
*/
+@SuppressLint("MissingPermission")
public class CarrierPrivilegesTracker extends Handler {
private static final String TAG = CarrierPrivilegesTracker.class.getSimpleName();
@@ -176,6 +178,8 @@
private static final int ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE = 11;
private final Context mContext;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
private final Phone mPhone;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
@@ -195,7 +199,7 @@
@Nullable private List<UiccAccessRule> mTestOverrideRules = null;
@Nullable private String mTestOverrideCarrierServicePackage = null;
// Map of PackageName -> Certificate hashes for that Package
- @NonNull private final Map<String, Set<String>> mInstalledPackageCerts = new ArrayMap<>();
+ @NonNull private final Map<String, Set<Integer>> mInstalledPackageCertHashes = new ArrayMap<>();
// Map of PackageName -> UIDs for that Package
@NonNull private final Map<String, Set<Integer>> mCachedUids = new ArrayMap<>();
@@ -223,6 +227,8 @@
"mPrivilegedPackageInfoLock.writeLock()"})
private boolean mSimIsReadyButNotLoaded = false;
+ private volatile Handler mCurrentHandler;
+
/** Small snapshot to hold package names and UIDs of privileged packages. */
private static final class PrivilegedPackageInfo {
@NonNull final Set<String> mPackageNames;
@@ -297,7 +303,9 @@
return;
}
- sendMessage(obtainMessage(ACTION_SIM_STATE_UPDATED, slotId, simState));
+ mCurrentHandler.sendMessage(
+ mCurrentHandler.obtainMessage(
+ ACTION_SIM_STATE_UPDATED, slotId, simState));
break;
}
case Intent.ACTION_PACKAGE_ADDED: // fall through
@@ -316,7 +324,7 @@
boolean notExist = false;
try {
disabledByUser = action.equals(Intent.ACTION_PACKAGE_CHANGED)
- && mPackageManager.getApplicationEnabledSetting(pkgName)
+ && getApplicationEnabledSetting(pkgName)
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
} catch (IllegalArgumentException iae) {
// Very rare case when package changed race with package removed
@@ -329,7 +337,8 @@
? ACTION_PACKAGE_REMOVED_OR_DISABLED_BY_USER
: ACTION_PACKAGE_ADDED_REPLACED_OR_CHANGED;
- sendMessage(obtainMessage(what, pkgName));
+ mCurrentHandler.sendMessage(
+ mCurrentHandler.obtainMessage(what, pkgName));
break;
}
}
@@ -337,27 +346,87 @@
};
public CarrierPrivilegesTracker(
- @NonNull Looper looper, @NonNull Phone phone, @NonNull Context context) {
+ @NonNull Looper looper, @NonNull Phone phone,
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
super(looper);
- mContext = context;
mPhone = phone;
+ mContext = context;
+ mFeatureFlags = featureFlags;
mPackageManager = mContext.getPackageManager();
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mCarrierConfigManager =
(CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
// Callback is executed in handler thread and directly handles carrier config update
- mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
- (slotIndex, subId, carrierId, specificCarrierId) -> handleCarrierConfigUpdated(
- subId, slotIndex));
+ if (mCarrierConfigManager != null) {
+ mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) -> handleCarrierConfigUpdated(
+ subId, slotIndex));
+ }
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyRegistryManager =
(TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+ if (mFeatureFlags.asyncInitCarrierPrivilegesTracker()) {
+ final Object localLock = new Object();
+ HandlerThread initializerThread =
+ new HandlerThread("CarrierPrivilegesTracker Initializer") {
+ @Override
+ protected void onLooperPrepared() {
+ synchronized (localLock) {
+ localLock.notifyAll();
+ }
+ }
+ };
+ synchronized (localLock) {
+ initializerThread.start();
+ while (true) {
+ try {
+ localLock.wait();
+ break;
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ mCurrentHandler = new Handler(initializerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case ACTION_INITIALIZE_TRACKER:
+ handleInitializeTracker();
+ if (!hasMessagesOrCallbacks()) {
+ mCurrentHandler = CarrierPrivilegesTracker.this;
+ initializerThread.quitSafely();
+ }
+ break;
+ default:
+ Message m = CarrierPrivilegesTracker.this.obtainMessage();
+ m.copyFrom(msg);
+ m.sendToTarget();
+ if (!hasMessagesOrCallbacks()) {
+ mCurrentHandler = CarrierPrivilegesTracker.this;
+ initializerThread.quitSafely();
+ }
+ break;
+ }
+ }
+ };
+ } else {
+ mCurrentHandler = this;
+ }
+
+ mCurrentHandler.sendMessage(obtainMessage(ACTION_INITIALIZE_TRACKER));
+
IntentFilter certFilter = new IntentFilter();
certFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
certFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
- mContext.registerReceiver(mIntentReceiver, certFilter);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ mContext.registerReceiverAsUser(
+ mIntentReceiver, UserHandle.of(ActivityManager.getCurrentUser()), certFilter,
+ /* broadcastPermission= */ null, /* scheduler= */ null);
+ } else {
+ mContext.registerReceiver(mIntentReceiver, certFilter);
+ }
IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -368,9 +437,14 @@
// For package-related broadcasts, specify the data scheme for "package" to receive the
// package name along with the broadcast
packageFilter.addDataScheme("package");
- mContext.registerReceiver(mIntentReceiver, packageFilter);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ mContext.registerReceiverAsUser(
+ mIntentReceiver, UserHandle.of(ActivityManager.getCurrentUser()), packageFilter,
+ /* broadcastPermission= */ null, /* scheduler= */ null);
+ } else {
+ mContext.registerReceiver(mIntentReceiver, packageFilter);
+ }
- sendMessage(obtainMessage(ACTION_INITIALIZE_TRACKER));
}
@Override
@@ -444,7 +518,8 @@
CarrierConfigManager.getCarrierConfigSubset(
mContext, subId, KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
// CarrierConfigManager#isConfigForIdentifiedCarrier can handle null or empty bundle
- if (!mCarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
+ if (mCarrierConfigManager == null
+ || !mCarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
return Collections.EMPTY_LIST;
}
@@ -477,7 +552,7 @@
&& mClearUiccRulesUptimeMillis == CLEAR_UICC_RULE_NOT_SCHEDULED) {
mClearUiccRulesUptimeMillis =
SystemClock.uptimeMillis() + CLEAR_UICC_RULES_DELAY_MILLIS;
- sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
+ mCurrentHandler.sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
mClearUiccRulesUptimeMillis);
mLocalLog.log("SIM is gone, simState=" + TelephonyManager.simStateToString(simState)
+ ". Delay " + TimeUnit.MILLISECONDS.toSeconds(
@@ -534,18 +609,29 @@
return uiccProfile.getCarrierPrivilegeAccessRules();
}
- private void handlePackageAddedReplacedOrChanged(@Nullable String pkgName) {
- if (pkgName == null) return;
+ private PackageInfo getPackageInfoForPackage(@Nullable String pkgName) {
+ if (pkgName == null) return null;
PackageInfo pkg;
try {
- pkg = mPackageManager.getPackageInfo(pkgName, INSTALLED_PACKAGES_QUERY_FLAGS);
+ return mFeatureFlags.supportCarrierServicesForHsum()
+ ? mPackageManager.getPackageInfoAsUser(
+ pkgName,
+ INSTALLED_PACKAGES_QUERY_FLAGS,
+ ActivityManager.getCurrentUser())
+ : mPackageManager.getPackageInfo(
+ pkgName, INSTALLED_PACKAGES_QUERY_FLAGS);
} catch (NameNotFoundException e) {
Rlog.e(TAG, "Error getting installed package: " + pkgName, e);
- return;
+ return null;
}
+ }
- updateCertsForPackage(pkg);
+ private void handlePackageAddedReplacedOrChanged(@Nullable String pkgName) {
+ PackageInfo pkg = getPackageInfoForPackage(pkgName);
+ if (pkg == null) return;
+
+ updateCertHashHashesForPackage(pkg);
// Invalidate cache because this may be a package already on the device but getting
// installed for a user it wasn't installed in before, which means there will be an
// additional UID.
@@ -553,30 +639,46 @@
if (VDBG) {
Rlog.d(TAG, "Package added/replaced/changed:"
+ " pkg=" + Rlog.pii(TAG, pkgName)
- + " cert hashes=" + mInstalledPackageCerts.get(pkgName));
+ + " cert hashes=" + mInstalledPackageCertHashes.get(pkgName));
}
maybeUpdatePrivilegedPackagesAndNotifyRegistrants();
}
- private void updateCertsForPackage(@NonNull PackageInfo pkg) {
- Set<String> certs = new ArraySet<>(1);
+ private void updateCertHashHashesForPackage(@NonNull PackageInfo pkg) {
+ Set<Integer> certs = new ArraySet<>(2);
List<Signature> signatures = UiccAccessRule.getSignatures(pkg);
for (Signature signature : signatures) {
byte[] sha1 = UiccAccessRule.getCertHash(signature, SHA_1);
- certs.add(IccUtils.bytesToHexString(sha1).toUpperCase(Locale.ROOT));
+ certs.add(UiccAccessRule.getCertificateHashHashCode(sha1));
byte[] sha256 = UiccAccessRule.getCertHash(signature, SHA_256);
- certs.add(IccUtils.bytesToHexString(sha256).toUpperCase(Locale.ROOT));
+ certs.add(UiccAccessRule.getCertificateHashHashCode(sha256));
}
- mInstalledPackageCerts.put(pkg.packageName, certs);
+ mInstalledPackageCertHashes.put(pkg.packageName, certs);
+ }
+
+ private Set<byte[]> getCertsForPackage(@NonNull String pkgName) {
+ PackageInfo pkg = getPackageInfoForPackage(pkgName);
+ if (pkg == null) return Collections.emptySet();
+
+ List<Signature> signatures = UiccAccessRule.getSignatures(pkg);
+
+ ArraySet<byte[]> certs = new ArraySet<>(2);
+ for (Signature signature : signatures) {
+ certs.add(UiccAccessRule.getCertHash(signature, SHA_1));
+ certs.add(UiccAccessRule.getCertHash(signature, SHA_256));
+ }
+
+ return certs;
}
private void handlePackageRemovedOrDisabledByUser(@Nullable String pkgName) {
if (pkgName == null) return;
- if (mInstalledPackageCerts.remove(pkgName) == null || mCachedUids.remove(pkgName) == null) {
+ if (mInstalledPackageCertHashes.remove(pkgName) == null
+ || mCachedUids.remove(pkgName) == null) {
Rlog.e(TAG, "Unknown package was uninstalled or disabled by user: " + pkgName);
return;
}
@@ -608,7 +710,7 @@
msg +=
" installed pkgs="
+ getObfuscatedPackages(
- mInstalledPackageCerts.entrySet(),
+ mInstalledPackageCertHashes.entrySet(),
e -> "pkg(" + Rlog.pii(TAG, e.getKey()) + ")=" + e.getValue());
}
mLocalLog.log(msg);
@@ -617,9 +719,12 @@
private void refreshInstalledPackageCache() {
List<PackageInfo> installedPackages =
mPackageManager.getInstalledPackagesAsUser(
- INSTALLED_PACKAGES_QUERY_FLAGS, UserHandle.SYSTEM.getIdentifier());
+ INSTALLED_PACKAGES_QUERY_FLAGS,
+ mFeatureFlags.supportCarrierServicesForHsum()
+ ? ActivityManager.getCurrentUser()
+ : UserHandle.SYSTEM.getIdentifier());
for (PackageInfo pkg : installedPackages) {
- updateCertsForPackage(pkg);
+ updateCertHashHashesForPackage(pkg);
// This may be unnecessary before initialization, but invalidate the cache all the time
// just in case to ensure consistency.
getUidsForPackage(pkg.packageName, /* invalidateCache= */ true);
@@ -708,8 +813,12 @@
Set<String> carrierServiceEligiblePackages = new ArraySet<>();
Set<String> privilegedPackageNames = new ArraySet<>();
Set<Integer> privilegedUids = new ArraySet<>();
- for (Map.Entry<String, Set<String>> e : mInstalledPackageCerts.entrySet()) {
- final int priv = getPackagePrivilegedStatus(e.getKey(), e.getValue());
+ for (Map.Entry<String, Set<Integer>> e : mInstalledPackageCertHashes.entrySet()) {
+ if (!isPackageMaybePrivileged(e.getKey(), e.getValue())) continue;
+
+ Set<byte[]> fullCerts = getCertsForPackage(e.getKey());
+
+ final int priv = getPackagePrivilegedStatus(e.getKey(), fullCerts);
switch (priv) {
case PACKAGE_PRIVILEGED_FROM_SIM:
case PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE: // fallthrough
@@ -728,32 +837,58 @@
getCarrierService(carrierServiceEligiblePackages));
}
+ private boolean isPackageMaybePrivileged(
+ @NonNull String pkgName, @NonNull Set<Integer> hashHashes) {
+ for (Integer hashHash : hashHashes) {
+ // Non-null (whether empty or not) test override rule will ignore the UICC and CC rules
+ if (mTestOverrideRules != null) {
+ for (UiccAccessRule rule : mTestOverrideRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ } else {
+ for (UiccAccessRule rule : mUiccRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ for (UiccAccessRule rule : mCarrierConfigRules) {
+ if (rule.hasMatchingCertificateHashHashAndPackageName(hashHash, pkgName)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Returns the privilege status of the provided package.
*
* <p>Returned privilege status depends on whether a package matches the certificates from
* carrier config, from test overrides or from certificates stored on the SIM.
*/
- private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<String> certs) {
+ private int getPackagePrivilegedStatus(@NonNull String pkgName, @NonNull Set<byte[]> certs) {
// Double-nested for loops, but each collection should contain at most 2 elements in nearly
// every case.
// TODO(b/184382310) find a way to speed this up
- for (String cert : certs) {
+ for (byte[] cert : certs) {
// Non-null (whether empty or not) test override rule will ignore the UICC and CC rules
if (mTestOverrideRules != null) {
for (UiccAccessRule rule : mTestOverrideRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return PACKAGE_PRIVILEGED_FROM_SIM;
}
}
} else {
for (UiccAccessRule rule : mUiccRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return PACKAGE_PRIVILEGED_FROM_SIM;
}
}
for (UiccAccessRule rule : mCarrierConfigRules) {
- if (rule.matches(cert, pkgName)) {
+ if (rule.hasMatchingCertificateHashAndPackageName(cert, pkgName)) {
return pkgName.equals(mTestOverrideCarrierServicePackage)
? PACKAGE_PRIVILEGED_FROM_CARRIER_SERVICE_TEST_OVERRIDE
: PACKAGE_PRIVILEGED_FROM_CARRIER_CONFIG;
@@ -791,7 +926,9 @@
private int getPackageUid(@Nullable String pkgName) {
int uid = Process.INVALID_UID;
try {
- uid = mPackageManager.getPackageUid(pkgName, /* flags= */0);
+ uid = mFeatureFlags.supportCarrierServicesForHsum()
+ ? mPackageManager.getPackageUidAsUser(pkgName, ActivityManager.getCurrentUser())
+ : mPackageManager.getPackageUid(pkgName, /* flags= */0);
} catch (NameNotFoundException e) {
Rlog.e(TAG, "Unable to find uid for package " + pkgName);
}
@@ -822,7 +959,7 @@
pw.println(
"CarrierPrivilegesTracker - Obfuscated Pkgs + Certs: "
+ getObfuscatedPackages(
- mInstalledPackageCerts.entrySet(),
+ mInstalledPackageCertHashes.entrySet(),
e -> "pkg(" + Rlog.pii(TAG, e.getKey()) + ")=" + e.getValue()));
}
pw.println("mClearUiccRulesUptimeMillis: " + mClearUiccRulesUptimeMillis);
@@ -838,7 +975,8 @@
* @see TelephonyManager#setCarrierTestOverride
*/
public void setTestOverrideCarrierPrivilegeRules(@Nullable String carrierPrivilegeRules) {
- sendMessage(obtainMessage(ACTION_SET_TEST_OVERRIDE_RULE, carrierPrivilegeRules));
+ mCurrentHandler.sendMessage(
+ obtainMessage(ACTION_SET_TEST_OVERRIDE_RULE, carrierPrivilegeRules));
}
/**
@@ -854,7 +992,7 @@
* @see TelephonyManager#setCarrierServicePackageOverride
*/
public void setTestOverrideCarrierServicePackage(@Nullable String carrierServicePackage) {
- sendMessage(obtainMessage(
+ mCurrentHandler.sendMessage(obtainMessage(
ACTION_SET_TEST_OVERRIDE_CARRIER_SERVICE_PACKAGE, carrierServicePackage));
}
@@ -991,10 +1129,25 @@
// Do the PackageManager queries before we take the lock, as these are the longest-running
// pieces of this method and don't depend on the set of carrier apps.
List<ResolveInfo> resolveInfos = new ArrayList<>();
- resolveInfos.addAll(mPackageManager.queryBroadcastReceivers(intent, 0));
- resolveInfos.addAll(mPackageManager.queryIntentActivities(intent, 0));
- resolveInfos.addAll(mPackageManager.queryIntentServices(intent, 0));
- resolveInfos.addAll(mPackageManager.queryIntentContentProviders(intent, 0));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ resolveInfos.addAll(
+ mPackageManager.queryBroadcastReceiversAsUser(
+ intent, /* flags= */ 0, ActivityManager.getCurrentUser()));
+ resolveInfos.addAll(
+ mPackageManager.queryIntentActivitiesAsUser(
+ intent, /* flags= */ 0, ActivityManager.getCurrentUser()));
+ resolveInfos.addAll(
+ mPackageManager.queryIntentServicesAsUser(
+ intent, /* flags= */ 0, ActivityManager.getCurrentUser()));
+ resolveInfos.addAll(
+ mPackageManager.queryIntentContentProvidersAsUser(
+ intent, /* flags= */ 0, ActivityManager.getCurrentUser()));
+ } else {
+ resolveInfos.addAll(mPackageManager.queryBroadcastReceivers(intent, 0));
+ resolveInfos.addAll(mPackageManager.queryIntentActivities(intent, 0));
+ resolveInfos.addAll(mPackageManager.queryIntentServices(intent, 0));
+ resolveInfos.addAll(mPackageManager.queryIntentContentProviders(intent, 0));
+ }
// Now actually check which of the resolved packages have carrier privileges.
mPrivilegedPackageInfoLock.readLock().lock();
@@ -1028,8 +1181,15 @@
@NonNull
private Pair<String, Integer> getCarrierService(@NonNull Set<String> simPrivilegedPackages) {
- List<ResolveInfo> carrierServiceResolveInfos = mPackageManager.queryIntentServices(
- new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), /* flags= */ 0);
+ List<ResolveInfo> carrierServiceResolveInfos =
+ mFeatureFlags.supportCarrierServicesForHsum()
+ ? mPackageManager.queryIntentServicesAsUser(
+ new Intent(CarrierService.CARRIER_SERVICE_INTERFACE),
+ /* flags= */ 0,
+ ActivityManager.getCurrentUser())
+ : mPackageManager.queryIntentServices(
+ new Intent(CarrierService.CARRIER_SERVICE_INTERFACE),
+ /* flags= */ 0);
String carrierServicePackageName = null;
for (ResolveInfo resolveInfo : carrierServiceResolveInfos) {
String packageName = getPackageName(resolveInfo);
@@ -1047,4 +1207,16 @@
? new Pair<>(null, Process.INVALID_UID)
: new Pair<>(carrierServicePackageName, getPackageUid(carrierServicePackageName));
}
+
+ private @PackageManager.EnabledState int getApplicationEnabledSetting(
+ @NonNull String packageName) {
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ return mContext.createContextAsUser(
+ UserHandle.of(ActivityManager.getCurrentUser()), /* flags= */ 0)
+ .getPackageManager()
+ .getApplicationEnabledSetting(packageName);
+ } else {
+ return mPackageManager.getApplicationEnabledSetting(packageName);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/CarrierResolver.java b/src/java/com/android/internal/telephony/CarrierResolver.java
index 8a9b3e3..829bf6c 100644
--- a/src/java/com/android/internal/telephony/CarrierResolver.java
+++ b/src/java/com/android/internal/telephony/CarrierResolver.java
@@ -30,6 +30,7 @@
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
+import android.os.UserHandle;
import android.provider.Telephony;
import android.service.carrier.CarrierIdentifier;
import android.telephony.CarrierConfigManager;
@@ -41,6 +42,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.CarrierIdMatchStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
@@ -112,6 +114,9 @@
private final LocalLog mCarrierIdLocalLog = new LocalLog(16);
private final TelephonyManager mTelephonyMgr;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
private final ContentObserver mContentObserver = new ContentObserver(this) {
@Override
public void onChange(boolean selfChange, Uri uri) {
@@ -172,9 +177,10 @@
}
};
- public CarrierResolver(Phone phone) {
+ public CarrierResolver(Phone phone, @NonNull FeatureFlags flags) {
logd("Creating CarrierResolver[" + phone.getPhoneId() + "]");
mContext = phone.getContext();
+ mFeatureFlags = flags;
mPhone = phone;
mTelephonyMgr = TelephonyManager.from(mContext);
@@ -500,7 +506,11 @@
intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, mSpecificCarrierId);
intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_NAME, mSpecificCarrierName);
intent.putExtra(TelephonyManager.EXTRA_SUBSCRIPTION_ID, mPhone.getSubId());
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
// notify content observers for specific carrier id change event.
ContentValues cv = new ContentValues();
@@ -535,7 +545,11 @@
intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, mCarrierId);
intent.putExtra(TelephonyManager.EXTRA_CARRIER_NAME, mCarrierName);
intent.putExtra(TelephonyManager.EXTRA_SUBSCRIPTION_ID, mPhone.getSubId());
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
// notify content observers for carrier id change event
ContentValues cv = new ContentValues();
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 960d794..4f9d84d 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -45,6 +46,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
import java.io.FileDescriptor;
@@ -160,7 +162,11 @@
};
public CarrierServiceBindHelper(Context context) {
- mContext = context.createContextAsUser(Process.myUserHandle(), 0);
+ mContext =
+ context.createContextAsUser(
+ Flags.supportCarrierServicesForHsum()
+ ? UserHandle.of(ActivityManager.getCurrentUser())
+ : Process.myUserHandle(), 0);
updateBindingsAndSimStates();
@@ -171,7 +177,7 @@
context, mHandler.getLooper(), UserHandle.ALL);
try {
Context contextAsUser = mContext.createPackageContextAsUser(mContext.getPackageName(),
- 0, UserHandle.SYSTEM);
+ 0, Flags.supportCarrierServicesForHsum() ? UserHandle.CURRENT : UserHandle.SYSTEM);
contextAsUser.registerReceiver(mUserUnlockedReceiver,
new IntentFilter(Intent.ACTION_USER_UNLOCKED), null /* broadcastPermission */,
mHandler);
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index 6b99b56..b470e2e 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -75,7 +75,8 @@
@VisibleForTesting
- public static final String ACTION_NEVER_ASK_AGAIN = "SilenceNoWifiEmrgCallingNotification";
+ public static final String ACTION_NEVER_ASK_AGAIN =
+ "com.android.internal.telephony.action.SILENCE_WIFI_CALLING_NOTIFICATION";
public final NotificationActionReceiver mActionReceiver = new NotificationActionReceiver();
@VisibleForTesting
@@ -116,7 +117,8 @@
mTelephonyManager = mPhone.getContext().getSystemService(
TelephonyManager.class).createForSubscriptionId(mPhone.getSubId());
CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
- ccm.registerCarrierConfigChangeListener(
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(
mPhone.getContext().getMainExecutor(),
(slotIndex, subId, carrierId, specificCarrierId) -> {
if (slotIndex != mPhone.getPhoneId()) return;
@@ -143,6 +145,7 @@
}
handleConfigChanges();
});
+ }
// Listen for subscriber changes
SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener(
@@ -731,6 +734,7 @@
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_NEVER_ASK_AGAIN)) {
Rlog.i(LOG_TAG, "NotificationActionReceiver: ACTION_NEVER_ASK_AGAIN");
+ dismissEmergencyCallingNotification();
// insert a key to silence future notifications
SharedPreferences.Editor editor =
PreferenceManager.getDefaultSharedPreferences(context).edit();
@@ -741,5 +745,22 @@
context.unregisterReceiver(mActionReceiver);
}
}
+
+ /**
+ * Dismiss the notification when the "Do Not Ask Again" button is clicked
+ */
+ private void dismissEmergencyCallingNotification() {
+ if (!mFeatureFlags.stopSpammingEmergencyNotification()) {
+ return;
+ }
+ try {
+ NotificationType t = mNotificationTypeMap.get(NOTIFICATION_EMERGENCY_NETWORK);
+ if (t != null) {
+ cancelNotification(t);
+ }
+ } catch (Exception e) {
+ Rlog.e(LOG_TAG, "dismissEmergencyCallingNotification", e);
+ }
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/CarrierSignalAgent.java b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
index 3250cef..2abe643 100644
--- a/src/java/com/android/internal/telephony/CarrierSignalAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
@@ -130,13 +130,15 @@
CarrierConfigManager carrierConfigManager = mPhone.getContext().getSystemService(
CarrierConfigManager.class);
loadCarrierConfig();
- carrierConfigManager.registerCarrierConfigChangeListener(
- mPhone.getContext().getMainExecutor(),
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex == mPhone.getPhoneId()) {
- loadCarrierConfig();
- }
- });
+ if (carrierConfigManager != null) {
+ carrierConfigManager.registerCarrierConfigChangeListener(
+ mPhone.getContext().getMainExecutor(),
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex == mPhone.getPhoneId()) {
+ loadCarrierConfig();
+ }
+ });
+ }
mPhone.getCarrierActionAgent().registerForCarrierAction(
CarrierActionAgent.CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS, this,
EVENT_REGISTER_DEFAULT_NETWORK_AVAIL, null, false);
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 82b4c2b8e..7a1c8fe 100644
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -692,8 +692,18 @@
&& mEmergencyNumberInfo.getEmergencyCallRouting()
!= EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY) {
int eccCategory = dialArgs.intentExtras.getInt(
- PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
- mEmergencyNumberInfo.getEmergencyServiceCategoryBitmask());
+ PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ mEmergencyNumberInfo.getEmergencyServiceCategoryBitmask());
+ // According to 3gpp 23.167 section 7.1.2, when CS domain is selected,
+ // emergency routing is performed only if the emergency category is provided.
+ if (this instanceof GsmCdmaConnection
+ && dialArgs.intentExtras.getInt(
+ PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED)
+ == EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED) {
+ Rlog.d(TAG, "setEmergencyCallInfo: specific eccCategory is required");
+ return;
+ }
Rlog.d(TAG, "setEmergencyCallInfo: enforce emergency routing eccCategory="
+ eccCategory);
List<String> emergencyUrns = dialArgs.intentExtras.getStringArrayList(
@@ -706,13 +716,32 @@
mEmergencyNumberInfo.getMnc(),
eccCategory,
emergencyUrns,
- mEmergencyNumberInfo.getEmergencyNumberSourceBitmask(),
+ getEmergencyNumberSourceForEmergencyRouting(),
EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
}
}
}
/**
+ * Get the emergency number source to be used for emergency routing calls.
+ * This is not getting actual source, instead its forcing the source to
+ * EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING.
+ * Even when the source is EMERGENCY_NUMBER_SOURCE_DATABASE,
+ * to allow the category information delivered by the network to be used,
+ * the source is set to EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING.
+ */
+ private int getEmergencyNumberSourceForEmergencyRouting() {
+ int source = mEmergencyNumberInfo.getEmergencyNumberSourceBitmask();
+ Rlog.d(TAG, "getEmergencyNumberSourceForEmergencyRouting: source=" + source);
+
+ if (source != EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST) {
+ source = EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING;
+ }
+
+ return source;
+ }
+
+ /**
* Set the non-detectable emergency number information.
*/
public void setNonDetectableEmergencyCallInfo(int eccCategory,
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 9c7993b..47c701c 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -135,13 +135,9 @@
int subId = sender.getSubId();
- if (mFeatureFlags.notifyDataActivityChangedWithSlot()) {
- int phoneId = sender.getPhoneId();
- mTelephonyRegistryMgr.notifyDataActivityChanged(phoneId, subId,
- sender.getDataActivityState());
- } else {
- mTelephonyRegistryMgr.notifyDataActivityChanged(subId, sender.getDataActivityState());
- }
+ int phoneId = sender.getPhoneId();
+ mTelephonyRegistryMgr.notifyDataActivityChanged(phoneId, subId,
+ sender.getDataActivityState());
}
@Override
@@ -307,14 +303,28 @@
}
@Override
- public void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type) {
- mTelephonyRegistryMgr.notifyCallBackModeStarted(sender.getPhoneId(),
- sender.getSubId(), type);
+ public void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ mTelephonyRegistryMgr.notifyCallbackModeStarted(sender.getPhoneId(),
+ sender.getSubId(), type, durationMillis);
+ }
+
+ @Override
+ public void notifyCallbackModeRestarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ mTelephonyRegistryMgr.notifyCallbackModeRestarted(sender.getPhoneId(),
+ sender.getSubId(), type, durationMillis);
}
@Override
public void notifyCallbackModeStopped(Phone sender, @EmergencyCallbackModeType int type,
@EmergencyCallbackModeStopReason int reason) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
mTelephonyRegistryMgr.notifyCallbackModeStopped(sender.getPhoneId(),
sender.getSubId(), type, reason);
}
@@ -324,6 +334,12 @@
mTelephonyRegistryMgr.notifyCarrierRoamingNtnModeChanged(sender.getSubId(), active);
}
+ @Override
+ public void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnEligibleStateChanged(
+ sender.getSubId(), eligible);
+ }
+
/**
* Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
* for the public API.
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index 7bdf2ff..f572bf8 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -102,6 +102,7 @@
private final RegistrantList mPhysicalChannelConfigRegistrants = new RegistrantList();
private final RegistrantList mSignalStrengthReportDecisionCallbackRegistrants =
new RegistrantList();
+ private final RegistrantList mScreenStateRegistrants = new RegistrantList();
private final NetworkRequest mWifiNetworkRequest =
new NetworkRequest.Builder()
@@ -217,7 +218,13 @@
public void onDisplayAdded(int displayId) { }
@Override
- public void onDisplayRemoved(int displayId) { }
+ public void onDisplayRemoved(int displayId) {
+ /* adapter for virtual display removed */
+ boolean screenOn = isScreenOn();
+ Message msg = obtainMessage(EVENT_SCREEN_STATE_CHANGED);
+ msg.arg1 = screenOn ? 1 : 0;
+ sendMessage(msg);
+ }
@Override
public void onDisplayChanged(int displayId) {
@@ -509,6 +516,7 @@
private void onUpdateDeviceState(int eventType, boolean state) {
final boolean shouldEnableBarringInfoReportsOld = shouldEnableBarringInfoReports();
final boolean wasHighPowerEnabled = shouldEnableHighPowerConsumptionIndications();
+ boolean wasScreenOn = mIsScreenOn;
switch (eventType) {
case EVENT_SCREEN_STATE_CHANGED:
if (mIsScreenOn == state) return;
@@ -618,6 +626,13 @@
mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(false);
}
}
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ // Determine whether to notify registrants about the screen on, off state change.
+ if (wasScreenOn != mIsScreenOn) {
+ mScreenStateRegistrants.notifyResult(mIsScreenOn);
+ }
+ }
}
/**
@@ -809,6 +824,37 @@
}
/**
+ * Unregister for Screen on, off notifications changed.
+ * @param h Handler to notify
+ */
+ public void unregisterForScreenStateChanged(Handler h) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "unregisterForScreenStateChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ mScreenStateRegistrants.remove(h);
+ }
+
+ /**
+ * Register a callback to receive the screen on or off.
+ * @param h Handler to notify
+ * @param what msg.what when the message is delivered
+ * @param obj AsyncResult.userObj when the message is delivered
+ */
+ public void registerForScreenStateChanged(Handler h, int what, Object obj) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "registerForScreenStateChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+ Registrant r = new Registrant(h, what, obj);
+ mScreenStateRegistrants.add(r);
+
+ // Initial notification
+ mScreenStateRegistrants.notifyResult(mIsScreenOn);
+ }
+
+ /**
* Register a callback to decide whether signal strength should be notified or not.
* @param h Handler to notify
*/
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index e8a0566..d3f0264 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -87,23 +87,26 @@
mLogTag = "DIC-" + mPhone.getPhoneId();
mServiceState = mPhone.getServiceStateTracker().getServiceState();
mConfigs = new PersistableBundle();
+ CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
try {
- mConfigs = mPhone.getContext().getSystemService(CarrierConfigManager.class)
- .getConfigForSubId(mPhone.getSubId(),
- CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
+ if (ccm != null) {
+ mConfigs = ccm.getConfigForSubId(mPhone.getSubId(),
+ CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
+ }
} catch (Exception ignored) {
// CarrierConfigLoader might not be available yet.
// Once it's available, configs will be updated through the listener.
}
mPhone.getServiceStateTracker()
.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
- mPhone.getContext().getSystemService(CarrierConfigManager.class)
- .registerCarrierConfigChangeListener(Runnable::run,
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex == mPhone.getPhoneId()) {
- obtainMessage(EVENT_CARRIER_CONFIG_CHANGED).sendToTarget();
- }
- });
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(Runnable::run,
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex == mPhone.getPhoneId()) {
+ obtainMessage(EVENT_CARRIER_CONFIG_CHANGED).sendToTarget();
+ }
+ });
+ }
mTelephonyDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
diff --git a/src/java/com/android/internal/telephony/FdnUtils.java b/src/java/com/android/internal/telephony/FdnUtils.java
index 23cab44..453b3fc 100644
--- a/src/java/com/android/internal/telephony/FdnUtils.java
+++ b/src/java/com/android/internal/telephony/FdnUtils.java
@@ -121,7 +121,8 @@
try {
PhoneNumber phoneNumber = phoneNumberUtil.parse(dialStr, defaultCountryIso);
dialStrE164 = phoneNumberUtil.format(phoneNumber, PhoneNumberFormat.E164);
- dialStrNational = String.valueOf(phoneNumber.getNationalNumber());
+ dialStrNational = String.valueOf(
+ phoneNumberUtil.getNationalSignificantNumber(phoneNumber));
} catch (NumberParseException ignored) {
Rlog.w(LOG_TAG, "isFDN: could not parse dialStr");
dialStr = extractSMSC(dialStr);
diff --git a/src/java/com/android/internal/telephony/GbaManager.java b/src/java/com/android/internal/telephony/GbaManager.java
index 7c5f636..047d5d5 100644
--- a/src/java/com/android/internal/telephony/GbaManager.java
+++ b/src/java/com/android/internal/telephony/GbaManager.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +28,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.IBootstrapAuthenticationCallback;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -75,7 +77,8 @@
private Handler mHandler;
private String mServicePackageName;
- private String mServicePackageNameOverride;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_SYSTEM;
private int mReleaseTime;
private int mRetryTimes = 0;
@@ -426,8 +429,9 @@
try {
logv("Trying to bind " + servicePackage);
mServiceConnection = new GbaServiceConnection();
- if (!mContext.bindService(intent, mServiceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE)) {
+ if (!mContext.bindServiceAsUser(intent, mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
+ UserHandle.of(mUserId))) {
logd("Cannot bind to the service.");
retryBind();
return;
@@ -462,12 +466,13 @@
}
/** override GBA service package name to be connected */
- public boolean overrideServicePackage(String packageName) {
+ public boolean overrideServicePackage(String packageName, @UserIdInt int userId) {
synchronized (this) {
- if (!TextUtils.equals(mServicePackageName, packageName)) {
+ if (!TextUtils.equals(mServicePackageName, packageName) || userId != mUserId) {
logv("Service package name is changed from " + mServicePackageName
- + " to " + packageName);
+ + " to " + packageName + ", user id from " + mUserId + " to " + userId);
mServicePackageName = packageName;
+ mUserId = userId;
if (!mHandler.hasMessages(EVENT_CONFIG_CHANGED)) {
mHandler.sendEmptyMessage(EVENT_CONFIG_CHANGED);
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 26d4e1b..14bd273 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -509,7 +509,8 @@
obtainCompleteMessage());
}
};
- EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete);
+ EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete,
+ TelephonyManager.STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED);
} else {
mPhone.exitEmergencyCallbackMode();
mPhone.setOnEcbModeExitResponse(this, EVENT_EXIT_ECM_RESPONSE_CDMA, null);
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index cc07047..d96663a 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -30,6 +30,7 @@
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+import android.telephony.emergency.EmergencyNumber;
import android.text.TextUtils;
import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
@@ -186,7 +187,7 @@
mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
if (dialArgs.isEmergency) {
- setEmergencyCallInfo(mOwner, null);
+ setEmergencyCallInfo(mOwner, dialArgs);
// There was no emergency number info found for this call, however it is
// still marked as an emergency number. This may happen if it was a redialed
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 93a0c2f..2e1a89f 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -390,8 +390,9 @@
.makeDataNetworkController(this, getLooper(), featureFlags);
mCarrierResolver = mTelephonyComponentFactory.inject(CarrierResolver.class.getName())
- .makeCarrierResolver(this);
- mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(Looper.myLooper(), this, context);
+ .makeCarrierResolver(this, featureFlags);
+ mCarrierPrivilegesTracker = new CarrierPrivilegesTracker(
+ Looper.myLooper(), this, context, featureFlags);
getCarrierActionAgent().registerForCarrierAction(
CarrierActionAgent.CARRIER_ACTION_SET_METERED_APNS_ENABLED, this,
@@ -1119,6 +1120,7 @@
@Override
public GsmCdmaCall getForegroundCall() {
+ if (!hasCalling()) return null;
return mCT.mForegroundCall;
}
@@ -1396,6 +1398,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean isInCall() {
+ if (!hasCalling()) return false;
+
GsmCdmaCall.State foregroundCallState = getForegroundCall().getState();
GsmCdmaCall.State backgroundCallState = getBackgroundCall().getState();
GsmCdmaCall.State ringingCallState = getRingingCall().getState();
@@ -5494,7 +5498,16 @@
public void refreshSafetySources(String refreshBroadcastId) {
if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
- mSafetySource.refresh(mContext, refreshBroadcastId);
+ post(() -> mSafetySource.refresh(mContext, refreshBroadcastId));
}
}
+
+ /**
+ * @return The sms dispatchers controller
+ */
+ @Override
+ @Nullable
+ public SmsDispatchersController getSmsDispatchersController() {
+ return mIccSmsInterfaceManager.mDispatchersController;
+ }
}
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 7c1670c..3141406 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -96,7 +96,6 @@
final protected Context mContext;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final protected AppOpsManager mAppOps;
- @VisibleForTesting
public SmsDispatchersController mDispatchersController;
private SmsPermissions mSmsPermissions;
@@ -407,15 +406,15 @@
* A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
* This method checks if the calling package or itself has the permission to send the data sms.
*/
- public void sendDataWithSelfPermissions(String callingPackage, String callingAttributionTag,
- String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
- PendingIntent deliveryIntent, boolean isForVvm) {
+ public void sendDataWithSelfPermissions(String callingPackage, int callingUser,
+ String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data,
+ PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributionTag,
"Sending SMS message")) {
returnUnspecifiedFailure(sentIntent);
return;
}
- sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
+ sendDataInternal(callingPackage, callingUser, destAddr, scAddr, destPort, data, sentIntent,
deliveryIntent, isForVvm);
}
@@ -425,9 +424,9 @@
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
- sendData(callingPackage, null, destAddr, scAddr, destPort, data,
+ public void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+ sendData(callingPackage, callingUser, null, destAddr, scAddr, destPort, data,
sentIntent, deliveryIntent);
}
@@ -435,7 +434,7 @@
* A permissions check before passing to {@link IccSmsInterfaceManager#sendDataInternal}.
* This method checks only if the calling package has the permission to send the data sms.
*/
- public void sendData(String callingPackage, String callingAttributionTag,
+ public void sendData(String callingPackage, int callingUser, String callingAttributionTag,
String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
if (!mSmsPermissions.checkCallingCanSendSms(callingPackage, callingAttributionTag,
@@ -443,7 +442,7 @@
returnUnspecifiedFailure(sentIntent);
return;
}
- sendDataInternal(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
+ sendDataInternal(callingPackage, callingUser, destAddr, scAddr, destPort, data, sentIntent,
deliveryIntent, false /* isForVvm */);
}
@@ -474,17 +473,17 @@
* raw pdu of the status report is in the extended data ("pdu").
*/
- private void sendDataInternal(String callingPackage, String destAddr, String scAddr,
- int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
+ private void sendDataInternal(String callingPackage, int callinUser, String destAddr,
+ String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+ PendingIntent deliveryIntent, boolean isForVvm) {
if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
log("sendData: destAddr=" + destAddr + " scAddr=" + scAddr + " destPort="
+ destPort + " data='" + HexDump.toHexString(data) + "' sentIntent="
+ sentIntent + " deliveryIntent=" + deliveryIntent + " isForVVM=" + isForVvm);
}
destAddr = filterDestAddress(destAddr);
- mDispatchersController.sendData(callingPackage, destAddr, scAddr, destPort, data,
- sentIntent, deliveryIntent, isForVvm);
+ mDispatchersController.sendData(callingPackage, callinUser, destAddr, scAddr,
+ destPort, data, sentIntent, deliveryIntent, isForVvm);
}
/**
@@ -492,12 +491,13 @@
* This method checks only if the calling package has the permission to send the sms.
* Note: SEND_SMS permission should be checked by the caller of this method
*/
- public void sendText(String callingPackage, String destAddr, String scAddr,
+ public void sendText(String callingPackage, int callingUser, String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck) {
- sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
- persistMessageForNonDefaultSmsApp, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
- false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */,
+ sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
+ deliveryIntent, persistMessageForNonDefaultSmsApp,
+ SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,
+ SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */,
messageId, skipShortCodeCheck);
}
@@ -505,27 +505,29 @@
* A permissions check before passing to {@link IccSmsInterfaceManager#sendTextInternal}.
* This method checks if the calling package or itself has the permission to send the sms.
*/
- public void sendTextWithSelfPermissions(String callingPackage, String callingAttributeTag,
- String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, boolean persistMessage, boolean isForVvm) {
+ public void sendTextWithSelfPermissions(String callingPackage, int callingUser,
+ String callingAttributeTag, String destAddr, String scAddr, String text,
+ PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage,
+ boolean isForVvm) {
if (!mSmsPermissions.checkCallingOrSelfCanSendSms(callingPackage, callingAttributeTag,
"Sending SMS message")) {
returnUnspecifiedFailure(sentIntent);
return;
}
- sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
- persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,
- SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm, 0L /* messageId */);
+ sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
+ deliveryIntent, persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
+ false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
+ isForVvm, 0L /* messageId */);
}
- private void sendTextInternal(String callingPackage, String destAddr, String scAddr,
- String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ private void sendTextInternal(String callingPackage, int callingUser, String destAddr,
+ String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
int validityPeriod, boolean isForVvm, long messageId) {
- sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
- persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod, isForVvm,
- messageId, false);
+ sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
+ deliveryIntent, persistMessageForNonDefaultSmsApp, priority, expectMore,
+ validityPeriod, isForVvm, messageId, false);
}
/**
@@ -577,8 +579,8 @@
* @param skipShortCodeCheck Skip check for short code type destination address.
*/
- private void sendTextInternal(String callingPackage, String destAddr, String scAddr,
- String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ private void sendTextInternal(String callingPackage, int callingUser, String destAddr,
+ String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
int validityPeriod, boolean isForVvm, long messageId, boolean skipShortCodeCheck) {
if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
@@ -591,7 +593,7 @@
notifyIfOutgoingEmergencySms(destAddr);
destAddr = filterDestAddress(destAddr);
mDispatchersController.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
- null/*messageUri*/, callingPackage, persistMessageForNonDefaultSmsApp,
+ null/*messageUri*/, callingPackage, callingUser, persistMessageForNonDefaultSmsApp,
priority, expectMore, validityPeriod, isForVvm, messageId, skipShortCodeCheck);
}
@@ -641,18 +643,19 @@
* Any Other values including negative considered as Invalid Validity Period of the message.
*/
- public void sendTextWithOptions(String callingPackage, String callingAttributionTag,
- String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, boolean persistMessageForNonDefaultSmsApp, int priority,
+ public void sendTextWithOptions(String callingPackage, int callingUser,
+ String callingAttributionTag, String destAddr, String scAddr, String text,
+ PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean persistMessageForNonDefaultSmsApp, int priority,
boolean expectMore, int validityPeriod) {
if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp,
callingPackage, callingAttributionTag, "Sending SMS message")) {
returnUnspecifiedFailure(sentIntent);
return;
}
- sendTextInternal(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
- persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod,
- false /* isForVvm */, 0L /* messageId */);
+ sendTextInternal(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
+ deliveryIntent, persistMessageForNonDefaultSmsApp, priority, expectMore,
+ validityPeriod, false /* isForVvm */, 0L /* messageId */);
}
/**
@@ -718,12 +721,12 @@
* Used for logging and diagnostics purposes. The id may be 0.
*/
- public void sendMultipartText(String callingPackage, String callingAttributionTag,
- String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents,
- List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
- long messageId) {
- sendMultipartTextWithOptions(callingPackage, callingAttributionTag, destAddr, scAddr, parts,
- sentIntents, deliveryIntents, persistMessageForNonDefaultSmsApp,
+ public void sendMultipartText(String callingPackage, int callingUser,
+ String callingAttributionTag, String destAddr, String scAddr, List<String> parts,
+ List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
+ boolean persistMessageForNonDefaultSmsApp, long messageId) {
+ sendMultipartTextWithOptions(callingPackage, callingUser, callingAttributionTag, destAddr,
+ scAddr, parts, sentIntents, deliveryIntents, persistMessageForNonDefaultSmsApp,
SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, false /* expectMore */,
SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
messageId);
@@ -778,10 +781,11 @@
* Used for logging and diagnostics purposes. The id may be 0.
*/
- public void sendMultipartTextWithOptions(String callingPackage, String callingAttributionTag,
- String destAddr, String scAddr, List<String> parts, List<PendingIntent> sentIntents,
- List<PendingIntent> deliveryIntents, boolean persistMessageForNonDefaultSmsApp,
- int priority, boolean expectMore, int validityPeriod, long messageId) {
+ public void sendMultipartTextWithOptions(String callingPackage, int callingUser,
+ String callingAttributionTag, String destAddr, String scAddr, List<String> parts,
+ List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
+ boolean persistMessageForNonDefaultSmsApp, int priority, boolean expectMore,
+ int validityPeriod, long messageId) {
if (!mSmsPermissions.checkCallingCanSendText(persistMessageForNonDefaultSmsApp,
callingPackage, callingAttributionTag, "Sending SMS message")) {
returnUnspecifiedFailure(sentIntents);
@@ -821,7 +825,7 @@
}
mDispatchersController.sendText(destAddr, scAddr, singlePart, singleSentIntent,
- singleDeliveryIntent, null /* messageUri */, callingPackage,
+ singleDeliveryIntent, null /* messageUri */, callingPackage, callingUser,
persistMessageForNonDefaultSmsApp, priority, expectMore, validityPeriod,
false /* isForVvm */, messageId);
}
@@ -829,12 +833,12 @@
}
mDispatchersController.sendMultipartText(destAddr,
- scAddr,
- (ArrayList<String>) parts,
- (ArrayList<PendingIntent>) sentIntents,
- (ArrayList<PendingIntent>) deliveryIntents,
- null, callingPackage, persistMessageForNonDefaultSmsApp,
- priority, expectMore, validityPeriod, messageId);
+ scAddr,
+ (ArrayList<String>) parts,
+ (ArrayList<PendingIntent>) sentIntents,
+ (ArrayList<PendingIntent>) deliveryIntents,
+ null, callingPackage, callingUser, persistMessageForNonDefaultSmsApp,
+ priority, expectMore, validityPeriod, messageId);
}
@@ -1292,12 +1296,13 @@
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void sendStoredText(String callingPkg, Uri messageUri, String scAddress,
+ public void sendStoredText(String callingPkg, int callingUser, Uri messageUri, String scAddress,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
- sendStoredText(callingPkg, null, messageUri, scAddress, sentIntent, deliveryIntent);
+ sendStoredText(callingPkg, callingUser, null, messageUri,
+ scAddress, sentIntent, deliveryIntent);
}
- public void sendStoredText(String callingPkg, String callingAttributionTag,
+ public void sendStoredText(String callingPkg, int callingUser, String callingAttributionTag,
Uri messageUri, String scAddress, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag,
@@ -1324,7 +1329,7 @@
notifyIfOutgoingEmergencySms(textAndAddress[1]);
textAndAddress[1] = filterDestAddress(textAndAddress[1]);
mDispatchersController.sendText(textAndAddress[1], scAddress, textAndAddress[0],
- sentIntent, deliveryIntent, messageUri, callingPkg,
+ sentIntent, deliveryIntent, messageUri, callingPkg, callingUser,
true /* persistMessageForNonDefaultSmsApp */, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, false /* isForVvm */,
0L /* messageId */);
@@ -1336,13 +1341,14 @@
*/
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void sendStoredMultipartText(String callingPkg, Uri messageUri, String scAddress,
- List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
- sendStoredMultipartText(callingPkg, null, messageUri, scAddress, sentIntents,
- deliveryIntents);
+ public void sendStoredMultipartText(String callingPkg, int callingUser,
+ Uri messageUri, String scAddress, List<PendingIntent> sentIntents,
+ List<PendingIntent> deliveryIntents) {
+ sendStoredMultipartText(callingPkg, callingUser, null,
+ messageUri, scAddress, sentIntents, deliveryIntents);
}
- public void sendStoredMultipartText(String callingPkg,
+ public void sendStoredMultipartText(String callingPkg, int callingUser,
String callingAttributionTag, Uri messageUri, String scAddress,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
if (!mSmsPermissions.checkCallingCanSendSms(callingPkg, callingAttributionTag,
@@ -1395,7 +1401,7 @@
mDispatchersController.sendText(textAndAddress[1], scAddress, singlePart,
singleSentIntent, singleDeliveryIntent, messageUri, callingPkg,
- true /* persistMessageForNonDefaultSmsApp */,
+ callingUser, true /* persistMessageForNonDefaultSmsApp */,
SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
false /* expectMore */, SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
false /* isForVvm */, 0L /* messageId */);
@@ -1410,7 +1416,7 @@
(ArrayList<PendingIntent>) sentIntents,
(ArrayList<PendingIntent>) deliveryIntents,
messageUri,
- callingPkg,
+ callingPkg, callingUser,
true /* persistMessageForNonDefaultSmsApp */,
SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
false /* expectMore */,
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 1a6bf2b..6955a55 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -202,9 +202,8 @@
tracker.onSent(mContext);
mTrackers.remove(token);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, true,
- tracker.isSinglePartOrLastPart());
+ mSmsDispatchersController.notifySmsSent(tracker, true,
+ tracker.isSinglePartOrLastPart(), true /*success*/);
break;
case ImsSmsImplBase.SEND_STATUS_ERROR:
tracker.onFailed(mContext, reason, networkReasonCode);
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 49d1adc..0106516 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -30,6 +30,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -73,7 +74,10 @@
import com.android.internal.telephony.SmsConstants.MessageClass;
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.internal.telephony.util.TelephonyUtils;
@@ -284,6 +288,8 @@
private List<SmsFilter> mSmsFilters;
+ protected final @NonNull FeatureFlags mFeatureFlags;
+
/**
* Create a new SMS broadcast helper.
* @param name the class name for logging
@@ -291,18 +297,19 @@
* @param storageMonitor the SmsStorageMonitor to check for storage availability
*/
protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
- Phone phone, Looper looper) {
+ Phone phone, Looper looper, FeatureFlags featureFlags) {
super(name, looper);
+ mFeatureFlags = featureFlags;
mContext = context;
mStorageMonitor = storageMonitor;
mPhone = phone;
mResolver = context.getContentResolver();
- mWapPush = new WapPushOverSms(context);
+ mWapPush = new WapPushOverSms(context, mFeatureFlags);
- boolean smsCapable = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_sms_capable);
- mSmsReceiveDisabled = !TelephonyManager.from(mContext).getSmsReceiveCapableForPhone(
+ TelephonyManager telephonyManager = TelephonyManager.from(mContext);
+ boolean smsCapable = telephonyManager.isDeviceSmsCapable();
+ mSmsReceiveDisabled = !telephonyManager.getSmsReceiveCapableForPhone(
mPhone.getPhoneId(), smsCapable);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -681,6 +688,17 @@
result = RESULT_SMS_DISPATCH_FAILURE;
}
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (result == Intents.RESULT_SMS_HANDLED) {
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ if (satelliteController == null) {
+ log("SatelliteController is not initialized");
+ return;
+ }
+ satelliteController.onSmsReceived(mPhone.getSubId());
+ }
+ }
+
// RESULT_OK means that the SMS will be acknowledged by special handling,
// e.g. for SMS-PP data download. Any other result, we should ack here.
if (result != Activity.RESULT_OK) {
@@ -801,7 +819,12 @@
Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
intent.putExtra("result", result);
intent.putExtra("subId", mPhone.getSubId());
- mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.RECEIVE_SMS);
+ } else {
+ mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
+ }
}
acknowledgeLastIncomingSms(success, result, response);
}
@@ -1064,7 +1087,7 @@
SmsBroadcastReceiver resultReceiver = tracker.getSmsBroadcastReceiver(this);
- if (!mUserManager.isUserUnlocked()) {
+ if (!isMainUserUnlocked()) {
log("processMessagePart: !isUserUnlocked; calling processMessagePartWithUserLocked. "
+ "Port: " + destPort, tracker.getMessageId());
return processMessagePartWithUserLocked(
@@ -1182,6 +1205,15 @@
return false;
}
+ private boolean isMainUserUnlocked() {
+ UserHandle mainUser = mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser() ?
+ mUserManager.getMainUser() : null;
+ if (mainUser != null) {
+ return mUserManager.isUserUnlocked(mainUser);
+ }
+ return mUserManager.isUserUnlocked();
+ }
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void showNewMessageNotification() {
// Do not show the notification on non-FBE devices.
@@ -1205,8 +1237,15 @@
.setChannelId(NotificationChannelController.CHANNEL_ID_SMS);
NotificationManager mNotificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- mNotificationManager.notify(
- NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build());
+ UserHandle mainUser = mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser() ?
+ mUserManager.getMainUser() : null;
+ if (mainUser != null) {
+ mNotificationManager.notifyAsUser(
+ NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build(), mainUser);
+ } else {
+ mNotificationManager.notify(
+ NOTIFICATION_TAG, NOTIFICATION_ID_NEW_MESSAGE, mBuilder.build());
+ }
}
static void cancelNewMessageNotification(Context context) {
@@ -1324,6 +1363,7 @@
* @param user user to deliver the intent to
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @SuppressLint("MissingPermission")
public void dispatchIntent(Intent intent, String permission, String appOp,
Bundle opts, SmsBroadcastReceiver resultReceiver, UserHandle user, int subId) {
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
@@ -1352,12 +1392,17 @@
// Get a list of currently started users.
int[] users = null;
final List<UserHandle> userHandles = mUserManager.getUserHandles(false);
+ final UserHandle mainUser = mUserManager.getMainUser();
final List<UserHandle> runningUserHandles = new ArrayList();
for (UserHandle handle : userHandles) {
if (mUserManager.isUserRunning(handle)) {
runningUserHandles.add(handle);
} else {
- if (handle.equals(UserHandle.SYSTEM)) {
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()
+ && handle.equals(mainUser)) {
+ logeWithLocalLog("dispatchIntent: MAIN user is not running",
+ resultReceiver.mInboundSmsTracker.getMessageId());
+ } else if (handle.equals(UserHandle.SYSTEM)) {
logeWithLocalLog("dispatchIntent: SYSTEM user is not running",
resultReceiver.mInboundSmsTracker.getMessageId());
}
@@ -1375,7 +1420,7 @@
// by user policy.
for (int i = users.length - 1; i >= 0; i--) {
UserHandle targetUser = UserHandle.of(users[i]);
- if (users[i] != UserHandle.SYSTEM.getIdentifier()) {
+ if (!isMainUser(users[i])) {
// Is the user not allowed to use SMS?
if (hasUserRestriction(UserManager.DISALLOW_SMS, targetUser)) {
continue;
@@ -1385,14 +1430,14 @@
continue;
}
}
- // Only pass in the resultReceiver when the user SYSTEM is processed.
+ // Only pass in the resultReceiver when the MAIN user is processed.
try {
- if (users[i] == UserHandle.SYSTEM.getIdentifier()) {
+ if (isMainUser(users[i])) {
resultReceiver.setWaitingForIntent(intent);
}
mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
.sendOrderedBroadcast(intent, Activity.RESULT_OK, permission, appOp,
- users[i] == UserHandle.SYSTEM.getIdentifier()
+ isMainUser(users[i])
? resultReceiver : null, getHandler(),
null /* initialData */, null /* initialExtras */, opts);
} catch (PackageManager.NameNotFoundException ignored) {
@@ -1416,6 +1461,15 @@
return (sources != null && !sources.isEmpty());
}
+ @SuppressLint("MissingPermission")
+ private boolean isMainUser(int userId) {
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ return userId == mUserManager.getMainUser().getIdentifier();
+ } else {
+ return userId == UserHandle.SYSTEM.getIdentifier();
+ }
+ }
+
/**
* Helper for {@link SmsBroadcastUndelivered} to delete an old message in the raw table.
*/
@@ -1511,7 +1565,11 @@
}
if (userHandle == null) {
- userHandle = UserHandle.SYSTEM;
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ userHandle = mUserManager.getMainUser();
+ } else {
+ userHandle = UserHandle.SYSTEM;
+ }
}
Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
@@ -1739,6 +1797,7 @@
handleAction(intent, true);
}
+ @SuppressLint("MissingPermission")
private synchronized void handleAction(@NonNull Intent intent, boolean onReceive) {
String action = intent.getAction();
if (mWaitingForIntent == null || !mWaitingForIntent.getAction().equals(action)) {
@@ -1795,9 +1854,15 @@
String mimeType = intent.getType();
setWaitingForIntent(intent);
- dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
- WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
- UserHandle.SYSTEM, subId);
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
+ WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options,
+ this, mUserManager.getMainUser(), subId);
+ } else {
+ dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
+ WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options,
+ this, UserHandle.SYSTEM, subId);
+ }
} else {
// Now that the intents have been deleted we can clean up the PDU data.
if (!Intents.DATA_SMS_RECEIVED_ACTION.equals(action)
@@ -2098,11 +2163,16 @@
public void onReceive(Context context, Intent intent) {
if (ACTION_OPEN_SMS_APP.equals(intent.getAction())) {
// do nothing if the user had not unlocked the device yet
+ // TODO(b/355049884): This is looking at sms package of the wrong user!
UserManager userManager =
(UserManager) context.getSystemService(Context.USER_SERVICE);
+ PackageManager pm = context.getPackageManager();
+ if (Flags.hsumPackageManager()) {
+ pm = context.createContextAsUser(UserHandle.CURRENT, 0).getPackageManager();
+ }
if (userManager.isUserUnlocked()) {
- context.startActivity(context.getPackageManager().getLaunchIntentForPackage(
- Telephony.Sms.getDefaultSmsPackage(context)));
+ context.startActivityAsUser(pm.getLaunchIntentForPackage(
+ Telephony.Sms.getDefaultSmsPackage(context)), UserHandle.CURRENT);
}
}
}
diff --git a/src/java/com/android/internal/telephony/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index 0afe119..42ec8d3 100644
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -566,7 +566,7 @@
}
if (mFeatureFlags.oemEnabledSatelliteFlag()) {
- TelephonyCountryDetector.getInstance(mPhone.getContext())
+ TelephonyCountryDetector.getInstance(mPhone.getContext(), mFeatureFlags)
.onNetworkCountryCodeChanged(mPhone, countryIso);
}
Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
diff --git a/src/java/com/android/internal/telephony/MockModem.java b/src/java/com/android/internal/telephony/MockModem.java
index a20e748..1fcdc2a 100644
--- a/src/java/com/android/internal/telephony/MockModem.java
+++ b/src/java/com/android/internal/telephony/MockModem.java
@@ -24,11 +24,13 @@
import static android.telephony.TelephonyManager.HAL_SERVICE_SIM;
import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.os.UserHandle;
import com.android.telephony.Rlog;
@@ -158,7 +160,8 @@
intent.setAction(actionName + phoneId);
intent.putExtra(PHONE_ID, phoneId);
- status = mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
+ status = mContext.bindServiceAsUser(intent, serviceConnection, Context.BIND_AUTO_CREATE,
+ UserHandle.of(ActivityManager.getCurrentUser()));
return status;
}
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index a14ae89..881adde 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -43,6 +43,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
+import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.CarrierConfigManager;
@@ -247,9 +248,11 @@
CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
// Listener callback is executed on handler thread to directly handle config change
- ccm.registerCarrierConfigChangeListener(this::post,
- (slotIndex, subId, carrierId, specificCarrierId) ->
- onCarrierConfigChanged(slotIndex, subId));
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) ->
+ onCarrierConfigChanged(slotIndex, subId));
+ }
mConvertedPsimSubId = getConvertedPsimSubscriptionId();
}
@@ -510,8 +513,8 @@
SatelliteController satelliteController = SatelliteController.getInstance();
boolean isSatelliteEnabledOrBeingEnabled = false;
if (satelliteController != null) {
- isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
- || satelliteController.isSatelliteBeingEnabled();
+ isSatelliteEnabledOrBeingEnabled =
+ satelliteController.isSatelliteEnabledOrBeingEnabled();
}
if (DBG) {
@@ -640,7 +643,7 @@
if (DBG) log("updateDefaultValues: change: " + change);
if (change == PRIMARY_SUB_NO_CHANGE) return;
- // If there's only one primary subscription active, we trigger PREFERRED_PICK_DIALOG
+ // If there's only one primary subscription active, we trigger mobile data
// dialog if and only if there were multiple primary SIM cards and one is removed.
// Otherwise, if user just inserted their first SIM, or there's one primary and one
// opportunistic subscription active (activeSubInfos.size() > 1), we automatically
@@ -656,7 +659,19 @@
if (hasCalling()) mSubscriptionManagerService.setDefaultVoiceSubId(subId);
if (hasMessaging()) mSubscriptionManagerService.setDefaultSmsSubId(subId);
if (!mSubscriptionManagerService.isEsimBootStrapProvisioningActivated()) {
- sendDefaultSubConfirmedNotification(subId);
+ // Determines the appropriate notification type
+ // Preconditions:
+ // - There is only one active primary subscription.
+ // - The eSIM bootstrap is NOT activated.
+ // Behavior:
+ // - If the primary subscription is not deactivated OR the device is in single SIM
+ // mode, send a notification to dismiss the SIM dialog.
+ // - Otherwise, send a notification to trigger the preferred SIM/data pick dialog.
+ @TelephonyManager.DefaultSubscriptionSelectType
+ int type = (change != PRIMARY_SUB_REMOVED || mActiveModemCount == 1)
+ ? EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS
+ : EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
+ sendDefaultSubConfirmedNotification(type, subId);
}
return;
}
@@ -768,17 +783,21 @@
}
}
- private void sendDefaultSubConfirmedNotification(int defaultSubId) {
+ private void sendDefaultSubConfirmedNotification(
+ @TelephonyManager.DefaultSubscriptionSelectType int type, int defaultSubId) {
Intent intent = new Intent();
intent.setAction(ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED);
intent.setClassName("com.android.settings",
"com.android.settings.sim.SimSelectNotification");
- intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
- EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS);
+ intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, type);
intent.putExtra(EXTRA_SUBSCRIPTION_ID, defaultSubId);
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
}
private void sendSubChangeNotificationIfNeeded(int change, boolean dataSelected,
@@ -816,7 +835,11 @@
if (simCombinationParams.mWarningType == EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA) {
intent.putExtra(EXTRA_SIM_COMBINATION_NAMES, simCombinationParams.mSimNames);
}
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
index 91cd4ec..cc2e94d 100644
--- a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
+++ b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
@@ -75,17 +75,19 @@
CarrierConfigManager ccm = phone.getContext().getSystemService(CarrierConfigManager.class);
// Callback directly calls rebindService and should be executed in handler thread
- ccm.registerCarrierConfigChangeListener(
- this::post,
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex == phone.getPhoneId()) {
- // We should wait for carrier config changed event because the target
- // binding package name can come from the carrier config. Note that
- // we still get this event even when SIM is absent.
- logd("Carrier config changed. Try to bind network service.");
- rebindService();
- }
- });
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(
+ this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex == phone.getPhoneId()) {
+ // We should wait for carrier config changed event because the target
+ // binding package name can come from the carrier config. Note that
+ // we still get this event even when SIM is absent.
+ logd("Carrier config changed. Try to bind network service.");
+ rebindService();
+ }
+ });
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
this, EVENT_BIND_NETWORK_SERVICE, null);
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index c09f8fb..9b2b847 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -33,6 +33,7 @@
import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.CellInfo;
import android.telephony.LocationAccessPolicy;
import android.telephony.NetworkScan;
@@ -567,8 +568,8 @@
// 3. The live scan is not requested by mobile network setting menu
private synchronized boolean interruptLiveScan(NetworkScanRequestInfo nsri) {
if (mLiveRequestInfo != null && mPendingRequestInfo == null
- && nsri.mUid == Process.SYSTEM_UID
- && mLiveRequestInfo.mUid != Process.SYSTEM_UID) {
+ && UserHandle.isSameApp(nsri.mUid, Process.SYSTEM_UID)
+ && !UserHandle.isSameApp(mLiveRequestInfo.mUid, Process.SYSTEM_UID)) {
doInterruptScan(mLiveRequestInfo.mScanId);
mPendingRequestInfo = nsri;
notifyMessenger(mLiveRequestInfo, TelephonyScanManager.CALLBACK_SCAN_ERROR,
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 67ca1e1..081a5c8 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -170,7 +170,6 @@
@Override
public void onQosSessionsChanged(
@NonNull List<QosBearerSession> qosBearerSessions) {
- if (!mIsTimerResetEnabledOnVoiceQos) return;
sendMessage(obtainMessage(EVENT_QOS_SESSION_CHANGED, qosBearerSessions));
}
@@ -233,6 +232,8 @@
private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
private boolean mDoesPccListIndicateIdle = false;
+ private boolean mInVoiceCall = false;
+
/**
* NetworkTypeController constructor.
*
@@ -315,7 +316,9 @@
filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
- ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener);
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener);
+ }
}
private void unRegisterForAllEvents() {
@@ -327,7 +330,7 @@
mDataNetworkControllerCallback);
mPhone.getContext().unregisterReceiver(mIntentReceiver);
CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
- if (mCarrierConfigChangeListener != null) {
+ if (ccm != null && mCarrierConfigChangeListener != null) {
ccm.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener);
}
}
@@ -712,21 +715,22 @@
break;
case EVENT_QOS_SESSION_CHANGED:
List<QosBearerSession> qosBearerSessions = (List<QosBearerSession>) msg.obj;
- boolean inVoiceCall = false;
+ mInVoiceCall = false;
for (QosBearerSession session : qosBearerSessions) {
// TS 23.203 23.501 - 1 means conversational voice
- if (session.getQos() instanceof EpsQos qos) {
- inVoiceCall = qos.getQci() == 1;
- } else if (session.getQos() instanceof NrQos qos) {
- inVoiceCall = qos.get5Qi() == 1;
- }
- if (inVoiceCall) {
- if (DBG) log("Device in voice call, reset all timers");
- resetAllTimers();
- transitionToCurrentState();
+ if (session.getQos() instanceof EpsQos qos && qos.getQci() == 1) {
+ mInVoiceCall = true;
+ break;
+ } else if (session.getQos() instanceof NrQos qos && qos.get5Qi() == 1) {
+ mInVoiceCall = true;
break;
}
}
+ if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ if (DBG) log("Device in voice call, reset all timers");
+ resetAllTimers();
+ transitionToCurrentState();
+ }
break;
default:
throw new RuntimeException("Received invalid event: " + msg.what);
@@ -1022,7 +1026,10 @@
if (rat == TelephonyManager.NETWORK_TYPE_NR
|| (isLte(rat) && isNrConnected())) {
if (isNrAdvanced()) {
- transitionTo(mNrConnectedAdvancedState);
+ // Move into idle state because mPhysicalLinkStatus indicated idle,
+ // ignored any advance reason because unless mPhysicalLinkStatus changed
+ // again, shouldn't move back to advance.
+ log("Ignore NR advanced from cached PCC/RatchetedNrBands while idle");
} else if (isPhysicalLinkActive()) {
transitionWithTimerTo(mNrConnectedState);
} else {
@@ -1309,6 +1316,7 @@
mRatchetedNrBands.addAll(nrBands);
} else {
if (mFeatureFlags.supportNrSaRrcIdle() && mDoesPccListIndicateIdle
+ && anchorNrCellId != mLastAnchorNrCellId
&& isUsingPhysicalChannelConfigForRrcDetection()
&& !mPrimaryCellChangedWhileIdle
&& !isNrAdvancedForPccFields(nrBandwidths, nrBands)) {
@@ -1347,11 +1355,13 @@
if (secondaryRule != null) {
int secondaryDuration = secondaryRule.getSecondaryTimer(mSecondaryTimerState);
long durationMillis = secondaryDuration * 1000L;
- if ((mSecondaryTimerExpireTimestamp - SystemClock.uptimeMillis()) > durationMillis) {
+ long now = SystemClock.uptimeMillis();
+ if ((mSecondaryTimerExpireTimestamp - now) > durationMillis) {
if (DBG) log("Due to PCI change, reduce the secondary timer to " + durationMillis);
removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, mSecondaryTimerState,
durationMillis);
+ mSecondaryTimerExpireTimestamp = now + durationMillis;
}
} else {
loge("!! Secondary timer is active, but found no rule for " + mPrimaryTimerState);
@@ -1363,6 +1373,8 @@
if (mIsPrimaryTimerActive) {
log("Transition without timer from " + getCurrentState().getName() + " to " + destName
+ " due to existing " + mPrimaryTimerState + " primary timer.");
+ } else if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ log("Skip primary timer to " + destName + " due to in call");
} else {
if (DBG) {
log("Transition with primary timer from " + mPreviousState + " to " + destName);
@@ -1387,7 +1399,10 @@
log("Transition with secondary timer from " + currentName + " to "
+ destState.getName());
}
- if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
+ if (mIsTimerResetEnabledOnVoiceQos && mInVoiceCall) {
+ log("Skip secondary timer from " + currentName + " to "
+ + destState.getName() + " due to in call");
+ } else if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
int duration = rule.getSecondaryTimer(currentName);
if (mLastShownNrDueToAdvancedBand && mNrAdvancedBandsSecondaryTimer > 0) {
duration = mNrAdvancedBandsSecondaryTimer;
@@ -1746,6 +1761,7 @@
pw.println("mPrimaryCellChangedWhileIdle=" + mPrimaryCellChangedWhileIdle);
pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming);
pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode);
+ pw.println("mIsTimerResetEnabledOnVoiceQos=" + mIsTimerResetEnabledOnVoiceQos);
pw.decreaseIndent();
pw.flush();
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index aa62acb..61f1d45 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -281,9 +281,6 @@
// Key used to read/write the ID for storing the call forwarding status
public static final String CF_ID = "cf_id_key";
- // Key used to read/write "disable DNS server check" pref (used for testing)
- private static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
-
// Integer used to let the calling application know that the we are ignoring auto mode switch.
private static final int ALREADY_IN_AUTO_SELECTION = 1;
@@ -334,7 +331,6 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public CommandsInterface mCi;
protected int mVmCount = 0;
- private boolean mDnsCheckDisabled;
protected DataNetworkController mDataNetworkController;
/* Used for dispatching signals to configured carrier apps */
protected CarrierSignalAgent mCarrierSignalAgent;
@@ -486,6 +482,7 @@
private static final String ALLOWED_NETWORK_TYPES_TEXT_POWER = "power";
private static final String ALLOWED_NETWORK_TYPES_TEXT_CARRIER = "carrier";
private static final String ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G = "enable_2g";
+ private static final String ALLOWED_NETWORK_TYPES_TEXT_TEST = "test";
private static final int INVALID_ALLOWED_NETWORK_TYPES = -1;
protected boolean mIsCarrierNrSupported = false;
protected boolean mIsAllowedNetworkTypesLoadedFromDb = false;
@@ -615,7 +612,6 @@
setUnitTestMode(unitTestMode);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
- mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
mCi.setOnCallRing(this, EVENT_CALL_RING, null);
/* "Voice capable" means that this device supports circuit-switched
@@ -661,7 +657,7 @@
// Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
mTelephonyComponentFactory = telephonyComponentFactory;
mSmsStorageMonitor = mTelephonyComponentFactory.inject(SmsStorageMonitor.class.getName())
- .makeSmsStorageMonitor(this);
+ .makeSmsStorageMonitor(this, mFeatureFlags);
mSmsUsageMonitor = mTelephonyComponentFactory.inject(SmsUsageMonitor.class.getName())
.makeSmsUsageMonitor(context);
mUiccController = UiccController.getInstance();
@@ -902,6 +898,8 @@
Rlog.e(mLogTag, "Invalid Exception for usage setting " + ar.exception);
break; // technically extraneous, but good hygiene
}
+ } else {
+ mUsageSettingFromModem = msg.arg1;
}
break;
default:
@@ -984,26 +982,6 @@
protected abstract void onUpdateIccAvailability();
/**
- * Disables the DNS check (i.e., allows "0.0.0.0").
- * Useful for lab testing environment.
- * @param b true disables the check, false enables.
- */
- public void disableDnsCheck(boolean b) {
- mDnsCheckDisabled = b;
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
- SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
- editor.apply();
- }
-
- /**
- * Returns true if the DNS check is currently disabled.
- */
- public boolean isDnsCheckDisabled() {
- return mDnsCheckDisabled;
- }
-
- /**
* Register for getting notifications for change in the Call State {@link Call.State}
* This is called PreciseCallState because the call state is more precise than the
* {@link PhoneConstants.State} which can be obtained using the {@link PhoneStateListener}
@@ -2512,6 +2490,8 @@
return TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER;
case ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G:
return TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G;
+ case ALLOWED_NETWORK_TYPES_TEXT_TEST:
+ return TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_TEST;
default:
return INVALID_ALLOWED_NETWORK_TYPES;
}
@@ -2535,6 +2515,8 @@
return ALLOWED_NETWORK_TYPES_TEXT_CARRIER;
case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G:
return ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G;
+ case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_TEST:
+ return ALLOWED_NETWORK_TYPES_TEXT_TEST;
default:
throw new IllegalArgumentException(
"No DB name conversion available for allowed network type reason: " + reason
@@ -3199,7 +3181,11 @@
Intent intent = new Intent(TelephonyIntents.SECRET_CODE_ACTION,
Uri.parse("android_secret_code://" + code));
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent, null, options.toBundle());
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, null, options.toBundle());
+ } else {
+ mContext.sendBroadcast(intent, null, options.toBundle());
+ }
// {@link TelephonyManager.ACTION_SECRET_CODE} will replace {@link
// TelephonyIntents#SECRET_CODE_ACTION} in the next Android version. Before
@@ -3207,7 +3193,12 @@
Intent secrectCodeIntent = new Intent(TelephonyManager.ACTION_SECRET_CODE,
Uri.parse("android_secret_code://" + code));
secrectCodeIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(secrectCodeIntent, null, options.toBundle());
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(secrectCodeIntent, UserHandle.ALL, null,
+ options.toBundle());
+ } else {
+ mContext.sendBroadcast(secrectCodeIntent, null, options.toBundle());
+ }
}
}
@@ -4495,7 +4486,8 @@
mCi.getUsageSetting(obtainMessage(EVENT_GET_USAGE_SETTING_DONE));
// If the modem value is already known, and the value has changed, proceed to update.
} else if (mPreferredUsageSetting != mUsageSettingFromModem) {
- mCi.setUsageSetting(obtainMessage(EVENT_SET_USAGE_SETTING_DONE),
+ mCi.setUsageSetting(obtainMessage(EVENT_SET_USAGE_SETTING_DONE,
+ mPreferredUsageSetting, 0 /* unused */),
mPreferredUsageSetting);
}
return true;
@@ -4921,6 +4913,14 @@
}
/**
+ * @return The sms dispatchers controller
+ */
+ @Nullable
+ public SmsDispatchersController getSmsDispatchersController() {
+ return null;
+ }
+
+ /**
* @return The data settings manager
*/
@NonNull
@@ -5295,22 +5295,43 @@
}
/**
- * Start callback mode
+ * Start the emergency callback mode
* @param type for callback mode entry.
+ * @param durationMillis is the number of milliseconds remaining in the emergency callback
+ * mode.
*/
- public void startCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type) {
- Rlog.d(mLogTag, "startCallbackMode:type=" + type);
- mNotifier.notifyCallbackModeStarted(this, type);
+ public void startEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "startEmergencyCallbackMode:type=" + type);
+ mNotifier.notifyCallbackModeStarted(this, type, durationMillis);
}
/**
- * Stop callback mode
+ * Restart the emergency callback mode
+ * @param type for callback mode entry.
+ * @param durationMillis is the number of milliseconds remaining in the emergency callback
+ * mode.
+ */
+ public void restartEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ long durationMillis) {
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "restartEmergencyCallbackMode:type=" + type);
+ mNotifier.notifyCallbackModeRestarted(this, type, durationMillis);
+ }
+
+ /**
+ * Stop the emergency callback mode
* @param type for callback mode exit.
* @param reason for stopping callback mode.
*/
- public void stopCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
+ public void stopEmergencyCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
@TelephonyManager.EmergencyCallbackModeStopReason int reason) {
- Rlog.d(mLogTag, "stopCallbackMode:type=" + type + ", reason=" + reason);
+ if (!mFeatureFlags.emergencyCallbackModeNotification()) return;
+
+ Rlog.d(mLogTag, "stopEmergencyCallbackMode:type=" + type + ", reason=" + reason);
mNotifier.notifyCallbackModeStopped(this, type, reason);
}
@@ -5326,11 +5347,31 @@
mNotifier.notifyCarrierRoamingNtnModeChanged(this, active);
}
+ /**
+ * Notify external listeners that the device eligibility to connect to carrier roaming
+ * non-terrestrial network changed.
+ *
+ * @param eligible {@code true} when the device is eligible for satellite
+ * communication if all the following conditions are met:
+ * <ul>
+ * <li>Any subscription on the device supports P2P satellite messaging which is defined by
+ * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li>
+ * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to
+ * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li>
+ * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi,
+ * and the hysteresis timer defined by {@link CarrierConfigManager
+ * #KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT} is expired. </li>
+ * </ul>
+ */
+ public void notifyCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
+ logd("notifyCarrierRoamingNtnEligibleStateChanged eligible:" + eligible);
+ mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Phone: subId=" + getSubId());
pw.println(" mPhoneId=" + mPhoneId);
pw.println(" mCi=" + mCi);
- pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
pw.println(" mCallRingDelay=" + mCallRingDelay);
@@ -5345,7 +5386,6 @@
pw.println(" mNotifier=" + mNotifier);
pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
pw.println(" mUnitTestMode=" + mUnitTestMode);
- pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
pw.println(" getUnitTestMode()=" + getUnitTestMode());
pw.println(" getState()=" + getState());
pw.println(" getIccSerialNumber()=" + Rlog.pii(mLogTag, getIccSerialNumber()));
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index ffa5b69..dd96594 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -29,6 +29,7 @@
import android.os.PowerManager;
import android.os.RegistrantList;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.sysprop.TelephonyProperties;
import android.telephony.PhoneCapability;
@@ -391,9 +392,12 @@
}
mSlotsSupportingSimultaneousCellularCalls.add(i);
}
- // Ensure the slots supporting cellular DSDA does not exceed the phone count
- if (mSlotsSupportingSimultaneousCellularCalls.size() > getPhoneCount()) {
- loge("Invalid size of DSDA slots. Disabling cellular DSDA.");
+ // Ensure the number of slots supporting cellular DSDA is valid:
+ if (mSlotsSupportingSimultaneousCellularCalls.size() > getPhoneCount() ||
+ mSlotsSupportingSimultaneousCellularCalls.size() < 2) {
+ loge("Invalid size of DSDA slots. Disabling cellular DSDA. Size of "
+ + "mSlotsSupportingSimultaneousCellularCalls=" +
+ mSlotsSupportingSimultaneousCellularCalls.size());
mSlotsSupportingSimultaneousCellularCalls.clear();
}
} else {
@@ -770,7 +774,11 @@
Intent intent = new Intent(ACTION_MULTI_SIM_CONFIG_CHANGED);
intent.putExtra(EXTRA_ACTIVE_SIM_SUPPORTED_COUNT, numOfActiveModems);
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
}
/**
* This is invoked from shell commands during CTS testing only.
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index d9c5c9c..c077ca9 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -46,6 +46,7 @@
import com.android.internal.telephony.data.CellularNetworkValidator;
import com.android.internal.telephony.data.PhoneSwitcher;
import com.android.internal.telephony.data.TelephonyNetworkFactory;
+import com.android.internal.telephony.data.TelephonyNetworkProvider;
import com.android.internal.telephony.euicc.EuiccCardController;
import com.android.internal.telephony.euicc.EuiccController;
import com.android.internal.telephony.flags.FeatureFlags;
@@ -101,6 +102,7 @@
static private SimultaneousCallingTracker sSimultaneousCallingTracker;
static private PhoneSwitcher sPhoneSwitcher;
static private TelephonyNetworkFactory[] sTelephonyNetworkFactories;
+ private static TelephonyNetworkProvider sTelephonyNetworkProvider;
static private NotificationChannelController sNotificationChannelController;
static private CellularNetworkValidator sCellularNetworkValidator;
@@ -205,7 +207,7 @@
// Instantiate UiccController so that all other classes can just
// call getInstance()
- sUiccController = UiccController.make(context);
+ sUiccController = UiccController.make(context, featureFlags);
Rlog.i(LOG_TAG, "Creating SubscriptionManagerService");
sSubscriptionManagerService = new SubscriptionManagerService(context,
@@ -239,6 +241,12 @@
}
Rlog.i(LOG_TAG, "defaultSmsApplication: " + packageName);
+ if (sFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ // Explicitly call this, even if the user has no default Sms application, to
+ // ensure that the System apps have the appropriate permissions.
+ SmsApplication.grantPermissionsToSystemApps(context);
+ }
+
// Set up monitor to watch for changes to SMS packages
SmsApplication.initSmsPackageMonitor(context);
@@ -279,9 +287,15 @@
sNotificationChannelController = new NotificationChannelController(context);
- for (int i = 0; i < numPhones; i++) {
- sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i], featureFlags);
+ if (featureFlags.supportNetworkProvider()) {
+ // Create the TelephonyNetworkProvider instance, which is a singleton.
+ sTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
+ context, featureFlags);
+ } else {
+ for (int i = 0; i < numPhones; i++) {
+ sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+ Looper.myLooper(), sPhones[i], featureFlags);
+ }
}
}
}
@@ -306,7 +320,10 @@
sPhones = copyOf(sPhones, activeModemCount);
sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount);
- sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+ }
int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
for (int i = prevActiveModemCount; i < activeModemCount; i++) {
@@ -318,8 +335,11 @@
PackageManager.FEATURE_TELEPHONY_IMS)) {
sPhones[i].createImsPhone();
}
- sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i], sFeatureFlags);
+
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+ Looper.myLooper(), sPhones[i], sFeatureFlags);
+ }
}
}
}
@@ -387,6 +407,10 @@
}
}
+ public static TelephonyNetworkProvider getNetworkProvider() {
+ return sTelephonyNetworkProvider;
+ }
+
/**
* Get the network factory associated with a given phone ID.
* @param phoneId the phone id
@@ -573,13 +597,22 @@
pw.flush();
pw.println("++++++++++++++++++++++++++++++++");
- sTelephonyNetworkFactories[i].dump(fd, pw, args);
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories[i].dump(fd, pw, args);
+ }
pw.flush();
pw.decreaseIndent();
pw.println("++++++++++++++++++++++++++++++++");
}
+ pw.increaseIndent();
+ if (sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkProvider.dump(fd, pw, args);
+ }
+ pw.decreaseIndent();
+ pw.println("++++++++++++++++++++++++++++++++");
+
pw.println("UiccController:");
pw.increaseIndent();
try {
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index 9f459f5..a43ff72 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -145,7 +145,12 @@
List<LinkCapacityEstimate> linkCapacityEstimateList);
/** Notify callback mode started. */
- void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type);
+ void notifyCallbackModeStarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis);
+
+ /** Notify callback mode restarted. */
+ void notifyCallbackModeRestarted(Phone sender, @EmergencyCallbackModeType int type,
+ long durationMillis);
/** Notify callback mode stopped. */
void notifyCallbackModeStopped(Phone sender, @EmergencyCallbackModeType int type,
@@ -156,4 +161,7 @@
/** Notify carrier roaming non-terrestrial network mode changed. **/
void notifyCarrierRoamingNtnModeChanged(Phone sender, boolean active);
+
+ /** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */
+ void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible);
}
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 073e242..7ee3de2 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -785,9 +785,16 @@
*/
@Nullable
private String getCurrentPackageName() {
+ if (mFeatureFlags.hsumPackageManager()) {
+ PackageManager pm = mContext.createContextAsUser(Binder.getCallingUserHandle(), 0)
+ .getPackageManager();
+ if (pm == null) return null;
+ String[] callingPackageNames = pm.getPackagesForUid(Binder.getCallingUid());
+ return (callingPackageNames == null) ? null : callingPackageNames[0];
+ }
if (mPackageManager == null) return null;
- String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
- return (callingUids == null) ? null : callingUids[0];
+ String[] callingPackageNames = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingPackageNames == null) ? null : callingPackageNames[0];
}
/**
diff --git a/src/java/com/android/internal/telephony/ProxyController.java b/src/java/com/android/internal/telephony/ProxyController.java
index 01aed07..3b30d2f 100644
--- a/src/java/com/android/internal/telephony/ProxyController.java
+++ b/src/java/com/android/internal/telephony/ProxyController.java
@@ -28,6 +28,7 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
+import android.os.UserHandle;
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -364,7 +365,11 @@
logd("onStartRadioCapabilityResponse got exception=" + ar.exception);
mRadioCapabilitySessionId = mUniqueIdGenerator.getAndIncrement();
Intent intent = new Intent(TelephonyIntents.ACTION_SET_RADIO_CAPABILITY_FAILED);
- mContext.sendBroadcast(intent);
+ if (mFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
clearTransaction();
return;
}
@@ -611,7 +616,12 @@
}
// Broadcast that we're done
- mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
+ if (mFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.READ_PHONE_STATE);
+ } else {
+ mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
+ }
}
// Clear this transaction
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8abebe2..88ead6f 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -1047,10 +1047,16 @@
}
} else {
mDisabledRadioServices.get(service).add(mPhoneId);
- mHalVersion.put(service, RADIO_HAL_VERSION_UNKNOWN);
- riljLoge("getRadioServiceProxy: set " + serviceToString(service) + " for "
- + HIDL_SERVICE_NAME[mPhoneId] + " as disabled\n"
- + android.util.Log.getStackTraceString(new RuntimeException()));
+ if (isRadioServiceSupported(service)) {
+ mHalVersion.put(service, RADIO_HAL_VERSION_UNKNOWN);
+ riljLoge("getRadioServiceProxy: set " + serviceToString(service) + " for "
+ + HIDL_SERVICE_NAME[mPhoneId] + " as disabled\n"
+ + android.util.Log.getStackTraceString(new RuntimeException()));
+ } else {
+ mHalVersion.put(service, RADIO_HAL_VERSION_UNSUPPORTED);
+ riljLog("getRadioServiceProxy: set " + serviceToString(service) + " for "
+ + HIDL_SERVICE_NAME[mPhoneId] + " as disabled (unsupported)");
+ }
}
}
} catch (RemoteException e) {
@@ -4238,7 +4244,7 @@
riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ " with data profiles : ");
for (DataProfile profile : dps) {
- riljLog(profile.toString());
+ riljLog(Objects.toString(profile, "DataProfile is null"));
}
}
@@ -4374,9 +4380,9 @@
riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ " params: " + carrierRestrictionRules);
}
-
radioServiceInvokeHelper(HAL_SERVICE_SIM, rr, "setAllowedCarriers", () -> {
- simProxy.setAllowedCarriers(rr.mSerial, carrierRestrictionRules);
+ simProxy.setAllowedCarriers(rr.mSerial, carrierRestrictionRules,
+ getHalVersion(HAL_SERVICE_SIM));
});
}
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 8897db4..a81dbc8 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -1944,6 +1944,31 @@
}
/**
+ * Convert a list of CarrierIdentifiers into an array of CarrierInfo.aidl
+ *
+ * @param carriers List of CarrierIdentifiers
+ * @return The converted array of CarrierInfos.
+ */
+ public static android.hardware.radio.sim.CarrierInfo[] convertToHalCarrierInfoListAidl(
+ List<CarrierIdentifier> carriers) {
+ android.hardware.radio.sim.CarrierInfo[] result =
+ new android.hardware.radio.sim.CarrierInfo[carriers.size()];
+ for (int i = 0; i < carriers.size(); i++) {
+ CarrierIdentifier ci = carriers.get(i);
+ android.hardware.radio.sim.CarrierInfo carrierInfo =
+ new android.hardware.radio.sim.CarrierInfo();
+ carrierInfo.mcc = convertNullToEmptyString(ci.getMcc());
+ carrierInfo.mnc = convertNullToEmptyString(ci.getMnc());
+ carrierInfo.spn = ci.getSpn();
+ carrierInfo.imsiPrefix = ci.getImsi();
+ carrierInfo.gid1 = ci.getGid1();
+ carrierInfo.gid2 = ci.getGid2();
+ result[i] = carrierInfo;
+ }
+ return result;
+ }
+
+ /**
* Convert to Dial defined in radio/1.0/types.hal
* @param address Address
* @param clirMode CLIR mode
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index da20639..b4db14c 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -466,7 +466,7 @@
RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_DATA_MODEM,
result, mDefaultWorkSource);
if (DBG) {
- logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest) + " " + modemId);
}
try {
proxy.setPreferredDataModem(rr.mSerial, modemId);
diff --git a/src/java/com/android/internal/telephony/RadioSimProxy.java b/src/java/com/android/internal/telephony/RadioSimProxy.java
index 5265692..1c864fe 100644
--- a/src/java/com/android/internal/telephony/RadioSimProxy.java
+++ b/src/java/com/android/internal/telephony/RadioSimProxy.java
@@ -24,6 +24,8 @@
import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
import com.android.internal.telephony.uicc.SimPhonebookRecord;
+import java.util.Collections;
+
/**
* A holder for IRadioSim.
* Use getAidl to get IRadioSim and call the AIDL implementations of the HAL APIs.
@@ -512,27 +514,44 @@
/**
* Call IRadioSim#setAllowedCarriers
- * @param serial Serial number of request
+ *
+ * @param serial Serial number of request
* @param carrierRestrictionRules Allowed carriers
- * @throws RemoteException
*/
- public void setAllowedCarriers(int serial, CarrierRestrictionRules carrierRestrictionRules)
- throws RemoteException {
+ public void setAllowedCarriers(int serial, CarrierRestrictionRules carrierRestrictionRules,
+ HalVersion halversion) throws RemoteException {
if (isEmpty()) return;
if (isAidl()) {
- // Prepare structure with allowed list, excluded list and priority
android.hardware.radio.sim.CarrierRestrictions carrierRestrictions =
new android.hardware.radio.sim.CarrierRestrictions();
- carrierRestrictions.allowedCarriers = RILUtils.convertToHalCarrierRestrictionListAidl(
- carrierRestrictionRules.getAllowedCarriers());
- carrierRestrictions.excludedCarriers = RILUtils.convertToHalCarrierRestrictionListAidl(
- carrierRestrictionRules.getExcludedCarriers());
+ if (halversion.greaterOrEqual(RIL.RADIO_HAL_VERSION_2_2)) {
+ carrierRestrictions.allowedCarrierInfoList =
+ RILUtils.convertToHalCarrierInfoListAidl(
+ carrierRestrictionRules.getAllowedCarriers());
+ carrierRestrictions.excludedCarrierInfoList =
+ RILUtils.convertToHalCarrierInfoListAidl(
+ carrierRestrictionRules.getExcludedCarriers());
+ carrierRestrictions.allowedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(Collections.EMPTY_LIST);
+ carrierRestrictions.excludedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(Collections.EMPTY_LIST);
+ } else {
+ // Prepare structure with allowed list, excluded list and priority
+ carrierRestrictions.allowedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(
+ carrierRestrictionRules.getAllowedCarriers());
+ carrierRestrictions.excludedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(
+ carrierRestrictionRules.getExcludedCarriers());
+ }
carrierRestrictions.allowedCarriersPrioritized =
(carrierRestrictionRules.getDefaultCarrierRestriction()
== CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED);
+ carrierRestrictions.status = carrierRestrictionRules.getCarrierRestrictionStatus();
mSimProxy.setAllowedCarriers(serial, carrierRestrictions,
RILUtils.convertToHalSimLockMultiSimPolicyAidl(
carrierRestrictionRules.getMultiSimPolicy()));
+ Rlog.d(TAG, "RadioSimProxy setAllowedCarriers params = " + carrierRestrictions);
} else {
// Prepare structure with allowed list, excluded list and priority
android.hardware.radio.V1_4.CarrierRestrictionsWithPriority carrierRestrictions =
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 8764e02..8a2d5bf 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -20,6 +20,7 @@
import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
import static com.android.internal.telephony.IccSmsInterfaceManager.SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
import android.annotation.UserIdInt;
@@ -52,7 +53,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -89,6 +89,7 @@
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccRecords;
@@ -255,8 +256,7 @@
mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
Settings.Global.SMS_SHORT_CODE_RULE), false, mSettingsObserver);
- mSmsCapable = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_sms_capable);
+ mSmsCapable = mTelephonyManager.isDeviceSmsCapable();
mSmsSendDisabled = !mTelephonyManager.getSmsSendCapableForPhone(
mPhone.getPhoneId(), mSmsCapable);
IntentFilter intentFilter = new IntentFilter();
@@ -1017,8 +1017,8 @@
*/
protected void notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker,
boolean isOverIms) {
- mSmsDispatchersController.notifySmsSentFailedToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, isOverIms);
+ mSmsDispatchersController.notifySmsSent(tracker, isOverIms,
+ true /*isLastSmsPart*/, false /*success*/);
}
/**
@@ -1053,9 +1053,8 @@
}
tracker.onSent(mContext);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, false,
- tracker.isSinglePartOrLastPart());
+ mSmsDispatchersController.notifySmsSent(tracker, false,
+ tracker.isSinglePartOrLastPart(), true /*success*/);
mPhone.getSmsStats().onOutgoingSms(
tracker.mImsRetry > 0 /* isOverIms */,
@@ -1398,17 +1397,19 @@
* raw pdu of the status report is in the extended data ("pdu").
*/
@UnsupportedAppUsage
- protected void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
+ protected void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean isForVvm, long uniqueMessageId) {
int messageRef = nextMessageRef();
SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
scAddr, destAddr, destPort, data, (deliveryIntent != null), messageRef);
if (pdu != null) {
HashMap map = getSmsTrackerMap(destAddr, scAddr, destPort, data, pdu);
- SmsTracker tracker = getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
- getFormat(), null /*messageUri*/, false /*expectMore*/,
+ SmsTracker tracker = getSmsTracker(callingPackage, callingUser, map, sentIntent,
+ deliveryIntent, getFormat(), null /*messageUri*/, false /*expectMore*/,
null /*fullMessageText*/, false /*isText*/,
- true /*persistMessage*/, isForVvm, 0L /* messageId */, messageRef);
+ true /*persistMessage*/, isForVvm, 0L /* messageId */, messageRef,
+ uniqueMessageId);
if (!sendSmsByCarrierApp(true /* isDataSms */, tracker)) {
sendSubmitPdu(tracker);
@@ -1521,11 +1522,12 @@
*/
public void sendText(String destAddr, String scAddr, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
- String callingPkg, boolean persistMessage, int priority,
+ String callingPkg, int callingUser, boolean persistMessage, int priority,
boolean expectMore, int validityPeriod, boolean isForVvm,
long messageId) {
sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg,
- persistMessage, priority, expectMore, validityPeriod, isForVvm, messageId, false);
+ callingUser, persistMessage, priority, expectMore, validityPeriod, isForVvm,
+ messageId, false, PendingRequest.getNextUniqueMessageId());
}
/**
@@ -1630,10 +1632,10 @@
* @param skipShortCodeCheck Skip check for short code type destination address.
*/
public void sendText(String destAddr, String scAddr, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
- String callingPkg, boolean persistMessage, int priority,
- boolean expectMore, int validityPeriod, boolean isForVvm,
- long messageId, boolean skipShortCodeCheck) {
+ PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri,
+ String callingPkg, int callingUser, boolean persistMessage, int priority,
+ boolean expectMore, int validityPeriod, boolean isForVvm,
+ long messageId, boolean skipShortCodeCheck, long uniqueMessageId) {
Rlog.d(TAG, "sendText id: " + SmsController.formatCrossStackMessageId(messageId));
int messageRef = nextMessageRef();
SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
@@ -1641,10 +1643,10 @@
messageRef);
if (pdu != null) {
HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
- SmsTracker tracker = getSmsTracker(callingPkg, map, sentIntent, deliveryIntent,
- getFormat(), messageUri, expectMore, text, true /*isText*/,
+ SmsTracker tracker = getSmsTracker(callingPkg, callingUser, map, sentIntent,
+ deliveryIntent, getFormat(), messageUri, expectMore, text, true /*isText*/,
persistMessage, priority, validityPeriod, isForVvm, messageId, messageRef,
- skipShortCodeCheck);
+ skipShortCodeCheck, uniqueMessageId);
if (!sendSmsByCarrierApp(false /* isDataSms */, tracker)) {
sendSubmitPdu(tracker);
@@ -1825,8 +1827,8 @@
public void sendMultipartText(String destAddr, String scAddr,
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
- boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
- long messageId) {
+ int callingUser, boolean persistMessage, int priority, boolean expectMore,
+ int validityPeriod, long messageId, long uniqueMessageId) {
final String fullMessageText = getMultipartMessageText(parts);
int refNumber = getNextConcatenatedRef() & 0x00FF;
int encoding = SmsConstants.ENCODING_UNKNOWN;
@@ -1885,11 +1887,11 @@
}
int messageRef = nextMessageRef();
trackers[i] =
- getNewSubmitPduTracker(callingPkg, destAddr, scAddr, parts.get(i), smsHeader,
- encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)),
+ getNewSubmitPduTracker(callingPkg, callingUser, destAddr, scAddr, parts.get(i),
+ smsHeader, encoding, sentIntent, deliveryIntent, (i == (msgCount - 1)),
unsentPartCount, anyPartFailed, messageUri,
fullMessageText, priority, expectMore, validityPeriod, messageId,
- messageRef);
+ messageRef, uniqueMessageId);
if (trackers[i] == null) {
triggerSentIntentForFailure(sentIntents);
return;
@@ -1920,12 +1922,12 @@
/**
* Create a new SubmitPdu and return the SMS tracker.
*/
- private SmsTracker getNewSubmitPduTracker(String callingPackage, String destinationAddress,
- String scAddress, String message, SmsHeader smsHeader, int encoding,
- PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
+ private SmsTracker getNewSubmitPduTracker(String callingPackage, int callingUser,
+ String destinationAddress, String scAddress, String message, SmsHeader smsHeader,
+ int encoding, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean lastPart,
AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
String fullMessageText, int priority, boolean expectMore, int validityPeriod,
- long messageId, int messageRef) {
+ long messageId, int messageRef, long uniqueMessageId) {
if (isCdmaMo()) {
UserData uData = new UserData();
uData.payloadStr = message;
@@ -1951,11 +1953,11 @@
if (submitPdu != null) {
HashMap map = getSmsTrackerMap(destinationAddress, scAddress,
message, submitPdu);
- return getSmsTracker(callingPackage, map, sentIntent, deliveryIntent,
- getFormat(), unsentPartCount, anyPartFailed, messageUri, smsHeader,
- (!lastPart || expectMore), fullMessageText, true /*isText*/,
- true /*persistMessage*/, priority, validityPeriod, false /* isForVvm */,
- messageId, messageRef, false);
+ return getSmsTracker(callingPackage, callingUser, map, sentIntent,
+ deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
+ smsHeader, (!lastPart || expectMore), fullMessageText, /*isText*/
+ true, /*persistMessage*/ true, priority, validityPeriod, /* isForVvm */
+ false, messageId, messageRef, false, uniqueMessageId);
} else {
Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -1969,11 +1971,12 @@
smsHeader.languageShiftTable, validityPeriod, messageRef);
if (pdu != null) {
HashMap map = getSmsTrackerMap(destinationAddress, scAddress, message, pdu);
- return getSmsTracker(callingPackage, map, sentIntent,
- deliveryIntent, getFormat(), unsentPartCount, anyPartFailed, messageUri,
- smsHeader, (!lastPart || expectMore), fullMessageText, true /*isText*/,
- false /*persistMessage*/, priority, validityPeriod, false /* isForVvm */,
- messageId, messageRef, false);
+ return getSmsTracker(callingPackage, callingUser, map,
+ sentIntent, deliveryIntent, getFormat(), unsentPartCount, anyPartFailed,
+ messageUri, smsHeader, (!lastPart || expectMore),
+ fullMessageText, /*isText*/
+ true, /*persistMessage*/ false, priority, validityPeriod, /* isForVvm */
+ false, messageId, messageRef, false, uniqueMessageId);
} else {
Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -2490,6 +2493,7 @@
private int mCarrierId;
private boolean mSkipShortCodeDestAddrCheck;
+ public final long mUniqueMessageId;
// SMS anomaly uuid -- unexpected error from RIL
private final UUID mAnomalyUnexpectedErrorFromRilUUID =
UUID.fromString("43043600-ea7a-44d2-9ae6-a58567ac7886");
@@ -2500,7 +2504,8 @@
SmsHeader smsHeader, boolean expectMore, String fullMessageText, int subId,
boolean isText, boolean persistMessage, int userId, int priority,
int validityPeriod, boolean isForVvm, long messageId, int carrierId,
- int messageRef, boolean skipShortCodeDestAddrCheck) {
+ int messageRef, boolean skipShortCodeDestAddrCheck,
+ long uniqueMessageId) {
mData = data;
mSentIntent = sentIntent;
mDeliveryIntent = deliveryIntent;
@@ -2527,6 +2532,26 @@
mMessageId = messageId;
mCarrierId = carrierId;
mSkipShortCodeDestAddrCheck = skipShortCodeDestAddrCheck;
+ mUniqueMessageId = uniqueMessageId;
+ }
+
+ @VisibleForTesting
+ public SmsTracker(String destAddr, long messageId) {
+ mData = null;
+ mSentIntent = null;
+ mDeliveryIntent = null;
+ mAppInfo = null;
+ mDestAddress = destAddr;
+ mUsesImsServiceForIms = false;
+ mSmsHeader = null;
+ mMessageId = messageId;
+ mUserId = 0;
+ mPriority = 0;
+ mValidityPeriod = 0;
+ mIsForVvm = false;
+ mCarrierId = 0;
+ mSkipShortCodeDestAddrCheck = false;
+ mUniqueMessageId = 0;
}
public HashMap<String, Object> getData() {
@@ -2812,16 +2837,21 @@
}
}
- protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
+ protected SmsTracker getSmsTracker(String callingPackage, int callingUser,
+ HashMap<String, Object> data,
PendingIntent sentIntent, PendingIntent deliveryIntent, String format,
AtomicInteger unsentPartCount, AtomicBoolean anyPartFailed, Uri messageUri,
SmsHeader smsHeader, boolean expectMore, String fullMessageText, boolean isText,
boolean persistMessage, int priority, int validityPeriod, boolean isForVvm,
- long messageId, int messageRef, boolean skipShortCodeCheck) {
+ long messageId, int messageRef, boolean skipShortCodeCheck,
+ long uniqueMessageId) {
+ if (!Flags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid()).getIdentifier();
+ }
+
// Get package info via packagemanager
- UserHandle callingUser = UserHandle.getUserHandleForUid(Binder.getCallingUid());
- final int userId = callingUser.getIdentifier();
- PackageManager pm = mContext.createContextAsUser(callingUser, 0).getPackageManager();
+ PackageManager pm = mContext.createContextAsUser(UserHandle.of(callingUser), 0)
+ .getPackageManager();
PackageInfo appInfo = null;
try {
appInfo = pm.getPackageInfo(callingPackage, PackageManager.GET_SIGNATURES);
@@ -2833,31 +2863,35 @@
String destAddr = PhoneNumberUtils.extractNetworkPortion((String) data.get("destAddr"));
return new SmsTracker(data, sentIntent, deliveryIntent, appInfo, destAddr, format,
unsentPartCount, anyPartFailed, messageUri, smsHeader, expectMore,
- fullMessageText, getSubId(), isText, persistMessage, userId, priority,
+ fullMessageText, getSubId(), isText, persistMessage, callingUser, priority,
validityPeriod, isForVvm, messageId, mPhone.getCarrierId(), messageRef,
- skipShortCodeCheck);
+ skipShortCodeCheck, uniqueMessageId);
}
- protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
- PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
- boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
- boolean isForVvm, long messageId, int messageRef) {
- return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
- null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
- expectMore, fullMessageText, isText, persistMessage,
- SMS_MESSAGE_PRIORITY_NOT_SPECIFIED, SMS_MESSAGE_PERIOD_NOT_SPECIFIED, isForVvm,
- messageId, messageRef, false);
+ protected SmsTracker getSmsTracker(String callingPackage, int callingUser,
+ HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ String format, Uri messageUri, boolean expectMore, String fullMessageText,
+ boolean isText, boolean persistMessage, boolean isForVvm,
+ long messageId, int messageRef, long uniqueMessageId) {
+ return getSmsTracker(callingPackage, callingUser , data, sentIntent, deliveryIntent,
+ format, /*unsentPartCount*/ null, /*anyPartFailed*/ null, messageUri, /*smsHeader*/
+ null, expectMore, fullMessageText, isText,
+ persistMessage, SMS_MESSAGE_PRIORITY_NOT_SPECIFIED,
+ SMS_MESSAGE_PERIOD_NOT_SPECIFIED,
+ isForVvm, messageId, messageRef, false, uniqueMessageId);
}
- protected SmsTracker getSmsTracker(String callingPackage, HashMap<String, Object> data,
- PendingIntent sentIntent, PendingIntent deliveryIntent, String format, Uri messageUri,
- boolean expectMore, String fullMessageText, boolean isText, boolean persistMessage,
- int priority, int validityPeriod, boolean isForVvm, long messageId, int messageRef,
- boolean skipShortCodeCheck) {
- return getSmsTracker(callingPackage, data, sentIntent, deliveryIntent, format,
- null/*unsentPartCount*/, null/*anyPartFailed*/, messageUri, null/*smsHeader*/,
- expectMore, fullMessageText, isText, persistMessage, priority, validityPeriod,
- isForVvm, messageId, messageRef, skipShortCodeCheck);
+ protected SmsTracker getSmsTracker(String callingPackage, int callingUser,
+ HashMap<String, Object> data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ String format, Uri messageUri, boolean expectMore, String fullMessageText,
+ boolean isText, boolean persistMessage, int priority, int validityPeriod,
+ boolean isForVvm, long messageId, int messageRef, boolean skipShortCodeCheck,
+ long uniqueMessageId) {
+ return getSmsTracker(callingPackage, callingUser, data, sentIntent, deliveryIntent,
+ format, /*unsentPartCount*/ null, /*anyPartFailed*/ null, messageUri, /*smsHeader*/
+ null, expectMore, fullMessageText, isText, persistMessage, priority,
+ validityPeriod, isForVvm, messageId, messageRef, skipShortCodeCheck,
+ uniqueMessageId);
}
protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
@@ -3029,24 +3063,6 @@
return SubscriptionManager.getSubscriptionId(mPhone.getPhoneId());
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private void checkCallerIsPhoneOrCarrierApp() {
- int uid = Binder.getCallingUid();
- int appId = UserHandle.getAppId(uid);
- if (appId == Process.PHONE_UID || uid == 0) {
- return;
- }
- try {
- PackageManager pm = mContext.getPackageManager();
- ApplicationInfo ai = pm.getApplicationInfo(getCarrierAppPackageName(), 0);
- if (UserHandle.getAppId(ai.uid) != UserHandle.getAppId(Binder.getCallingUid())) {
- throw new SecurityException("Caller is not phone or carrier app!");
- }
- } catch (PackageManager.NameNotFoundException re) {
- throw new SecurityException("Caller is not phone or carrier app!");
- }
- }
-
protected boolean isCdmaMo() {
return mSmsDispatchersController.isCdmaMo();
}
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 2a9bf7f..3309d21 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -327,18 +327,10 @@
private boolean mImsRegistrationOnOff = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mDeviceShuttingDown = false;
+ private CarrierDisplayNameData mCarrierDisplayNameData =
+ new CarrierDisplayNameData.Builder().build();
/** Keep track of SPN display rules, so we only broadcast intent if something changes. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurSpn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurDataSpn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private String mCurPlmn = null;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private boolean mCurShowPlmn = false;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- private boolean mCurShowSpn = false;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@VisibleForTesting
public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mPrevSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -452,7 +444,7 @@
// Once sub id becomes valid, we need to update the service provider name
// displayed on the UI again. The old SPN update intents sent to
// MobileSignalController earlier were actually ignored due to invalid sub id.
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
mSubId = curSubId;
}
@@ -559,12 +551,12 @@
pollState();
// Depends on modem, ServiceState is not necessarily updated, so make sure updating
// SPN.
- updateSpnDisplay();
+ updateCarrierDisplayName();
} else if (action.equals(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED)) {
String lastKnownNetworkCountry = intent.getStringExtra(
TelephonyManager.EXTRA_LAST_KNOWN_NETWORK_COUNTRY);
if (!mLastKnownNetworkCountry.equals(lastKnownNetworkCountry)) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
}
}
@@ -666,7 +658,9 @@
mCarrierConfig = getCarrierConfig();
CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
// Callback which directly handle config change should be executed in handler thread
- ccm.registerCarrierConfigChangeListener(this::post, mCarrierConfigChangeListener);
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(this::post, mCarrierConfigChangeListener);
+ }
mAccessNetworksManager = mPhone.getAccessNetworksManager();
mOutOfServiceSS = new ServiceState();
@@ -1162,6 +1156,9 @@
mDesiredPowerState = power;
setPowerStateToDesired(forEmergencyCall, isSelectedPhoneForEmergencyCall, forceApply);
+ if (mDesiredPowerState) {
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(true);
+ }
}
/**
@@ -1240,7 +1237,7 @@
if (mUiccApplication == null
|| mUiccApplication.getState() != AppState.APPSTATE_READY) {
mIsSimReady = false;
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
break;
@@ -1323,6 +1320,12 @@
// Hence, issuing shut down regardless of radio power response
mCi.requestShutdown(null);
}
+
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ loge("EVENT_RADIO_POWER_OFF_DONE: exception=" + ar.exception);
+ SatelliteController.getInstance().onPowerOffCellularRadioFailed();
+ }
break;
// GSM
@@ -1413,7 +1416,7 @@
updateOtaspState();
if (mPhone.isPhoneTypeGsm()) {
mCdnr.updateEfFromUsim((SIMRecords) mIccRecords);
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
break;
@@ -1520,7 +1523,7 @@
case EVENT_IMS_CAPABILITY_CHANGED:
if (DBG) log("EVENT_IMS_CAPABILITY_CHANGED");
- updateSpnDisplay();
+ updateCarrierDisplayName();
mImsCapabilityChangedRegistrants.notifyRegistrants();
break;
@@ -1612,7 +1615,7 @@
mCdnr.updateEfFromRuim((RuimRecords) mIccRecords);
updatePhoneObject();
if (mPhone.isPhoneTypeCdma()) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
} else {
RuimRecords ruim = (RuimRecords) mIccRecords;
if (ruim != null) {
@@ -2750,59 +2753,42 @@
}
}
- private void notifySpnDisplayUpdate(CarrierDisplayNameData data) {
- int subId = mPhone.getSubId();
- // Update ACTION_SERVICE_PROVIDERS_UPDATED if any value changes
- if (mSubId != subId
- || data.shouldShowPlmn() != mCurShowPlmn
- || data.shouldShowSpn() != mCurShowSpn
- || !TextUtils.equals(data.getSpn(), mCurSpn)
- || !TextUtils.equals(data.getDataSpn(), mCurDataSpn)
- || !TextUtils.equals(data.getPlmn(), mCurPlmn)) {
+ private void notifyCarrierDisplayNameDataChanged() {
+ final String log = String.format("notifyCarrierDisplayNameDataChanged: "
+ + "changed sending intent, "
+ + "rule=%d, CarrierDisplayNameData=%s, subId=%d",
+ getCarrierNameDisplayBitmask(mSS),
+ mCarrierDisplayNameData,
+ mPhone.getSubId());
+ mCdnrLogs.log(log);
+ if (DBG) log(log);
- final String log = String.format("updateSpnDisplay: changed sending intent, "
- + "rule=%d, showPlmn='%b', plmn='%s', showSpn='%b', spn='%s', "
- + "dataSpn='%s', subId='%d'",
- getCarrierNameDisplayBitmask(mSS),
- data.shouldShowPlmn(),
- data.getPlmn(),
- data.shouldShowSpn(),
- data.getSpn(),
- data.getDataSpn(),
- subId);
- mCdnrLogs.log(log);
- if (DBG) log("updateSpnDisplay: " + log);
- Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
- intent.putExtra(TelephonyManager.EXTRA_SHOW_SPN, data.shouldShowSpn());
- intent.putExtra(TelephonyManager.EXTRA_SPN, data.getSpn());
- intent.putExtra(TelephonyManager.EXTRA_DATA_SPN, data.getDataSpn());
- intent.putExtra(TelephonyManager.EXTRA_SHOW_PLMN, data.shouldShowPlmn());
- intent.putExtra(TelephonyManager.EXTRA_PLMN, data.getPlmn());
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
- mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- mSubscriptionManagerService.setCarrierName(subId, TextUtils.emptyIfNull(
- getCarrierName(data.shouldShowPlmn(), data.getPlmn(),
- data.shouldShowSpn(), data.getSpn())));
- }
- }
- mCurShowSpn = data.shouldShowSpn();
- mCurShowPlmn = data.shouldShowPlmn();
- mCurSpn = data.getSpn();
- mCurDataSpn = data.getDataSpn();
- mCurPlmn = data.getPlmn();
+ Intent intent = new Intent(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
+ intent.putExtra(TelephonyManager.EXTRA_SHOW_SPN, mCarrierDisplayNameData.shouldShowSpn());
+ intent.putExtra(TelephonyManager.EXTRA_SPN, mCarrierDisplayNameData.getSpn());
+ intent.putExtra(TelephonyManager.EXTRA_DATA_SPN, mCarrierDisplayNameData.getDataSpn());
+ intent.putExtra(TelephonyManager.EXTRA_SHOW_PLMN, mCarrierDisplayNameData.shouldShowPlmn());
+ intent.putExtra(TelephonyManager.EXTRA_PLMN, mCarrierDisplayNameData.getPlmn());
+ SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
+ mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@NonNull
- private String getCarrierName(boolean showPlmn, String plmn, boolean showSpn, String spn) {
+ private String getCarrierName(CarrierDisplayNameData cdnd) {
+ boolean showPlmn = cdnd.shouldShowPlmn();
+ boolean showSpn = cdnd.shouldShowSpn();
+ String plmn = cdnd.getPlmn();
+ String spn = cdnd.getSpn();
+
String carrierName = "";
if (showPlmn) {
carrierName = plmn;
if (showSpn) {
- // Need to show both plmn and spn if both are not same.
- if (!Objects.equals(spn, plmn)) {
+ if (TextUtils.isEmpty(carrierName)) {
+ carrierName = spn;
+ } else if (!TextUtils.isEmpty(spn) && !Objects.equals(spn, carrierName)) {
+ // Need to show both plmn and spn if both are not same.
String separator = mPhone.getContext().getString(
com.android.internal.R.string.kg_text_message_separator).toString();
carrierName = new StringBuilder().append(carrierName).append(separator)
@@ -2812,29 +2798,34 @@
} else if (showSpn) {
carrierName = spn;
}
- return carrierName;
+ return TextUtils.emptyIfNull(carrierName);
}
- private void updateSpnDisplayCdnr() {
- log("updateSpnDisplayCdnr+");
- CarrierDisplayNameData data = mCdnr.getCarrierDisplayNameData();
- notifySpnDisplayUpdate(data);
- log("updateSpnDisplayCdnr-");
- }
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@VisibleForTesting
- public void updateSpnDisplay() {
- if (mCarrierConfig.getBoolean(
- CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL)) {
- updateSpnDisplayCdnr();
- } else {
- updateSpnDisplayLegacy();
+ public void updateCarrierDisplayName() {
+ final boolean useCdnr = mCarrierConfig.getBoolean(
+ CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL);
+
+ final CarrierDisplayNameData cdnd = useCdnr
+ ? mCdnr.getCarrierDisplayNameData()
+ : getCarrierDisplayNameLegacy();
+
+ final int subId = mPhone.getSubId();
+
+ // Avoid sending unnecessary updates
+ if (subId == mSubId && cdnd.equals(mCarrierDisplayNameData)) return;
+
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ mSubscriptionManagerService.setCarrierName(subId, getCarrierName(cdnd));
}
+
+ mCarrierDisplayNameData = cdnd; // notify...() relies on the updated value
+ notifyCarrierDisplayNameDataChanged();
+
}
- private void updateSpnDisplayLegacy() {
- log("updateSpnDisplayLegacy+");
+ private @NonNull CarrierDisplayNameData getCarrierDisplayNameLegacy() {
+ log("getCarrierDisplayNameLegacy+");
String spn = null;
String dataSpn = null;
@@ -2875,11 +2866,12 @@
.getStringArray(com.android.internal.R.array.wfcSpnFormats);
if (voiceIdx < 0 || voiceIdx >= wfcSpnFormats.length) {
- loge("updateSpnDisplay: KEY_WFC_SPN_FORMAT_IDX_INT out of bounds: " + voiceIdx);
+ loge("updateCarrierDisplayName: KEY_WFC_SPN_FORMAT_IDX_INT out of bounds: "
+ + voiceIdx);
voiceIdx = 0;
}
if (dataIdx < 0 || dataIdx >= wfcSpnFormats.length) {
- loge("updateSpnDisplay: KEY_WFC_DATA_SPN_FORMAT_IDX_INT out of bounds: "
+ loge("updateCarrierDisplayName: KEY_WFC_DATA_SPN_FORMAT_IDX_INT out of bounds: "
+ dataIdx);
dataIdx = 0;
}
@@ -2895,10 +2887,8 @@
}
String crossSimSpnFormat = null;
- if (mPhone.getImsPhone() != null
- && (mPhone.getImsPhone() != null)
- && (mPhone.getImsPhone().getImsRegistrationTech()
- == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM)) {
+ if ((getImsRegistrationTech() == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM)
+ && mPhone.isImsRegistered()) {
// In Cross SIM Calling mode show SPN or PLMN + Cross SIM Calling
//
// 1) Show SPN + Cross SIM Calling If SIM has SPN and SPN display condition
@@ -2915,7 +2905,7 @@
.getStringArray(R.array.crossSimSpnFormats);
if (crossSimSpnFormatIdx < 0 || crossSimSpnFormatIdx >= crossSimSpnFormats.length) {
- loge("updateSpnDisplay: KEY_CROSS_SIM_SPN_FORMAT_INT out of bounds: "
+ loge("updateCarrierDisplayName: KEY_CROSS_SIM_SPN_FORMAT_INT out of bounds: "
+ crossSimSpnFormatIdx);
crossSimSpnFormatIdx = 0;
}
@@ -2960,21 +2950,25 @@
.toString();
noService = true;
}
- if (DBG) log("updateSpnDisplay: radio is on but out " +
- "of service, set plmn='" + plmn + "'");
+ if (DBG) {
+ log("updateCarrierDisplayName: radio is on but out "
+ + "of service, set plmn='" + plmn + "'");
+ }
} else if (combinedRegState == ServiceState.STATE_IN_SERVICE) {
// In either home or roaming service
plmn = mSS.getOperatorAlpha();
showPlmn = !TextUtils.isEmpty(plmn) &&
((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN)
== CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN);
- if (DBG) log("updateSpnDisplay: rawPlmn = " + plmn);
+ if (DBG) log("updateCarrierDisplayName: rawPlmn = " + plmn);
} else {
// Power off state, such as airplane mode, show plmn as null
showPlmn = true;
plmn = null;
- if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn="
- + showPlmn + " plmn=" + plmn);
+ if (DBG) {
+ log("updateCarrierDisplayName: radio is off w/ showPlmn="
+ + showPlmn + " plmn=" + plmn);
+ }
}
// The value of spn/showSpn are same in different scenarios.
@@ -2986,7 +2980,7 @@
showSpn = !noService && !TextUtils.isEmpty(spn)
&& ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN)
== CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN);
- if (DBG) log("updateSpnDisplay: rawSpn = " + spn);
+ if (DBG) log("updateCarrierDisplayName: rawSpn = " + spn);
if (!TextUtils.isEmpty(crossSimSpnFormat)) {
if (!TextUtils.isEmpty(spn)) {
// Show SPN + Cross-SIM Calling If SIM has SPN and SPN display condition
@@ -3045,7 +3039,7 @@
// mOperatorAlpha contains the ERI text
plmn = mSS.getOperatorAlpha();
- if (DBG) log("updateSpnDisplay: cdma rawPlmn = " + plmn);
+ if (DBG) log("updateCarrierDisplayName: cdma rawPlmn = " + plmn);
showPlmn = plmn != null;
@@ -3057,8 +3051,8 @@
// todo: temporary hack; should have a better fix. This is to avoid using operator
// name from ServiceState (populated in processIwlanRegistrationInfo()) until
// wifi calling is actually enabled
- log("updateSpnDisplay: overwriting plmn from " + plmn + " to null as radio " +
- "state is off");
+ log("updateCarrierDisplayName: overwriting plmn from "
+ + plmn + " to null as radio " + "state is off");
plmn = null;
}
@@ -3066,20 +3060,21 @@
plmn = Resources.getSystem().getText(com.android.internal.R.string
.lockscreen_carrier_default).toString();
if (DBG) {
- log("updateSpnDisplay: radio is on but out of svc, set plmn='" + plmn + "'");
+ log("updateCarrierDisplayName: radio is on but out of svc, set plmn='"
+ + plmn + "'");
}
}
-
}
- notifySpnDisplayUpdate(new CarrierDisplayNameData.Builder()
+ log("getCarrierDisplayNameLegacy-");
+
+ return new CarrierDisplayNameData.Builder()
.setSpn(spn)
.setDataSpn(dataSpn)
.setShowSpn(showSpn)
.setPlmn(plmn)
.setShowPlmn(showPlmn)
- .build());
- log("updateSpnDisplayLegacy-");
+ .build();
}
/**
@@ -3288,7 +3283,7 @@
mImsRegistrationOnOff = registered;
// It's possible ServiceState changes did not trigger SPN display update; we update it here.
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
public void onImsCapabilityChanged() {
@@ -3702,11 +3697,11 @@
String eriText = mPhone.getCdmaEriText();
boolean hasEriChanged = !TextUtils.equals(mEriText, eriText);
mEriText = eriText;
- // Trigger updateSpnDisplay when
+ // Trigger updateCarrierDisplayName when
// 1. Service state is changed.
// 2. phone type is Cdma or CdmaLte and ERI text has changed.
if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)) {
- updateSpnDisplay();
+ updateCarrierDisplayName();
}
if (hasChanged) {
@@ -4977,7 +4972,7 @@
*/
public void powerOffRadioSafely() {
synchronized (this) {
- SatelliteController.getInstance().onCellularRadioPowerOffRequested();
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(false);
if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
EmergencyStateTracker.getInstance().onCellularRadioPowerOffRequested();
}
@@ -5268,11 +5263,7 @@
pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
pw.println(" mNotification=" + mNotification);
- pw.println(" mCurSpn=" + mCurSpn);
- pw.println(" mCurDataSpn=" + mCurDataSpn);
- pw.println(" mCurShowSpn=" + mCurShowSpn);
- pw.println(" mCurPlmn=" + mCurPlmn);
- pw.println(" mCurShowPlmn=" + mCurShowPlmn);
+ pw.println(" mCarrierDisplayNameData=" + mCarrierDisplayNameData);
pw.flush();
pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode);
pw.println(" mRoamingIndicator=" + mRoamingIndicator);
diff --git a/src/java/com/android/internal/telephony/SignalStrengthController.java b/src/java/com/android/internal/telephony/SignalStrengthController.java
index 98f84b2..31e1950 100644
--- a/src/java/com/android/internal/telephony/SignalStrengthController.java
+++ b/src/java/com/android/internal/telephony/SignalStrengthController.java
@@ -164,9 +164,11 @@
CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
mCarrierConfig = getCarrierConfig();
// Callback which directly handle config change should be executed on handler thread
- ccm.registerCarrierConfigChangeListener(this::post,
- (slotIndex, subId, carrierId, specificCarrierId) ->
- onCarrierConfigurationChanged(slotIndex));
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) ->
+ onCarrierConfigurationChanged(slotIndex));
+ }
mPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
}
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 59defc3..97692a0 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -112,7 +112,7 @@
android.hardware.radio.sim.CarrierRestrictions carrierRestrictions,
int multiSimPolicy) {
RILRequest rr = mRil.processResponse(HAL_SERVICE_SIM, responseInfo);
- boolean carrierLockInfoSupported = mRil.getHalVersion(HAL_SERVICE_SIM).greater(
+ boolean carrierLockInfoSupported = mRil.getHalVersion(HAL_SERVICE_SIM).greaterOrEqual(
RIL.RADIO_HAL_VERSION_2_2);
if (rr == null) {
return;
diff --git a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
index 0b427f8..12cc2fa 100644
--- a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
+++ b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
@@ -366,9 +366,8 @@
SubscriptionInfo subInfo =
SubscriptionManagerService.getInstance().getSubscriptionInfo(subId);
- if (mFeatureFlags.dataOnlyCellularService() &&
- subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID && subInfo != null &&
- subInfo.getServiceCapabilities()
+ if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID && subInfo != null
+ && subInfo.getServiceCapabilities()
.contains(SubscriptionManager.SERVICE_CAPABILITY_VOICE)) {
Log.v(LOG_TAG, "generateVoiceCapablePhoneMapBasedOnUserAssociation: adding "
+ "phoneId = " + phone.getPhoneId());
diff --git a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index 077ee0b..8c9a820 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -27,6 +27,7 @@
import android.database.Cursor;
import android.database.SQLException;
import android.os.PersistableBundle;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
@@ -35,6 +36,7 @@
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
@@ -97,6 +99,10 @@
/** Content resolver to use to access raw table from SmsProvider. */
private final ContentResolver mResolver;
+ private final UserManager mUserManager;
+
+ private final FeatureFlags mFeatureFlags;
+
/** Broadcast receiver that processes the raw table when the user unlocks the phone for the
* first time after reboot and the credential-encrypted storage is available.
*/
@@ -105,6 +111,12 @@
public void onReceive(final Context context, Intent intent) {
Rlog.d(TAG, "Received broadcast " + intent.getAction());
if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+ if (userId != getMainUser().getIdentifier()) {
+ return;
+ }
+ }
new ScanRawTableThread(context).start();
}
}
@@ -126,9 +138,9 @@
}
public static void initialize(Context context, GsmInboundSmsHandler gsmInboundSmsHandler,
- CdmaInboundSmsHandler cdmaInboundSmsHandler) {
+ CdmaInboundSmsHandler cdmaInboundSmsHandler, FeatureFlags featureFlags) {
if (instance == null) {
- instance = new SmsBroadcastUndelivered(context);
+ instance = new SmsBroadcastUndelivered(context, featureFlags);
}
// Tell handlers to start processing new messages and transit from the startup state to the
@@ -143,20 +155,38 @@
}
@UnsupportedAppUsage
- private SmsBroadcastUndelivered(Context context) {
+ private SmsBroadcastUndelivered(Context context, FeatureFlags featureFlags) {
mResolver = context.getContentResolver();
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserManager = context.getSystemService(UserManager.class);
+ mFeatureFlags = featureFlags;
- if (userManager.isUserUnlocked()) {
+ UserHandle mainUser = getMainUser();
+ boolean isUserUnlocked = mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser() ?
+ mUserManager.isUserUnlocked(mainUser) : mUserManager.isUserUnlocked();
+ if (isUserUnlocked) {
new ScanRawTableThread(context).start();
} else {
IntentFilter userFilter = new IntentFilter();
userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- context.registerReceiver(mBroadcastReceiver, userFilter);
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ context.registerReceiverAsUser(
+ mBroadcastReceiver, mainUser, userFilter, null, null);
+ } else {
+ context.registerReceiver(mBroadcastReceiver, userFilter);
+ }
}
}
+ /** Returns the MainUser, which is the user designated for sending SMS broadcasts. */
+ private UserHandle getMainUser() {
+ UserHandle mainUser = null;
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ mainUser = mUserManager.getMainUser();
+ }
+ return mainUser != null ? mainUser : UserHandle.SYSTEM;
+ }
+
/**
* Scan the raw table for complete SMS messages to broadcast, and old PDUs to delete.
*/
@@ -296,7 +326,8 @@
int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
CarrierConfigManager configManager =
(CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- PersistableBundle bundle = configManager.getConfigForSubId(subId);
+ PersistableBundle bundle = null;
+ if (configManager != null) bundle = configManager.getConfigForSubId(subId);
if (bundle != null) {
return bundle.getLong(CarrierConfigManager.KEY_UNDELIVERED_SMS_MESSAGE_EXPIRATION_TIME,
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 59184d8..e3c409d 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -176,11 +176,13 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendDataForSubscriber caller=" + callingPackage);
// Check if user is associated with the subscription
if (!TelephonyPermissions.checkSubscriptionAssociatedWithUser(mContext, subId,
- Binder.getCallingUserHandle(), destAddr)) {
+ callingUser, destAddr)) {
TelephonyUtils.showSwitchToManagedProfileDialogIfAppropriate(mContext, subId,
Binder.getCallingUid(), callingPackage);
sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_USER_NOT_ALLOWED);
@@ -195,7 +197,8 @@
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendData(callingPackage, callingAttributionTag, destAddr, scAddr, destPort,
+ iccSmsIntMgr.sendData(callingPackage, callingUser.getIdentifier(),
+ callingAttributionTag, destAddr, scAddr, destPort,
data, sentIntent, deliveryIntent);
} else {
Rlog.e(LOG_TAG, "sendDataForSubscriber iccSmsIntMgr is null for"
@@ -206,12 +209,14 @@
}
private void sendDataForSubscriberWithSelfPermissionsInternal(int subId, String callingPackage,
- String callingAttributionTag, String destAddr, String scAddr, int destPort, byte[] data,
- PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
+ int callingUser, String callingAttributionTag, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean isForVvm) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendDataWithSelfPermissions(callingPackage, callingAttributionTag,
- destAddr, scAddr, destPort, data, sentIntent, deliveryIntent, isForVvm);
+ iccSmsIntMgr.sendDataWithSelfPermissions(callingPackage, callingUser,
+ callingAttributionTag, destAddr, scAddr, destPort, data, sentIntent,
+ deliveryIntent, isForVvm);
} else {
Rlog.e(LOG_TAG, "sendText iccSmsIntMgr is null for"
+ " Subscription: " + subId);
@@ -219,7 +224,15 @@
}
}
+ @NonNull
private String getCallingPackage() {
+ if (mFlags.hsumPackageManager()) {
+ PackageManager pm = mContext.createContextAsUser(Binder.getCallingUserHandle(), 0)
+ .getPackageManager();
+ String[] packages = pm.getPackagesForUid(Binder.getCallingUid());
+ if (packages == null || packages.length == 0) return "";
+ return packages[0];
+ }
return mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
}
@@ -261,6 +274,8 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendTextForSubscriber caller=" + callingPackage);
if (skipFdnCheck || skipShortCodeCheck) {
@@ -306,9 +321,9 @@
if (isBluetoothSubscription(info)) {
sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent);
} else {
- sendIccText(subId, callingPackage, destAddr, scAddr, text, sentIntent,
- deliveryIntent, persistMessageForNonDefaultSmsApp, messageId,
- skipShortCodeCheck);
+ sendIccText(subId, callingPackage, callingUser.getIdentifier(), destAddr, scAddr,
+ text, sentIntent, deliveryIntent, persistMessageForNonDefaultSmsApp,
+ messageId, skipShortCodeCheck);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -326,14 +341,14 @@
btSmsInterfaceManager.sendText(mContext, destAddr, text, sentIntent, deliveryIntent, info);
}
- private void sendIccText(int subId, String callingPackage, String destAddr,
+ private void sendIccText(int subId, String callingPackage, int callingUser, String destAddr,
String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
boolean persistMessageForNonDefaultSmsApp, long messageId, boolean skipShortCodeCheck) {
Rlog.d(LOG_TAG, "sendTextForSubscriber iccSmsIntMgr"
+ " Subscription: " + subId + " " + formatCrossStackMessageId(messageId));
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendText(callingPackage, destAddr, scAddr, text, sentIntent,
+ iccSmsIntMgr.sendText(callingPackage, callingUser, destAddr, scAddr, text, sentIntent,
deliveryIntent, persistMessageForNonDefaultSmsApp, messageId,
skipShortCodeCheck);
} else {
@@ -344,13 +359,14 @@
}
private void sendTextForSubscriberWithSelfPermissionsInternal(int subId, String callingPackage,
- String callingAttributeTag, String destAddr, String scAddr, String text,
- PendingIntent sentIntent, PendingIntent deliveryIntent, boolean persistMessage,
- boolean isForVvm) {
+ int callingUser, String callingAttributeTag, String destAddr, String scAddr,
+ String text, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean persistMessage, boolean isForVvm) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendTextWithSelfPermissions(callingPackage, callingAttributeTag, destAddr,
- scAddr, text, sentIntent, deliveryIntent, persistMessage, isForVvm);
+ iccSmsIntMgr.sendTextWithSelfPermissions(callingPackage, callingUser,
+ callingAttributeTag, destAddr, scAddr, text, sentIntent, deliveryIntent,
+ persistMessage, isForVvm);
} else {
Rlog.e(LOG_TAG, "sendText iccSmsIntMgr is null for"
+ " Subscription: " + subId);
@@ -366,6 +382,8 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendTextForSubscriberWithOptions caller=" + callingPackage);
// Check if user is associated with the subscription
@@ -385,9 +403,9 @@
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendTextWithOptions(callingPackage, callingAttributionTag, destAddr,
- scAddr, parts, sentIntent, deliveryIntent, persistMessage, priority, expectMore,
- validityPeriod);
+ iccSmsIntMgr.sendTextWithOptions(callingPackage, callingUser.getIdentifier(),
+ callingAttributionTag, destAddr, scAddr, parts, sentIntent, deliveryIntent,
+ persistMessage, priority, expectMore, validityPeriod);
} else {
Rlog.e(LOG_TAG, "sendTextWithOptions iccSmsIntMgr is null for"
+ " Subscription: " + subId);
@@ -402,9 +420,9 @@
boolean persistMessageForNonDefaultSmsApp, long messageId) {
// This is different from the checking of other method. It prefers the package name
// returned by getCallPackage() for backward-compatibility.
- if (getCallingPackage() != null) {
- callingPackage = getCallingPackage();
- }
+ callingPackage = getCallingPackage();
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendMultipartTextForSubscriber caller=" + callingPackage);
// Check if user is associated with the subscription
@@ -426,9 +444,9 @@
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendMultipartText(callingPackage, callingAttributionTag, destAddr, scAddr,
- parts, sentIntents, deliveryIntents, persistMessageForNonDefaultSmsApp,
- messageId);
+ iccSmsIntMgr.sendMultipartText(callingPackage, callingUser.getIdentifier(),
+ callingAttributionTag, destAddr, scAddr, parts, sentIntents, deliveryIntents,
+ persistMessageForNonDefaultSmsApp, messageId);
} else {
Rlog.e(LOG_TAG, "sendMultipartTextForSubscriber iccSmsIntMgr is null for"
+ " Subscription: " + subId + " " + formatCrossStackMessageId(messageId));
@@ -444,6 +462,8 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendMultipartTextForSubscriberWithOptions caller=" + callingPackage);
// Check if user is associated with the subscription
@@ -463,9 +483,9 @@
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendMultipartTextWithOptions(callingPackage, callingAttributionTag,
- destAddr, scAddr, parts, sentIntents, deliveryIntents, persistMessage, priority,
- expectMore, validityPeriod, 0L /* messageId */);
+ iccSmsIntMgr.sendMultipartTextWithOptions(callingPackage, callingUser.getIdentifier(),
+ callingAttributionTag, destAddr, scAddr, parts, sentIntents, deliveryIntents,
+ persistMessage, priority, expectMore, validityPeriod, 0L /* messageId */);
} else {
Rlog.e(LOG_TAG, "sendMultipartTextWithOptions iccSmsIntMgr is null for"
+ " Subscription: " + subId);
@@ -717,6 +737,7 @@
Uri messageUri, String scAddress, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
+ UserHandle callingUser = Binder.getCallingUserHandle();
if (!getCallingPackage().equals(callingPkg)) {
throw new SecurityException("sendStoredText: Package " + callingPkg
+ "does not belong to " + Binder.getCallingUid());
@@ -724,8 +745,8 @@
Rlog.d(LOG_TAG, "sendStoredText caller=" + callingPkg);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendStoredText(callingPkg, callingAttributionTag, messageUri, scAddress,
- sentIntent, deliveryIntent);
+ iccSmsIntMgr.sendStoredText(callingPkg, callingUser.getIdentifier(),
+ callingAttributionTag, messageUri, scAddress, sentIntent, deliveryIntent);
} else {
Rlog.e(LOG_TAG, "sendStoredText iccSmsIntMgr is null for subscription: " + subId);
sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
@@ -737,6 +758,8 @@
Uri messageUri, String scAddress, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
if (!getCallingPackage().equals(callingPkg)) {
throw new SecurityException("sendStoredMultipartText: Package " + callingPkg
+ " does not belong to " + Binder.getCallingUid());
@@ -744,8 +767,8 @@
Rlog.d(LOG_TAG, "sendStoredMultipartText caller=" + callingPkg);
if (iccSmsIntMgr != null) {
- iccSmsIntMgr.sendStoredMultipartText(callingPkg, callingAttributionTag, messageUri,
- scAddress, sentIntents, deliveryIntents);
+ iccSmsIntMgr.sendStoredMultipartText(callingPkg, callingUser.getIdentifier(),
+ callingAttributionTag, messageUri, scAddress, sentIntents, deliveryIntents);
} else {
Rlog.e(LOG_TAG, "sendStoredMultipartText iccSmsIntMgr is null for subscription: "
+ subId);
@@ -979,7 +1002,7 @@
* Internal API to send visual voicemail related SMS. This is not exposed outside the phone
* process, and should be called only after verifying that the caller is the default VVM app.
*/
- public void sendVisualVoicemailSmsForSubscriber(String callingPackage,
+ public void sendVisualVoicemailSmsForSubscriber(String callingPackage, int callingUser,
String callingAttributionTag, int subId, String number, int port, String text,
PendingIntent sentIntent) {
Rlog.d(LOG_TAG, "sendVisualVoicemailSmsForSubscriber caller=" + callingPackage);
@@ -1001,12 +1024,12 @@
}
if (port == 0) {
- sendTextForSubscriberWithSelfPermissionsInternal(subId, callingPackage,
+ sendTextForSubscriberWithSelfPermissionsInternal(subId, callingPackage, callingUser,
callingAttributionTag, number, null, text, sentIntent, null, false,
true /* isForVvm */);
} else {
byte[] data = text.getBytes(StandardCharsets.UTF_8);
- sendDataForSubscriberWithSelfPermissionsInternal(subId, callingPackage,
+ sendDataForSubscriberWithSelfPermissionsInternal(subId, callingPackage, callingUser,
callingAttributionTag, number, null, (short) port, data, sentIntent, null,
true /* isForVvm */);
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index bc1e1a8..b60ded5 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -35,6 +35,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Telephony.Sms;
import android.provider.Telephony.Sms.Intents;
@@ -46,6 +47,7 @@
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import com.android.ims.ImsManager;
@@ -61,11 +63,14 @@
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
import com.android.internal.telephony.gsm.GsmSMSDispatcher;
+import com.android.internal.telephony.satellite.DatagramDispatcher;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -115,6 +120,12 @@
/** Called when the domain selection should be performed. */
private static final int EVENT_REQUEST_DOMAIN_SELECTION = 22;
+ /** Called when {@link DatagramDispatcher} informs to send carrier roaming nb iot ntn sms. */
+ private static final int CMD_SEND_TEXT = 23;
+
+ /** Called when {@link DatagramDispatcher} informs sms cannot be sent over ntn due to error. */
+ private static final int EVENT_SEND_TEXT_OVER_NTN_ERROR = 24;
+
/** Delete any partial message segments after being IN_SERVICE for 1 day. */
private static final long PARTIAL_SEGMENT_WAIT_DURATION = (long) (60 * 60 * 1000) * 24;
/** Constant for invalid time */
@@ -205,15 +216,17 @@
};
/** Stores the sending SMS information for a pending request. */
- private static class PendingRequest {
+ public static class PendingRequest {
public static final int TYPE_DATA = 1;
public static final int TYPE_TEXT = 2;
public static final int TYPE_MULTIPART_TEXT = 3;
public static final int TYPE_RETRY_SMS = 4;
+ private static final AtomicLong sNextUniqueMessageId = new AtomicLong(0);
public final int type;
public final SMSDispatcher.SmsTracker tracker;
public final String callingPackage;
+ public final int callingUser;
public final String destAddr;
public final String scAddr;
public final ArrayList<PendingIntent> sentIntents;
@@ -231,16 +244,18 @@
public final int validityPeriod;
public final long messageId;
public final boolean skipShortCodeCheck;
+ public final long uniqueMessageId;
- PendingRequest(int type, SMSDispatcher.SmsTracker tracker, String callingPackage,
- String destAddr, String scAddr, ArrayList<PendingIntent> sentIntents,
- ArrayList<PendingIntent> deliveryIntents, boolean isForVvm, byte[] data,
- int destPort, ArrayList<String> texts, Uri messageUri, boolean persistMessage,
- int priority, boolean expectMore, int validityPeriod, long messageId,
- boolean skipShortCodeCheck) {
+ public PendingRequest(int type, SMSDispatcher.SmsTracker tracker, String callingPackage,
+ int callingUser, String destAddr, String scAddr,
+ ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
+ boolean isForVvm, byte[] data, int destPort, ArrayList<String> texts,
+ Uri messageUri, boolean persistMessage, int priority, boolean expectMore,
+ int validityPeriod, long messageId, boolean skipShortCodeCheck) {
this.type = type;
this.tracker = tracker;
this.callingPackage = callingPackage;
+ this.callingUser = callingUser;
this.destAddr = destAddr;
this.scAddr = scAddr;
this.sentIntents = sentIntents;
@@ -258,6 +273,16 @@
this.validityPeriod = validityPeriod;
this.messageId = messageId;
this.skipShortCodeCheck = skipShortCodeCheck;
+ if (tracker != null) {
+ this.uniqueMessageId = tracker.mUniqueMessageId;
+ } else {
+ this.uniqueMessageId = getNextUniqueMessageId();
+ }
+ }
+
+ public static long getNextUniqueMessageId() {
+ return sNextUniqueMessageId.getAndUpdate(
+ id -> ((id + 1) % Long.MAX_VALUE));
}
}
@@ -381,12 +406,12 @@
mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, ImsManager::getConnector);
mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
- storageMonitor, phone, looper);
+ storageMonitor, phone, looper, mFeatureFlags);
mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
- storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper);
+ storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper, mFeatureFlags);
mGsmDispatcher = new GsmSMSDispatcher(phone, this, mGsmInboundSmsHandler);
SmsBroadcastUndelivered.initialize(phone.getContext(),
- mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
InboundSmsHandler.registerNewMessageNotificationActionHandler(phone.getContext());
mCi.registerForOn(this, EVENT_RADIO_ON, null);
@@ -525,6 +550,26 @@
}
break;
}
+ case CMD_SEND_TEXT: {
+ PendingRequest request = (PendingRequest) msg.obj;
+ if (request.type == PendingRequest.TYPE_TEXT) {
+ sendTextInternal(request);
+ } else if (request.type == PendingRequest.TYPE_MULTIPART_TEXT) {
+ sendMultipartTextInternal(request);
+ } else {
+ logd("CMD_SEND_TEXT: type=" + request.type
+ + " messageId=" + request.messageId);
+ }
+ break;
+ }
+ case EVENT_SEND_TEXT_OVER_NTN_ERROR: {
+ PendingRequest request = (PendingRequest) msg.obj;
+ logd("EVENT_SEND_TEXT_OVER_NTN_ERROR: type=" + request.type
+ + " messageId=" + request.messageId);
+ triggerSentIntentForFailure(request.sentIntents);
+ break;
+ }
+
default:
if (isCdmaMo()) {
mCdmaDispatcher.handleMessage(msg);
@@ -786,7 +831,9 @@
SomeArgs args = SomeArgs.obtain();
args.arg1 = getDomainSelectionConnectionHolder(isEmergency);
args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker,
- null, null, null, null, null, false, null, 0, null, null, false,
+ null, UserHandle.USER_NULL, null, null,
+ null, null, false, null, 0,
+ null, null, false,
0, false, 0, 0L, false);
args.arg3 = "sendRetrySms";
sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
@@ -833,8 +880,8 @@
// should never come here...
Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSentFailedToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, !retryUsingImsService);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
String scAddr = (String) map.get("scAddr");
@@ -842,8 +889,8 @@
if (destAddr == null) {
Rlog.e(TAG, "sendRetrySms failed due to null destAddr");
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSentFailedToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, !retryUsingImsService);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
@@ -884,8 +931,8 @@
+ "scAddr: %s, "
+ "destPort: %s", scAddr, map.get("destPort")));
tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
- notifySmsSentFailedToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, !retryUsingImsService);
+ notifySmsSent(tracker, !retryUsingImsService,
+ true /*isLastSmsPart*/, false /*success*/);
return;
}
// replace old smsc and pdu with newly encoded ones
@@ -1178,36 +1225,35 @@
}
/**
- * Called when MO SMS is successfully sent.
+ * Called when MO SMS is sent.
*/
- protected void notifySmsSentToEmergencyStateTracker(@NonNull String destAddr, long messageId,
- boolean isOverIms, boolean isLastSmsPart) {
+ protected void notifySmsSent(@NonNull SMSDispatcher.SmsTracker tracker,
+ boolean isOverIms, boolean isLastSmsPart, boolean success) {
+ notifySmsSentToEmergencyStateTracker(tracker.mDestAddress,
+ tracker.mMessageId, isOverIms, isLastSmsPart, success);
+ notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId, success);
+ }
+
+ /**
+ * Called when MO SMS is sent.
+ */
+ private void notifySmsSentToEmergencyStateTracker(@NonNull String destAddr, long messageId,
+ boolean isOverIms, boolean isLastSmsPart, boolean success) {
if (isSmsDomainSelectionEnabled()) {
// Run on main thread for interworking with EmergencyStateTracker.
SomeArgs args = SomeArgs.obtain();
args.arg1 = destAddr;
args.arg2 = Long.valueOf(messageId);
- args.arg3 = Boolean.TRUE;
+ args.arg3 = Boolean.valueOf(success);
args.arg4 = Boolean.valueOf(isOverIms);
args.arg5 = Boolean.valueOf(isLastSmsPart);
sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
}
}
- /**
- * Called when sending MO SMS is failed.
- */
- protected void notifySmsSentFailedToEmergencyStateTracker(@NonNull String destAddr,
- long messageId, boolean isOverIms) {
- if (isSmsDomainSelectionEnabled()) {
- // Run on main thread for interworking with EmergencyStateTracker.
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = destAddr;
- args.arg2 = Long.valueOf(messageId);
- args.arg3 = Boolean.FALSE;
- args.arg4 = Boolean.valueOf(isOverIms);
- args.arg5 = Boolean.TRUE; // Ignored when sending SMS is failed.
- sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
+ private void notifySmsSentToDatagramDispatcher(long messageId, boolean success) {
+ if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
}
}
@@ -1367,17 +1413,20 @@
private void sendData(@NetworkRegistrationInfo.Domain int domain,
@NonNull PendingRequest request) {
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
- mImsSmsDispatcher.sendData(request.callingPackage, request.destAddr, request.scAddr,
- request.destPort, request.data, request.sentIntents.get(0),
- request.deliveryIntents.get(0), request.isForVvm);
+ mImsSmsDispatcher.sendData(request.callingPackage, request.callingUser,
+ request.destAddr, request.scAddr, request.destPort, request.data,
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
} else if (isCdmaMo(domain)) {
- mCdmaDispatcher.sendData(request.callingPackage, request.destAddr, request.scAddr,
- request.destPort, request.data, request.sentIntents.get(0),
- request.deliveryIntents.get(0), request.isForVvm);
+ mCdmaDispatcher.sendData(request.callingPackage, request.callingUser, request.destAddr,
+ request.scAddr, request.destPort, request.data,
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
} else {
- mGsmDispatcher.sendData(request.callingPackage, request.destAddr, request.scAddr,
- request.destPort, request.data, request.sentIntents.get(0),
- request.deliveryIntents.get(0), request.isForVvm);
+ mGsmDispatcher.sendData(request.callingPackage, request.callingUser, request.destAddr,
+ request.scAddr, request.destPort, request.data,
+ request.sentIntents.get(0), request.deliveryIntents.get(0), request.isForVvm,
+ request.uniqueMessageId);
}
}
@@ -1394,22 +1443,25 @@
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
mImsSmsDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
request.sentIntents.get(0), request.deliveryIntents.get(0),
- request.messageUri, request.callingPackage, request.persistMessage,
- request.priority, false /*request.expectMore*/, request.validityPeriod,
- request.isForVvm, request.messageId, request.skipShortCodeCheck);
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, /*request.expectMore*/ false,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
if (isCdmaMo(domain)) {
mCdmaDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
request.sentIntents.get(0), request.deliveryIntents.get(0),
- request.messageUri, request.callingPackage, request.persistMessage,
- request.priority, request.expectMore, request.validityPeriod,
- request.isForVvm, request.messageId, request.skipShortCodeCheck);
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, request.expectMore,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
mGsmDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
request.sentIntents.get(0), request.deliveryIntents.get(0),
- request.messageUri, request.callingPackage, request.persistMessage,
- request.priority, request.expectMore, request.validityPeriod,
- request.isForVvm, request.messageId, request.skipShortCodeCheck);
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, request.expectMore,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
}
}
}
@@ -1427,24 +1479,31 @@
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
mImsSmsDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
- request.callingPackage, request.persistMessage, request.priority,
- false /*request.expectMore*/, request.validityPeriod, request.messageId);
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, false /*request.expectMore*/, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
} else {
if (isCdmaMo(domain)) {
mCdmaDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
- request.callingPackage, request.persistMessage, request.priority,
- request.expectMore, request.validityPeriod, request.messageId);
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, request.expectMore, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
} else {
mGsmDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
request.sentIntents, request.deliveryIntents, request.messageUri,
- request.callingPackage, request.persistMessage, request.priority,
- request.expectMore, request.validityPeriod, request.messageId);
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, request.expectMore, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
}
}
}
- private void triggerSentIntentForFailure(@NonNull PendingIntent sentIntent) {
+ private void triggerSentIntentForFailure(PendingIntent sentIntent) {
+ if (sentIntent == null) {
+ logd("sentIntent is null");
+ return;
+ }
try {
sentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
} catch (CanceledException e) {
@@ -1452,7 +1511,11 @@
}
}
- private void triggerSentIntentForFailure(@NonNull List<PendingIntent> sentIntents) {
+ private void triggerSentIntentForFailure(List<PendingIntent> sentIntents) {
+ if (sentIntents == null) {
+ logd("sentIntents is null");
+ return;
+ }
for (PendingIntent sentIntent : sentIntents) {
triggerSentIntentForFailure(sentIntent);
}
@@ -1546,31 +1609,36 @@
* broadcast when the message is delivered to the recipient. The
* raw pdu of the status report is in the extended data ("pdu").
*/
- protected void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent, boolean isForVvm) {
+ protected void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean isForVvm) {
if (TextUtils.isEmpty(scAddr)) {
scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPackage);
}
if (isSmsDomainSelectionEnabled()) {
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(false),
- new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage,
+ new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage, callingUser,
destAddr, scAddr, asArrayList(sentIntent),
- asArrayList(deliveryIntent), isForVvm, data, destPort, null, null,
- false, 0, false, 0, 0L, false),
+ asArrayList(deliveryIntent), isForVvm, data, destPort, null,
+ null, false, 0, false, 0,
+ 0L, false),
"sendData");
return;
}
if (mImsSmsDispatcher.isAvailable()) {
- mImsSmsDispatcher.sendData(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
- deliveryIntent, isForVvm);
+ mImsSmsDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
+ data, sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
} else if (isCdmaMo()) {
- mCdmaDispatcher.sendData(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
- deliveryIntent, isForVvm);
+ mCdmaDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
+ sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
} else {
- mGsmDispatcher.sendData(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
- deliveryIntent, isForVvm);
+ mGsmDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
+ sentIntent, deliveryIntent, isForVvm,
+ PendingRequest.getNextUniqueMessageId());
}
}
@@ -1672,11 +1740,12 @@
* Any Other values included Negative considered as Invalid Validity Period of the message.
*/
public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, Uri messageUri, String callingPkg, boolean persistMessage,
- int priority, boolean expectMore, int validityPeriod, boolean isForVvm,
- long messageId) {
+ PendingIntent deliveryIntent, Uri messageUri, String callingPkg, int callingUser,
+ boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
+ boolean isForVvm, long messageId) {
sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg,
- persistMessage, priority, expectMore, validityPeriod, isForVvm, messageId, false);
+ callingUser, persistMessage, priority, expectMore, validityPeriod, isForVvm,
+ messageId, false);
}
/**
@@ -1778,39 +1847,62 @@
* @param skipShortCodeCheck Skip check for short code type destination address.
*/
public void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent,
- PendingIntent deliveryIntent, Uri messageUri, String callingPkg, boolean persistMessage,
- int priority, boolean expectMore, int validityPeriod, boolean isForVvm,
- long messageId, boolean skipShortCodeCheck) {
+ PendingIntent deliveryIntent, Uri messageUri, String callingPkg, int callingUser,
+ boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
+ boolean isForVvm, long messageId, boolean skipShortCodeCheck) {
if (TextUtils.isEmpty(scAddr)) {
scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPkg);
}
- if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(destAddr);
- sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
- new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg,
- destAddr, scAddr, asArrayList(sentIntent),
- asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
- messageUri, persistMessage, priority, expectMore, validityPeriod,
- messageId, skipShortCodeCheck),
- "sendText");
+ PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_TEXT, null,
+ callingPkg, callingUser, destAddr, scAddr, asArrayList(sentIntent),
+ asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
+ messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
+ skipShortCodeCheck);
+
+ if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ // Send P2P SMS using carrier roaming NB IOT NTN
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
}
- if (mImsSmsDispatcher.isAvailable() || mImsSmsDispatcher.isEmergencySmsSupport(destAddr)) {
- mImsSmsDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
- messageUri, callingPkg, persistMessage, priority, false /*expectMore*/,
- validityPeriod, isForVvm, messageId, skipShortCodeCheck);
+ sendTextInternal(pendingRequest);
+ }
+
+ private void sendTextInternal(PendingRequest request) {
+ logd("sendTextInternal: messageId=" + request.messageId
+ + ", uniqueMessageId=" + request.uniqueMessageId);
+ if (isSmsDomainSelectionEnabled()) {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
+ sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
+ request, "sendText");
+ return;
+ }
+
+ if (mImsSmsDispatcher.isAvailable() || mImsSmsDispatcher.isEmergencySmsSupport(
+ request.destAddr)) {
+ mImsSmsDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
+ request.sentIntents.get(0), request.deliveryIntents.get(0),
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, false /*expectMore*/,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
if (isCdmaMo()) {
- mCdmaDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
- messageUri, callingPkg, persistMessage, priority, expectMore,
- validityPeriod, isForVvm, messageId, skipShortCodeCheck);
+ mCdmaDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
+ request.sentIntents.get(0), request.deliveryIntents.get(0),
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, request.expectMore,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
} else {
- mGsmDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,
- messageUri, callingPkg, persistMessage, priority, expectMore,
- validityPeriod, isForVvm, messageId, skipShortCodeCheck);
+ mGsmDispatcher.sendText(request.destAddr, request.scAddr, request.texts.get(0),
+ request.sentIntents.get(0), request.deliveryIntents.get(0),
+ request.messageUri, request.callingPackage, request.callingUser,
+ request.persistMessage, request.priority, request.expectMore,
+ request.validityPeriod, request.isForVvm, request.messageId,
+ request.skipShortCodeCheck, request.uniqueMessageId);
}
}
}
@@ -1922,37 +2014,55 @@
protected void sendMultipartText(String destAddr, String scAddr,
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
- boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
- long messageId) {
+ int callingUser, boolean persistMessage, int priority, boolean expectMore,
+ int validityPeriod, long messageId) {
if (TextUtils.isEmpty(scAddr)) {
scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPkg);
}
+ PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
+ callingPkg, callingUser, destAddr, scAddr, sentIntents, deliveryIntents, false,
+ null, 0, parts, messageUri, persistMessage, priority, expectMore,
+ validityPeriod, messageId, false);
+
+ if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ // Send multipart P2P SMS using carrier roaming NB IOT NTN
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ return;
+ }
+
+ sendMultipartTextInternal(pendingRequest);
+ }
+
+ private void sendMultipartTextInternal(PendingRequest request) {
+ logd("sendMultipartTextInternal: messageId=" + request.messageId);
if (isSmsDomainSelectionEnabled()) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(destAddr);
+ boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
- new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
- callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false,
- null, 0, parts, messageUri, persistMessage, priority, expectMore,
- validityPeriod, messageId, false),
- "sendMultipartText");
+ request, "sendMultipartText");
return;
}
if (mImsSmsDispatcher.isAvailable()) {
- mImsSmsDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,
- deliveryIntents, messageUri, callingPkg, persistMessage, priority,
- false /*expectMore*/, validityPeriod, messageId);
+ mImsSmsDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
+ request.sentIntents, request.deliveryIntents, request.messageUri,
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, false /*expectMore*/, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
} else {
if (isCdmaMo()) {
- mCdmaDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,
- deliveryIntents, messageUri, callingPkg, persistMessage, priority,
- expectMore, validityPeriod, messageId);
+ mCdmaDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
+ request.sentIntents, request.deliveryIntents, request.messageUri,
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, request.expectMore, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
} else {
- mGsmDispatcher.sendMultipartText(destAddr, scAddr, parts, sentIntents,
- deliveryIntents, messageUri, callingPkg, persistMessage, priority,
- expectMore, validityPeriod, messageId);
+ mGsmDispatcher.sendMultipartText(request.destAddr, request.scAddr, request.texts,
+ request.sentIntents, request.deliveryIntents, request.messageUri,
+ request.callingPackage, request.callingUser, request.persistMessage,
+ request.priority, request.expectMore, request.validityPeriod,
+ request.messageId, request.uniqueMessageId);
}
}
}
@@ -2081,6 +2191,44 @@
else return mGsmInboundSmsHandler;
}
+ /**
+ * This API should be used only by {@link DatagramDispatcher} to send SMS over
+ * non-terrestrial network.
+ *
+ * @param request {@link PendingRequest} object that contains all the information required to
+ * send MO SMS.
+ */
+ public void sendCarrierRoamingNbIotNtnText(@NonNull PendingRequest request) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
+ + "feature flag is disabled");
+ return;
+ }
+
+ sendMessage(obtainMessage(CMD_SEND_TEXT, request));
+ }
+
+ /**
+ * Send error code to pending MO SMS request.
+ *
+ * @param pendingRequest {@link PendingRequest} object that contains all the information
+ * related to MO SMS.
+ * @param errorCode error code to be returned.
+ */
+ public void onSendCarrierRoamingNbIotNtnTextError(@NonNull PendingRequest pendingRequest,
+ @SatelliteManager.SatelliteResult int errorCode) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
+ + "feature flag is disabled");
+ return;
+ }
+
+ logd("onSendCarrierRoamingNbIotNtnTextError: messageId=" + pendingRequest.messageId
+ + " errorCode=" + errorCode);
+ sendMessage(obtainMessage(EVENT_SEND_TEXT_OVER_NTN_ERROR, pendingRequest));
+ }
+
+
public interface SmsInjectionCallback {
void onSmsInjectedResult(int result);
}
diff --git a/src/java/com/android/internal/telephony/SmsStorageMonitor.java b/src/java/com/android/internal/telephony/SmsStorageMonitor.java
index 2736f7a..07b7a18 100644
--- a/src/java/com/android/internal/telephony/SmsStorageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsStorageMonitor.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -33,6 +34,7 @@
import android.telephony.SubscriptionManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.telephony.Rlog;
@@ -91,6 +93,9 @@
private boolean mMemoryStatusOverrideFlag = false;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
/**
* Hold the wake lock for 5 seconds, which should be enough time for
* any receiver(s) to grab its own wake lock.
@@ -100,9 +105,11 @@
/**
* Creates an SmsStorageMonitor and registers for events.
* @param phone the Phone to use
+ * @param flags The Android feature flags
*/
- public SmsStorageMonitor(Phone phone) {
+ public SmsStorageMonitor(@NonNull Phone phone, @NonNull FeatureFlags flags) {
mPhone = phone;
+ mFeatureFlags = flags;
mContext = phone.getContext();
mCi = phone.mCi;
@@ -278,7 +285,12 @@
intent.setComponent(componentName);
mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
- mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.RECEIVE_SMS);
+ } else {
+ mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
+ }
}
/** Returns whether or not there is storage available for an incoming SMS. */
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 0b0f9d3..10e97b6 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -289,8 +289,16 @@
return new GsmCdmaCallTracker(phone, featureFlags);
}
- public SmsStorageMonitor makeSmsStorageMonitor(Phone phone) {
- return new SmsStorageMonitor(phone);
+ /**
+ * Create {@link SmsStorageMonitor} instance.
+ *
+ * @param phone Phone instance
+ * @param flags Android feature flags
+ *
+ * @return The created instance
+ */
+ public SmsStorageMonitor makeSmsStorageMonitor(Phone phone, @NonNull FeatureFlags flags) {
+ return new SmsStorageMonitor(phone, flags);
}
public SmsUsageMonitor makeSmsUsageMonitor(Context context) {
@@ -331,8 +339,16 @@
return new CarrierActionAgent(phone);
}
- public CarrierResolver makeCarrierResolver(Phone phone) {
- return new CarrierResolver(phone);
+ /**
+ * Create {@link CarrierResolver} instance
+ *
+ * @param phone The phone instance
+ * @param flags Android feature flags
+ *
+ * @return The created instance
+ */
+ public CarrierResolver makeCarrierResolver(Phone phone, FeatureFlags flags) {
+ return new CarrierResolver(phone, flags);
}
public IccPhoneBookInterfaceManager makeIccPhoneBookInterfaceManager(Phone phone) {
diff --git a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
index 56e8b46..1e07bc3 100644
--- a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
+++ b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -35,6 +34,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.RegistrantList;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.telephony.Rlog;
@@ -42,6 +42,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.util.ArrayList;
import java.util.HashMap;
@@ -83,6 +84,8 @@
@NonNull private final Geocoder mGeocoder;
@NonNull private final LocationManager mLocationManager;
@NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final RegistrantList mWifiConnectivityStateChangedRegistrantList =
+ new RegistrantList();
@NonNull private final Object mLock = new Object();
@NonNull
@GuardedBy("mLock")
@@ -106,6 +109,11 @@
private Map<String, Long> mOverriddenCachedNetworkCountryCodes = new HashMap<>();
@GuardedBy("mLock")
private boolean mIsCountryCodesOverridden = false;
+ private final RegistrantList mCountryCodeChangedRegistrants = new RegistrantList();
+ private boolean mIsWifiNetworkConnected = false;
+
+ private FeatureFlags mFeatureFlags = null;
+
@NonNull private final LocationListener mLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
@@ -183,22 +191,26 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected TelephonyCountryDetector(@NonNull Looper looper, @NonNull Context context,
@NonNull LocationManager locationManager,
- @NonNull ConnectivityManager connectivityManager) {
+ @NonNull ConnectivityManager connectivityManager,
+ FeatureFlags featureFlags) {
super(looper);
mLocationManager = locationManager;
mGeocoder = new Geocoder(context);
mConnectivityManager = connectivityManager;
+ mFeatureFlags = featureFlags;
initialize();
}
/** @return the singleton instance of the {@link TelephonyCountryDetector} */
- public static synchronized TelephonyCountryDetector getInstance(@NonNull Context context) {
+ public static synchronized TelephonyCountryDetector getInstance(@NonNull Context context,
+ FeatureFlags featureFlags) {
if (sInstance == null) {
HandlerThread handlerThread = new HandlerThread("TelephonyCountryDetector");
handlerThread.start();
sInstance = new TelephonyCountryDetector(handlerThread.getLooper(), context,
context.getSystemService(LocationManager.class),
- context.getSystemService(ConnectivityManager.class));
+ context.getSystemService(ConnectivityManager.class),
+ featureFlags);
}
return sInstance;
}
@@ -286,6 +298,8 @@
handleNetworkCountryCodeChangedEvent((NetworkCountryCodeInfo) msg.obj);
break;
case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED:
+ handleEventWifiConnectivityStateChanged((boolean) msg.obj);
+ break;
case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET:
evaluateRequestingLocationUpdates();
break;
@@ -468,6 +482,27 @@
}
}
evaluateRequestingLocationUpdates();
+ if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("mCountryCodeChangedRegistrants.notifyRegistrants()");
+ mCountryCodeChangedRegistrants.notifyRegistrants();
+ } else {
+ logd("mCountryCodeChangedRegistrants.notifyRegistrants() is not called");
+ }
+ }
+
+ private void handleEventWifiConnectivityStateChanged(boolean connected) {
+ logd("handleEventWifiConnectivityStateChanged: " + connected);
+ evaluateNotifyWifiConnectivityStateChangedEvent(connected);
+ evaluateRequestingLocationUpdates();
+ }
+
+ private void evaluateNotifyWifiConnectivityStateChangedEvent(boolean connected) {
+ if (connected != mIsWifiNetworkConnected) {
+ mIsWifiNetworkConnected = connected;
+ mWifiConnectivityStateChangedRegistrantList.notifyResult(mIsWifiNetworkConnected);
+ logd("evaluateNotifyWifiConnectivityStateChangedEvent: wifi connectivity state has "
+ + "changed to " + connected);
+ }
}
private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) {
@@ -501,25 +536,23 @@
private void registerForWifiConnectivityStateChanged() {
logd("registerForWifiConnectivityStateChanged");
NetworkRequest.Builder builder = new NetworkRequest.Builder();
- builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
ConnectivityManager.NetworkCallback networkCallback =
new ConnectivityManager.NetworkCallback() {
@Override
- public void onAvailable(Network network) {
- logd("Wifi network available: " + network);
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ public void onCapabilitiesChanged(Network network,
+ NetworkCapabilities networkCapabilities) {
+ logd("onCapabilitiesChanged: " + networkCapabilities);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED,
+ isInternetAvailable(networkCapabilities));
}
@Override
public void onLost(Network network) {
logd("Wifi network lost: " + network);
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
- }
-
- @Override
- public void onUnavailable() {
- logd("Wifi network unavailable");
- sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ sendRequestAsync(EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, false);
}
};
mConnectivityManager.registerNetworkCallback(builder.build(), networkCallback);
@@ -533,13 +566,41 @@
}
}
- private boolean isWifiNetworkConnected() {
- Network activeNetwork = mConnectivityManager.getActiveNetwork();
- NetworkCapabilities networkCapabilities =
- mConnectivityManager.getNetworkCapabilities(activeNetwork);
- return networkCapabilities != null
- && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
- && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ /**
+ * Check whether Wi-Fi network is connected or not.
+ * @return {@code true} is Wi-Fi is connected, and internet is available, {@code false}
+ * otherwise.
+ */
+ public boolean isWifiNetworkConnected() {
+ logd("isWifiNetworkConnected: " + mIsWifiNetworkConnected);
+ return mIsWifiNetworkConnected;
+ }
+
+ private boolean isInternetAvailable(NetworkCapabilities networkCapabilities) {
+ boolean isWifiConnected =
+ networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ logd("isWifiConnected: " + isWifiConnected);
+ return isWifiConnected;
+ }
+
+ /**
+ * Register a callback to receive Wi-Fi connectivity state changes.
+ * @param h Handler for notification message
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForWifiConnectivityStateChanged(@NonNull Handler h, int what,
+ @Nullable Object obj) {
+ mWifiConnectivityStateChangedRegistrantList.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for Wi-Fi connectivity state changes.
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForWifiConnectivityStateChanged(@NonNull Handler h) {
+ mWifiConnectivityStateChangedRegistrantList.remove(h);
}
/**
@@ -558,6 +619,26 @@
|| SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
}
+ /**
+ * Register a callback for country code changed events
+ *
+ * @param h Handler to notify
+ * @param what msg.what when the message is delivered
+ * @param obj AsyncResult.userObj when the message is delivered
+ */
+ public void registerForCountryCodeChanged(Handler h, int what, Object obj) {
+ mCountryCodeChangedRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregister a callback for country code changed events
+ *
+ * @param h Handler to notifyf
+ */
+ public void unregisterForCountryCodeChanged(Handler h) {
+ mCountryCodeChangedRegistrants.remove(h);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java b/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
index e374811..64ecdc9 100644
--- a/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
+++ b/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
@@ -35,6 +35,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.VisualVoicemailSmsParser.WrappedMessageData;
+import com.android.internal.telephony.flags.Flags;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
@@ -286,7 +287,11 @@
intent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS, builder.build());
intent.putExtra(VoicemailContract.EXTRA_TARGET_PACKAGE, filterSettings.packageName);
intent.setPackage(TELEPHONY_SERVICE_PACKAGE);
- context.sendBroadcast(intent);
+ if (Flags.hsumBroadcast()) {
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ context.sendBroadcast(intent);
+ }
}
/**
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java
index 7669411..9bede69 100644
--- a/src/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/src/java/com/android/internal/telephony/WapPushOverSms.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -45,6 +46,7 @@
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.telephony.Rlog;
@@ -67,8 +69,14 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private final Context mContext;
+
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ private UserManager mUserManager;
+
PowerWhitelistManager mPowerWhitelistManager;
+ protected final @NonNull FeatureFlags mFeatureFlags;
+
private String mWapPushManagerPackage;
/** Assigned from ServiceConnection callback on main threaad. */
@@ -128,11 +136,11 @@
if (DBG) Rlog.v(TAG, "wappush manager disconnected.");
}
- public WapPushOverSms(Context context) {
+ public WapPushOverSms(Context context, FeatureFlags featureFlags) {
+ mFeatureFlags = featureFlags;
mContext = context;
mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class);
-
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mUserManager = mContext.getSystemService(UserManager.class);
bindWapPushManagerService(mContext);
}
@@ -325,6 +333,7 @@
* {@link Activity#RESULT_OK} if the message has been broadcast
* to applications
*/
+ @SuppressLint("MissingPermission")
public int dispatchWapPdu(byte[] pdu, InboundSmsHandler.SmsBroadcastReceiver receiver,
InboundSmsHandler handler, String address, int subId, long messageId) {
DecodedResult result = decodeWapPdu(pdu, handler);
@@ -422,7 +431,11 @@
}
if (userHandle == null) {
- userHandle = UserHandle.SYSTEM;
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ userHandle = mUserManager.getMainUser();
+ } else {
+ userHandle = UserHandle.SYSTEM;
+ }
}
handler.dispatchIntent(intent, getPermissionForType(result.mimeType),
getAppOpsStringPermissionForIntent(result.mimeType), options, receiver,
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index 4da1622..5fdb8ce 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -40,6 +40,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -712,7 +713,12 @@
intent.putExtra("SLOT_ID", mSlotId);
intent.setComponent(AppInterface.getDefaultSTKApplication());
CatLog.d(this, "Sending CmdMsg: " + cmdMsg+ " on slotid:" + mSlotId);
- mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+
+ if (sFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, AppInterface.STK_PERMISSION);
+ } else {
+ mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ }
}
/**
@@ -726,7 +732,11 @@
Intent intent = new Intent(AppInterface.CAT_SESSION_END_ACTION);
intent.putExtra("SLOT_ID", mSlotId);
intent.setComponent(AppInterface.getDefaultSTKApplication());
- mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ if (sFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, AppInterface.STK_PERMISSION);
+ } else {
+ mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ }
}
@@ -1090,7 +1100,11 @@
intent.putExtra("SLOT_ID", mSlotId);
CatLog.d(this, "Sending Card Status: "
+ cardState + " " + "cardPresent: " + cardPresent + "SLOT_ID: " + mSlotId);
- mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ if (sFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, AppInterface.STK_PERMISSION);
+ } else {
+ mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ }
}
private void broadcastAlphaMessage(String alphaString) {
@@ -1100,7 +1114,11 @@
intent.putExtra(AppInterface.ALPHA_STRING, alphaString);
intent.putExtra("SLOT_ID", mSlotId);
intent.setComponent(AppInterface.getDefaultSTKApplication());
- mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ if (sFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL, AppInterface.STK_PERMISSION);
+ } else {
+ mContext.sendBroadcast(intent, AppInterface.STK_PERMISSION);
+ }
}
@Override
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
index 784c974..9a85329 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaInboundSmsHandler.java
@@ -41,6 +41,7 @@
import com.android.internal.telephony.cdma.sms.BearerData;
import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.HexDump;
import java.io.ByteArrayOutputStream;
@@ -78,8 +79,9 @@
* Create a new inbound SMS handler for CDMA.
*/
private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
- Phone phone, CdmaSMSDispatcher smsDispatcher, Looper looper) {
- super("CdmaInboundSmsHandler", context, storageMonitor, phone, looper);
+ Phone phone, CdmaSMSDispatcher smsDispatcher, Looper looper,
+ FeatureFlags featureFlags) {
+ super("CdmaInboundSmsHandler", context, storageMonitor, phone, looper, featureFlags);
mSmsDispatcher = smsDispatcher;
phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);
@@ -171,9 +173,9 @@
*/
public static CdmaInboundSmsHandler makeInboundSmsHandler(Context context,
SmsStorageMonitor storageMonitor, Phone phone, CdmaSMSDispatcher smsDispatcher,
- Looper looper) {
+ Looper looper, FeatureFlags featureFlags) {
CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
- phone, smsDispatcher, looper);
+ phone, smsDispatcher, looper, featureFlags);
handler.start();
return handler;
}
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameData.java b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameData.java
index 59745dc..597bad3 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameData.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameData.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Rlog;
import java.util.Objects;
@@ -25,6 +26,9 @@
* A container of carrier display name.
*/
public class CarrierDisplayNameData implements Parcelable {
+
+ private static final String LOG_TAG = "CarrierDisplayNameData";
+
/** Service provider name. */
private final String mSpn;
@@ -40,8 +44,18 @@
/** {@code True} if display PLMN network name is required. */
private final boolean mShowPlmn;
- private CarrierDisplayNameData(String spn, String dataSpn, boolean showSpn, String plmn,
- boolean showPlmn) {
+ private CarrierDisplayNameData(
+ String spn, String dataSpn, boolean showSpn, String plmn, boolean showPlmn) {
+ final String logString = "Data SPN must be provided if SPN is provided";
+ if (spn != null && dataSpn == null) {
+ Rlog.e(LOG_TAG, logString);
+ if (android.os.Build.isDebuggable()) {
+ throw new IllegalArgumentException(logString);
+ } else {
+ dataSpn = spn;
+ }
+ }
+
this.mSpn = spn;
this.mDataSpn = dataSpn;
this.mShowSpn = showSpn;
diff --git a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
index 4b5eebc..8646981 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
@@ -190,7 +190,7 @@
}
/** Get the resolved carrier display name. */
- public CarrierDisplayNameData getCarrierDisplayNameData() {
+ public @NonNull CarrierDisplayNameData getCarrierDisplayNameData() {
resolveCarrierDisplayName();
return mCarrierDisplayNameData;
}
@@ -340,6 +340,7 @@
return new CarrierDisplayNameData.Builder()
.setSpn(spn)
+ .setDataSpn(spn)
.setShowSpn(showSpn)
.setPlmn(plmn)
.setShowPlmn(showPlmn)
@@ -477,7 +478,8 @@
CarrierDisplayNameData data = getCarrierDisplayNameFromEf();
if (DBG) Rlog.d(TAG, "CarrierName from EF: " + data);
if ((mPhone.getImsPhone() != null) && (mPhone.getImsPhone().getImsRegistrationTech()
- == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM)) {
+ == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM
+ && mPhone.isImsRegistered())) {
data = getCarrierDisplayNameFromCrossSimCallingOverride(data);
if (DBG) {
Rlog.d(TAG, "CarrierName override by Cross-SIM Calling " + data);
diff --git a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index bc684af..2691eab 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -333,7 +333,7 @@
log("onNetworkValidationRequested: networkCapability = ["
+ DataUtils.networkCapabilityToString(networkCapability) + "]");
- dnc.requestNetworkValidation(networkCapability, result -> post(() -> {
+ dnc.requestNetworkValidation(networkCapability, result -> {
try {
log("onNetworkValidationRequestDone:"
+ DataServiceCallback.resultCodeToString(result));
@@ -342,7 +342,7 @@
// Ignore if the remote process is no longer available to call back.
loge("onNetworkValidationRequestDone RemoteException" + e);
}
- }));
+ });
}
@Override
@@ -414,15 +414,19 @@
// bindQualifiedNetworksService posts real work to handler thread. So here we can
// let the callback execute in binder thread to avoid post twice.
- mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex != mPhone.getPhoneId()) return;
- // We should wait for carrier config changed event because the target binding
- // package name can come from the carrier config. Note that we still get this
- // event even when SIM is absent.
- if (DBG) log("Carrier config changed. Try to bind qualified network service.");
- bindQualifiedNetworksService();
- });
+ if (mCarrierConfigManager != null) {
+ mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex != mPhone.getPhoneId()) return;
+ // We should wait for carrier config changed event because the target
+ // binding package name can come from the carrier config. Note that we still
+ // get this event even when SIM is absent.
+ if (DBG) {
+ log("Carrier config changed. Try to bind qualified network service.");
+ }
+ bindQualifiedNetworksService();
+ });
+ }
bindQualifiedNetworksService();
// Using post to delay the registering because data retry manager and data config
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 9f4fa11..89b0fec 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -18,6 +18,7 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StringDef;
import android.content.res.Resources;
import android.net.LinkProperties;
@@ -272,7 +273,7 @@
private final String mLogTag;
@NonNull
private final FeatureFlags mFeatureFlags;
- @NonNull
+ @Nullable
private final CarrierConfigManager mCarrierConfigManager;
@NonNull
private PersistableBundle mCarrierConfig = null;
@@ -355,12 +356,14 @@
mCarrierConfigManager = mPhone.getContext().getSystemService(CarrierConfigManager.class);
// Callback send msg to handler thread, so callback itself can be executed in binder thread.
- mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex == mPhone.getPhoneId()) {
- sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
- }
- });
+ if (mCarrierConfigManager != null) {
+ mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex == mPhone.getPhoneId()) {
+ sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
+ }
+ });
+ }
// Register for device config update
DeviceConfig.addOnPropertiesChangedListener(
@@ -640,10 +643,8 @@
// Consumer slices are the slices that are allowed to be accessed by regular application to
// get better performance. They should be metered. This can be turned into configurations in
// the future.
- if (mFeatureFlags.meteredEmbbUrlcc()) {
- meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
- meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
- }
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
return Collections.unmodifiableSet(meteredCapabilities);
}
@@ -758,7 +759,6 @@
*/
public boolean allowBringUpNetworkInNonVops(@NetworkRegistrationInfo.RegistrationState
int regState) {
- if (!mFeatureFlags.allowMmtelInNonVops()) return false;
int networkType = -1;
if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
networkType = CarrierConfigManager.Ims.NETWORK_TYPE_HOME;
@@ -1503,14 +1503,6 @@
}
/**
- * {@code True} enables mms to be attempted on iwlan if possible, even if existing cellular
- * networks already supports iwlan.
- */
- public boolean isForceIwlanMmsFeatureEnabled() {
- return mResources.getBoolean(com.android.internal.R.bool.force_iwlan_mms_feature_enabled);
- }
-
- /**
* Log debug messages.
* @param s debug messages
*/
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index f5eae91..40c0081 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -225,6 +225,8 @@
SIM_LOADED(true),
/** SIM is removed. */
SIM_REMOVAL(true),
+ /** SIM is disabled. */
+ SIM_DISABLED(true),
/** Data profiles changed. */
DATA_PROFILES_CHANGED(true),
/** When service state changes.(For now only considering data RAT and data registration). */
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 87c392e..738c60f 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -100,6 +100,7 @@
import com.android.internal.telephony.data.DataRetryManager.DataRetryEntry;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
import com.android.internal.telephony.data.TelephonyNetworkAgent.TelephonyNetworkAgentCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DataCallSessionStats;
@@ -271,6 +272,9 @@
/** Event for response to data network validation request. */
private static final int EVENT_DATA_NETWORK_VALIDATION_RESPONSE = 29;
+ /** Event for preferred data subscription changed. */
+ private static final int EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED = 30;
+
/** Invalid context id. */
private static final int INVALID_CID = -1;
@@ -460,7 +464,10 @@
// Dynamically add and remove MMTEL capability when network transition between VoPS
// and non-VoPS network if the request is not MMTEL. For MMTEL, we retain the capability
// to prevent immediate tear down.
- NetworkCapabilities.NET_CAPABILITY_MMTEL
+ NetworkCapabilities.NET_CAPABILITY_MMTEL,
+ // Dynamically add and remove MMS capability depending on QNS's preference if there is
+ // a transport specific APN alternative.
+ NetworkCapabilities.NET_CAPABILITY_MMS
);
/** The parent state. Any messages not handled by the child state fallback to this. */
@@ -588,6 +595,10 @@
@NonNull
private final DataNetworkController mDataNetworkController;
+ /** Phone switcher which is responsible to determine which phone to route network request. */
+ @NonNull
+ private final PhoneSwitcher mPhoneSwitcher;
+
/** Data network controller callback. */
@NonNull
private final DataNetworkController.DataNetworkControllerCallback
@@ -673,6 +684,13 @@
/** Whether the current data network is congested. */
private boolean mCongested = false;
+ /**
+ * Whether the current data network is on preferred data modem.
+ *
+ * @see PhoneSwitcher#getPreferredDataPhoneId()
+ */
+ private boolean mOnPreferredDataPhone;
+
/** The network requests associated with this data network */
@NonNull
private final NetworkRequestList mAttachedNetworkRequestList =
@@ -812,6 +830,12 @@
private PreciseDataConnectionState mPreciseDataConnectionState;
/**
+ * Callback to listen event from {@link PhoneSwitcher}.
+ */
+ @NonNull
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
+ /**
* The network bandwidth.
*/
public static class NetworkBandwidth {
@@ -1024,6 +1048,8 @@
mAccessNetworksManager = phone.getAccessNetworksManager();
mVcnManager = mPhone.getContext().getSystemService(VcnManager.class);
mDataNetworkController = phone.getDataNetworkController();
+ mPhoneSwitcher = PhoneSwitcher.getInstance();
+ mOnPreferredDataPhone = phone.getPhoneId() == mPhoneSwitcher.getPreferredDataPhoneId();
mDataNetworkControllerCallback = new DataNetworkController.DataNetworkControllerCallback(
getHandler()::post) {
@Override
@@ -1153,14 +1179,25 @@
configBuilder.setNat64DetectionEnabled(false);
}
- final NetworkFactory factory = PhoneFactory.getNetworkFactory(
- mPhone.getPhoneId());
- final NetworkProvider provider = (null == factory) ? null : factory.getProvider();
+ NetworkProvider provider;
+ if (mFlags.supportNetworkProvider()) {
+ provider = PhoneFactory.getNetworkProvider();
+ } else {
+ final NetworkFactory factory = PhoneFactory.getNetworkFactory(
+ mPhone.getPhoneId());
+ provider = (null == factory) ? null : factory.getProvider();
+ }
- mNetworkScore = new NetworkScore.Builder()
- .setKeepConnectedReason(isHandoverInProgress()
+ NetworkScore.Builder builder = new NetworkScore.Builder()
+ .setKeepConnectedReason(isHandoverInProgress()
? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER
- : NetworkScore.KEEP_CONNECTED_NONE).build();
+ : NetworkScore.KEEP_CONNECTED_NONE);
+ if (mFlags.supportNetworkProvider()) {
+ builder.setTransportPrimary(mOnPreferredDataPhone);
+ }
+ mNetworkScore = builder.build();
+ logl("mNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
+ + ", keepConnectedReason=" + mNetworkScore.getKeepConnectedReason());
return new TelephonyNetworkAgent(mPhone, getHandler().getLooper(), this,
mNetworkScore, configBuilder.build(), provider,
@@ -1222,6 +1259,16 @@
mDataNetworkController.getDataSettingsManager()
.registerCallback(mDataSettingsManagerCallback);
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcherCallback = new PhoneSwitcherCallback(Runnable::run) {
+ @Override
+ public void onPreferredDataPhoneIdChanged(int phoneId) {
+ sendMessage(EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED, phoneId, 0);
+ }
+ };
+ mPhoneSwitcher.registerCallback(mPhoneSwitcherCallback);
+ }
+
mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(
getHandler(), EVENT_DISPLAY_INFO_CHANGED, null);
mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(),
@@ -1263,21 +1310,19 @@
getHandler(), EVENT_VOICE_CALL_ENDED, null);
}
- if (mFlags.forceIwlanMms() && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
- if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
- mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
- getHandler()::post) {
- @Override
- public void onPreferredTransportChanged(
- @NetCapability int networkCapability, boolean forceReconnect) {
- if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) {
- log("MMS preference changed.");
- updateNetworkCapabilities();
- }
+ if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
+ getHandler()::post) {
+ @Override
+ public void onPreferredTransportChanged(
+ @NetCapability int networkCapability, boolean forceReconnect) {
+ if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) {
+ log("MMS preference changed.");
+ updateNetworkCapabilities();
}
- };
- mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
- }
+ }
+ };
+ mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
}
// Only add symmetric code here, for example, registering and unregistering.
@@ -1289,8 +1334,7 @@
@Override
public void exit() {
logv("Unregistering all events.");
- if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null
- && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
+ if (mAccessNetworksManagerCallback != null) {
mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
}
@@ -1316,6 +1360,9 @@
mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler());
mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(
getHandler());
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcher.unregisterCallback(mPhoneSwitcherCallback);
+ }
mDataNetworkController.getDataSettingsManager()
.unregisterCallback(mDataSettingsManagerCallback);
mRil.unregisterForPcoData(getHandler());
@@ -1349,13 +1396,13 @@
}
case EVENT_ATTACH_NETWORK_REQUEST: {
onAttachNetworkRequests((NetworkRequestList) msg.obj);
- updateNetworkScore(isHandoverInProgress());
+ updateNetworkScore();
break;
}
case EVENT_DETACH_NETWORK_REQUEST: {
onDetachNetworkRequest((TelephonyNetworkRequest) msg.obj,
msg.arg1 != 0 /* shouldRetry */);
- updateNetworkScore(isHandoverInProgress());
+ updateNetworkScore();
break;
}
case EVENT_DETACH_ALL_NETWORK_REQUESTS: {
@@ -1426,6 +1473,12 @@
// handle the resultCode in response for the request.
handleDataNetworkValidationRequestResultCode(msg.arg1 /* resultCode */);
break;
+ case EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED:
+ mOnPreferredDataPhone = mPhone.getPhoneId() == msg.arg1;
+ logl("Preferred data phone id changed to " + msg.arg1
+ + ", mOnPreferredDataPhone=" + mOnPreferredDataPhone);
+ updateNetworkScore();
+ break;
default:
loge("Unhandled event " + eventToString(msg.what));
break;
@@ -2353,14 +2406,7 @@
DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
// Check if the network is non-VoPS.
if (dsri != null && dsri.getVopsSupportInfo() != null
- && !dsri.getVopsSupportInfo().isVopsSupported()
- // Reflect the actual MMTEL if flag on.
- && (mFlags.allowMmtelInNonVops()
- // Deceive Connectivity service to satisfy an MMTEL request, this should
- // be useless because we reach here if no MMTEL request, then removing
- // MMTEL capability shouldn't have any impacts.
- || !mDataConfigManager.shouldKeepNetworkUpInNonVops(
- nri.getNetworkRegistrationState()))) {
+ && !dsri.getVopsSupportInfo().isVopsSupported()) {
builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
log("updateNetworkCapabilities: dsri=" + dsri);
@@ -2488,9 +2534,7 @@
// Check if the feature force MMS on IWLAN is enabled. When the feature is enabled, MMS
// will be attempted on IWLAN if possible, even if existing cellular networks already
// supports IWLAN.
- if (mFlags.forceIwlanMms() && builder.build()
- .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
+ if (builder.build().hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
// If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on
// IWLAN, then we need to remove the MMS capability on the cellular network. This will
// allow the new MMS network to be brought up on IWLAN when MMS network request arrives.
@@ -3313,6 +3357,12 @@
return mLinkStatus;
}
+ /**
+ * Update the network score and report to connectivity service if necessary.
+ */
+ private void updateNetworkScore() {
+ updateNetworkScore(isHandoverInProgress());
+ }
/**
* Update the network score and report to connectivity service if necessary.
@@ -3322,10 +3372,18 @@
private void updateNetworkScore(boolean keepConnectedForHandover) {
int connectedReason = keepConnectedForHandover
? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER : NetworkScore.KEEP_CONNECTED_NONE;
- if (mNetworkScore.getKeepConnectedReason() != connectedReason) {
- mNetworkScore = new NetworkScore.Builder()
- .setKeepConnectedReason(connectedReason).build();
+ if (mNetworkScore.getKeepConnectedReason() != connectedReason
+ || (mFlags.supportNetworkProvider()
+ && mNetworkScore.isTransportPrimary() != mOnPreferredDataPhone)) {
+ NetworkScore.Builder builder = new NetworkScore.Builder()
+ .setKeepConnectedReason(connectedReason);
+ if (mFlags.supportNetworkProvider()) {
+ builder.setTransportPrimary(mOnPreferredDataPhone);
+ }
+ mNetworkScore = builder.build();
mNetworkAgent.sendNetworkScore(mNetworkScore);
+ logl("updateNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
+ + ", keepConnectedForHandover=" + keepConnectedForHandover);
}
}
@@ -3359,7 +3417,7 @@
public int getApnTypeNetworkCapability() {
if (!mAttachedNetworkRequestList.isEmpty()) {
// The highest priority network request is always at the top of list.
- return mAttachedNetworkRequestList.get(0).getApnTypeNetworkCapability();
+ return mAttachedNetworkRequestList.get(0).getHighestPriorityApnTypeNetworkCapability();
} else {
return Arrays.stream(getNetworkCapabilities().getCapabilities()).boxed()
.filter(cap -> DataUtils.networkCapabilityToApnType(cap)
@@ -4054,12 +4112,14 @@
pw.println("Tag: " + name());
pw.increaseIndent();
pw.println("mSubId=" + mSubId);
+ pw.println("mOnPreferredDataPhone=" + mOnPreferredDataPhone);
pw.println("mTransport=" + AccessNetworkConstants.transportTypeToString(mTransport));
pw.println("mLastKnownDataNetworkType=" + TelephonyManager
.getNetworkTypeName(mLastKnownDataNetworkType));
pw.println("WWAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
pw.println("WLAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
pw.println("mNetworkScore=" + mNetworkScore);
+ pw.println("keepConnectedReason=" + mNetworkScore.getKeepConnectedReason());
pw.println("mDataAllowedReason=" + mDataAllowedReason);
pw.println("mPduSessionId=" + mPduSessionId);
pw.println("mDataProfile=" + mDataProfile);
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 010e0fe..9e432e1 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1299,6 +1299,13 @@
* @param networkRequest The network request.
*/
private void onAddNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
+ // TelephonyNetworkRequest at TelephonyNetworkProvider layer does not have config assigned
+ // (Because TelephonyNetworkProvider is a singleton across all SIMs. We are not able to
+ // retrieve the right carrier config for it.). So as soon as the request arrives
+ // DataNetworkController, we need to update the config in the request so it can update
+ // some of its config-dependent properties like request priority.
+ networkRequest.updateDataConfig(mDataConfigManager);
+
// To detect IMS back-to-back release-request anomaly event
if (mLastImsOperationIsRelease) {
mLastImsOperationIsRelease = false;
@@ -1501,11 +1508,9 @@
.build(), mPhone, mFeatureFlags);
// If we don't skip checking existing network, then we should check If one of the
// existing networks can satisfy the internet request, then internet is allowed.
- if ((!mFeatureFlags.ignoreExistingNetworksForInternetAllowedChecking()
- || !ignoreExistingNetworks)
- && mDataNetworkList.stream().anyMatch(
- dataNetwork -> internetRequest.canBeSatisfiedBy(
- dataNetwork.getNetworkCapabilities()))) {
+ if (!ignoreExistingNetworks && mDataNetworkList.stream().anyMatch(
+ dataNetwork -> internetRequest.canBeSatisfiedBy(
+ dataNetwork.getNetworkCapabilities()))) {
return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY);
}
@@ -1579,7 +1584,7 @@
@NonNull TelephonyNetworkRequest networkRequest, DataEvaluationReason reason) {
DataEvaluation evaluation = new DataEvaluation(reason);
int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
- networkRequest.getApnTypeNetworkCapability());
+ networkRequest.getHighestPriorityApnTypeNetworkCapability());
// Check if the request can be satisfied by cellular network or satellite network.
if (mFeatureFlags.satelliteInternet()
@@ -1711,7 +1716,7 @@
if (mDataSettingsManager.isDataInitialized()) {
if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
- networkRequest.getApnTypeNetworkCapability()))) {
+ networkRequest.getHighestPriorityApnTypeNetworkCapability()))) {
evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
}
} else {
@@ -1746,7 +1751,9 @@
// Check if request is unmetered (WiFi or unmetered APN).
evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
} else if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
- if (!networkRequest.isMeteredRequest()) {
+ boolean isMeteredRequest = mDataConfigManager.isAnyMeteredCapability(
+ networkRequest.getCapabilities(), mServiceState.getDataRoaming());
+ if (!isMeteredRequest) {
evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
}
}
@@ -1985,7 +1992,7 @@
if (mAllNetworkRequestList.stream()
.filter(request -> dataNetwork.getTransport()
== mAccessNetworksManager.getPreferredTransportByNetworkCapability(
- request.getApnTypeNetworkCapability()))
+ request.getHighestPriorityApnTypeNetworkCapability()))
.filter(request
-> !hasCapabilityExemptsFromSinglePdnRule(request.getCapabilities()))
.anyMatch(request -> request.getPriority() > dataNetwork.getPriority())) {
@@ -2507,6 +2514,30 @@
}
private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest request) {
+ if (mFeatureFlags.supportNetworkProvider()) {
+ if (!mAllNetworkRequestList.remove(request)) {
+ loge("onRemoveNetworkRequest: Network request does not exist. " + request);
+ return;
+ }
+
+ if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+ mImsThrottleCounter.addOccurrence();
+ mLastReleasedImsRequestCapabilities = request.getCapabilities();
+ mLastImsOperationIsRelease = true;
+ }
+
+ if (request.getAttachedNetwork() != null) {
+ request.getAttachedNetwork().detachNetworkRequest(
+ request, false /* shouldRetry */);
+ }
+
+ request.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+ request.setEvaluation(null);
+
+ log("onRemoveNetworkRequest: Removed " + request);
+ return;
+ }
+
// The request generated from telephony network factory does not contain the information
// the original request has, for example, attached data network. We need to find the
// original one.
@@ -2527,7 +2558,7 @@
if (networkRequest.getAttachedNetwork() != null) {
networkRequest.getAttachedNetwork().detachNetworkRequest(
- networkRequest, false /* shouldRetry */);
+ networkRequest, false /* shouldRetry */);
}
log("onRemoveNetworkRequest: Removed " + networkRequest);
}
@@ -2869,7 +2900,7 @@
}
int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
- networkRequestList.get(0).getApnTypeNetworkCapability());
+ networkRequestList.get(0).getHighestPriorityApnTypeNetworkCapability());
logl("Creating data network on "
+ AccessNetworkConstants.transportTypeToString(transport) + " with " + dataProfile
+ ", and attaching " + networkRequestList.size() + " network requests to it.");
@@ -3141,7 +3172,8 @@
log("onDataNetworkSetupRetry: Request list:" + requestList);
TelephonyNetworkRequest telephonyNetworkRequest = requestList.get(0);
- int networkCapability = telephonyNetworkRequest.getApnTypeNetworkCapability();
+ int networkCapability = telephonyNetworkRequest
+ .getHighestPriorityApnTypeNetworkCapability();
int preferredTransport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
networkCapability);
if (preferredTransport != dataSetupRetryEntry.transport) {
@@ -3163,7 +3195,7 @@
telephonyNetworkRequest, DataEvaluationReason.DATA_RETRY);
if (!evaluation.containsDisallowedReasons()) {
DataProfile dataProfile = dataSetupRetryEntry.dataProfile;
- if (dataProfile == null) {
+ if (dataProfile == null || !mDataProfileManager.isDataProfileCompatible(dataProfile)) {
dataProfile = evaluation.getCandidateDataProfile();
}
if (dataProfile != null) {
@@ -3511,15 +3543,6 @@
}
/**
- * Called when SIM is absent.
- */
- private void onSimAbsent() {
- log("onSimAbsent");
- sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
- DataEvaluationReason.SIM_REMOVAL));
- }
-
- /**
* Called when SIM state changes.
*
* @param simState SIM state. (Note this is mixed with card state and application state.)
@@ -3527,13 +3550,22 @@
private void onSimStateChanged(@SimState int simState) {
log("onSimStateChanged: state=" + TelephonyManager.simStateToString(simState));
if (mSimState != simState) {
- mSimState = simState;
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
- onSimAbsent();
+ log("onSimStateChanged: SIM absent.");
+ sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
+ DataEvaluationReason.SIM_REMOVAL));
+ } else if (simState == TelephonyManager.SIM_STATE_NOT_READY
+ && mSimState == TelephonyManager.SIM_STATE_LOADED) {
+ if (mFeatureFlags.simDisabledGracefulTearDown()) {
+ log("onSimStateChanged: SIM disabled.");
+ sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
+ DataEvaluationReason.SIM_DISABLED));
+ }
} else if (simState == TelephonyManager.SIM_STATE_LOADED) {
sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
DataEvaluationReason.SIM_LOADED));
}
+ mSimState = simState;
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onSimStateChanged(mSimState)));
}
@@ -3609,8 +3641,7 @@
dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry);
} else if (dataNetwork.shouldDelayImsTearDownDueToInCall()
&& (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE)
- || mFeatureFlags.relaxHoTeardown() && dataEvaluation.isSubsetOf(
- DataDisallowedReason.NOT_IN_SERVICE,
+ || dataEvaluation.isSubsetOf(DataDisallowedReason.NOT_IN_SERVICE,
DataDisallowedReason.NOT_ALLOWED_BY_POLICY))) {
// We try our best to preserve the voice call by retrying later
if (dataHandoverRetryEntry != null) {
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index c50d50a..28fe935 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -432,35 +432,18 @@
*/
private void onInternetDataNetworkConnected(@NonNull Set<DataNetwork> internetNetworks) {
DataProfile defaultProfile = null;
- if (mFeatureFlags.refinePreferredDataProfileSelection()) {
- // Most of the cases there should be only one.
- // but in case there are multiple, find the default internet network, and choose the
- // one which has longest life cycle.
- defaultProfile = internetNetworks.stream()
- .filter(network -> mPreferredDataProfile == null
- // Find the one most resembles the current preferred profile,
- // avoiding e.g. DUN default network.
- || canPreferredDataProfileSatisfy(
- network.getAttachedNetworkRequestList()))
- .map(DataNetwork::getDataProfile)
- .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
- .orElse(null);
- } else {
- if (internetNetworks.size() == 1) {
- // Most of the cases there should be only one.
- defaultProfile = internetNetworks.stream().findFirst().get().getDataProfile();
- } else if (internetNetworks.size() > 1) {
- // but in case there are multiple, find the default internet network, and choose the
- // one which has longest life cycle.
- defaultProfile = internetNetworks.stream()
- .filter(network -> mPreferredDataProfile == null
- || canPreferredDataProfileSatisfy(
- network.getAttachedNetworkRequestList()))
- .map(DataNetwork::getDataProfile)
- .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
- .orElse(null);
- }
- }
+ // Most of the cases there should be only one.
+ // but in case there are multiple, find the default internet network, and choose the
+ // one which has longest life cycle.
+ defaultProfile = internetNetworks.stream()
+ .filter(network -> mPreferredDataProfile == null
+ // Find the one most resembles the current preferred profile,
+ // avoiding e.g. DUN default network.
+ || canPreferredDataProfileSatisfy(
+ network.getAttachedNetworkRequestList()))
+ .map(DataNetwork::getDataProfile)
+ .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
+ .orElse(null);
// Update a working internet data profile by subid as a future candidate for preferred
// data profile after APNs are reset to default
diff --git a/src/java/com/android/internal/telephony/data/DataRetryManager.java b/src/java/com/android/internal/telephony/data/DataRetryManager.java
index d35e9e8..318c4b5 100644
--- a/src/java/com/android/internal/telephony/data/DataRetryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataRetryManager.java
@@ -22,11 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.NetworkCapabilities;
import android.os.AsyncResult;
import android.os.Handler;
@@ -79,11 +74,6 @@
public class DataRetryManager extends Handler {
private static final boolean VDBG = false;
- /** Intent of Alarm Manager for long retry timer. */
- private static final String ACTION_RETRY = "com.android.internal.telephony.data.ACTION_RETRY";
- /** The extra key for the hashcode of the retry entry for Alarm Manager. */
- private static final String ACTION_RETRY_EXTRA_HASHCODE = "extra_retry_hashcode";
-
/** Event for data setup retry. */
private static final int EVENT_DATA_SETUP_RETRY = 3;
@@ -1078,22 +1068,6 @@
mRil.registerForOn(this, EVENT_RADIO_ON, null);
mRil.registerForModemReset(this, EVENT_MODEM_RESET, null);
- if (!mFlags.useAlarmCallback()) {
- // Register intent of alarm manager for long retry timer
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_RETRY);
- mPhone.getContext().registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_RETRY.equals(intent.getAction())) {
- DataRetryManager.this.onAlarmIntentRetry(
- intent.getIntExtra(ACTION_RETRY_EXTRA_HASHCODE,
- -1 /*Bad hashcode*/));
- }
- }
- }, intentFilter);
- }
-
if (mDataConfigManager.shouldResetDataThrottlingWhenTacChanges()) {
mPhone.getServiceStateTracker().registerForAreaCodeChanged(this, EVENT_TAC_CHANGED,
null);
@@ -1277,7 +1251,8 @@
return;
}
for (NetworkRequestList networkRequestList : groupedNetworkRequestLists) {
- int capability = networkRequestList.get(0).getApnTypeNetworkCapability();
+ int capability = networkRequestList.get(0)
+ .getHighestPrioritySupportedNetworkCapability();
if (retryRule.canBeMatched(capability, cause)) {
// Check if there is already a similar network request retry scheduled.
if (isSimilarNetworkRequestRetryScheduled(
@@ -1492,7 +1467,8 @@
mPhone.getCarrierId());
continue;
}
- if (entry.networkRequestList.get(0).getApnTypeNetworkCapability()
+ if (entry.networkRequestList.get(0)
+ .getHighestPrioritySupportedNetworkCapability()
== networkCapability
&& entry.appliedDataRetryRule.equals(dataRetryRule)) {
if (entry.getState() == DataRetryEntry.RETRY_STATE_SUCCEEDED
@@ -1529,32 +1505,19 @@
? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY, dataRetryEntry),
dataRetryEntry.retryDelayMillis);
} else {
- if (mFlags.useAlarmCallback()) {
- // No need to wake up the device, the retry can wait util next time the device wake
- // up to save power.
- mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
- dataRetryEntry.retryElapsedTime,
- "dataRetryHash-" + dataRetryEntry.hashCode() /*debug tag*/,
- Runnable::run,
- null /*worksource*/,
- () -> {
- logl("onAlarm retry " + dataRetryEntry);
- sendMessage(obtainMessage(dataRetryEntry instanceof DataSetupRetryEntry
- ? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY,
- dataRetryEntry));
- });
- } else {
- Intent intent = new Intent(ACTION_RETRY);
- intent.putExtra(ACTION_RETRY_EXTRA_HASHCODE, dataRetryEntry.hashCode());
- // No need to wake up the device, the retry can wait util next time the device wake
- // up to save power.
- mAlarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
- dataRetryEntry.retryElapsedTime,
- PendingIntent.getBroadcast(mPhone.getContext(),
- dataRetryEntry.hashCode()/*Unique identifier of the retry attempt*/,
- intent,
- PendingIntent.FLAG_IMMUTABLE));
- }
+ // No need to wake up the device, the retry can wait util next time the device wake
+ // up to save power.
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
+ dataRetryEntry.retryElapsedTime,
+ "dataRetryHash-" + dataRetryEntry.hashCode() /*debug tag*/,
+ Runnable::run,
+ null /*worksource*/,
+ () -> {
+ logl("onAlarm retry " + dataRetryEntry);
+ sendMessage(obtainMessage(dataRetryEntry instanceof DataSetupRetryEntry
+ ? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY,
+ dataRetryEntry));
+ });
}
}
@@ -1599,8 +1562,7 @@
// transport.
mDataThrottlingEntries.removeIf(
throttlingEntry -> dataProfile.equals(throttlingEntry.dataProfile)
- && (!mFlags.unthrottleCheckTransport()
- || throttlingEntry.transport == transport));
+ && (throttlingEntry.transport == transport));
if (mDataThrottlingEntries.size() >= MAXIMUM_HISTORICAL_ENTRIES) {
// If we don't see the anomaly report after U release, we should remove this check for
@@ -1649,7 +1611,7 @@
// profile manager.
Stream<DataThrottlingEntry> stream = mDataThrottlingEntries.stream();
stream = stream.filter(entry -> entry.expirationTimeMillis > now
- && (!mFlags.unthrottleCheckTransport() || entry.transport == transport));
+ && entry.transport == transport);
if (dataProfile.getApnSetting() != null) {
stream = stream
.filter(entry -> entry.dataProfile.getApnSetting() != null)
@@ -1779,8 +1741,9 @@
mPhone.getCarrierId());
continue;
}
- if (entry.networkRequestList.get(0).getApnTypeNetworkCapability()
- == networkRequest.getApnTypeNetworkCapability()
+ if (entry.networkRequestList.get(0)
+ .getHighestPrioritySupportedNetworkCapability()
+ == networkRequest.getHighestPrioritySupportedNetworkCapability()
&& entry.transport == transport) {
return true;
}
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index fb112d9..0b9ac27 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -326,7 +326,7 @@
@Override
public void onUserDataEnabledChanged(boolean enabled,
@NonNull String callingPackage) {
- log("phone" + phone.getPhoneId() + " onUserDataEnabledChanged "
+ log("phone " + phone.getPhoneId() + " onUserDataEnabledChanged "
+ enabled + " by " + callingPackage
+ ", reevaluating mobile data policies");
DataSettingsManager.this.updateDataEnabledAndNotify(
@@ -335,6 +335,16 @@
});
}
}
+ SubscriptionManagerService.getInstance().registerCallback(
+ new SubscriptionManagerService.SubscriptionManagerServiceCallback(this::post) {
+ @Override
+ public void onDefaultDataSubscriptionChanged(int subId) {
+ log((subId == mSubId ? "Became" : "Not")
+ + " default data sub, reevaluating mobile data policies");
+ DataSettingsManager.this.updateDataEnabledAndNotify(
+ TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+ }
+ });
updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
}
diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
index b9b60a0..42e1a78 100644
--- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
@@ -32,6 +32,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.ValidationStatus;
@@ -714,7 +715,12 @@
// Put the bundled stats extras on the intent.
intent.putExtra("EXTRA_DSRS_STATS_BUNDLE", bundle);
- mPhone.getContext().sendBroadcast(intent, READ_PRIVILEGED_PHONE_STATE);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mPhone.getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
+ READ_PRIVILEGED_PHONE_STATE);
+ } else {
+ mPhone.getContext().sendBroadcast(intent, READ_PRIVILEGED_PHONE_STATE);
+ }
}
/** Recovery Action: RECOVERY_ACTION_GET_DATA_CALL_LIST */
diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java
index 20da97f..c88e0b3 100644
--- a/src/java/com/android/internal/telephony/data/DataUtils.java
+++ b/src/java/com/android/internal/telephony/data/DataUtils.java
@@ -287,6 +287,8 @@
case NetworkCapabilities.NET_CAPABILITY_VSIM -> ApnSetting.TYPE_VSIM;
case NetworkCapabilities.NET_CAPABILITY_BIP -> ApnSetting.TYPE_BIP;
case NetworkCapabilities.NET_CAPABILITY_RCS -> ApnSetting.TYPE_RCS;
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> ApnSetting.TYPE_OEM_PAID;
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> ApnSetting.TYPE_OEM_PRIVATE;
default -> ApnSetting.TYPE_NONE;
};
}
@@ -315,6 +317,8 @@
case ApnSetting.TYPE_VSIM -> NetworkCapabilities.NET_CAPABILITY_VSIM;
case ApnSetting.TYPE_ENTERPRISE -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
case ApnSetting.TYPE_RCS -> NetworkCapabilities.NET_CAPABILITY_RCS;
+ case ApnSetting.TYPE_OEM_PAID -> NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+ case ApnSetting.TYPE_OEM_PRIVATE -> NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE;
default -> -1;
};
}
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 27b4331..62d33d9 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -30,6 +30,7 @@
import static java.util.Arrays.copyOf;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -63,6 +64,7 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseIntArray;
@@ -89,6 +91,7 @@
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
import com.android.internal.telephony.subscription.SubscriptionManagerService.WatchedInt;
import com.android.internal.util.IndentingPrintWriter;
import com.android.telephony.Rlog;
@@ -182,6 +185,27 @@
}
}
+ /**
+ * Callback from PhoneSwitcher
+ */
+ public static class PhoneSwitcherCallback extends DataCallback {
+ /**
+ * Constructor
+ *
+ * @param executor The executor of the callback.
+ */
+ public PhoneSwitcherCallback(@NonNull @CallbackExecutor Executor executor) {
+ super(executor);
+ }
+
+ /**
+ * Called when preferred data phone id changed.
+ *
+ * @param phoneId The phone id of the preferred data.
+ */
+ public void onPreferredDataPhoneIdChanged(int phoneId) {}
+ }
+
@NonNull
private final NetworkRequestList mNetworkRequestList = new NetworkRequestList();
protected final RegistrantList mActivePhoneRegistrants;
@@ -260,6 +284,10 @@
private ISetOpportunisticDataCallback mSetOpptSubCallback;
+ /** Phone switcher callbacks. */
+ @NonNull
+ private final Set<PhoneSwitcherCallback> mPhoneSwitcherCallbacks = new ArraySet<>();
+
private static final int EVENT_PRIMARY_DATA_SUB_CHANGED = 101;
protected static final int EVENT_SUBSCRIPTION_CHANGED = 102;
private static final int EVENT_REQUEST_NETWORK = 103;
@@ -467,6 +495,24 @@
}
}
+ /**
+ * Register the callback for receiving information from {@link PhoneSwitcher}.
+ *
+ * @param callback The callback.
+ */
+ public void registerCallback(@NonNull PhoneSwitcherCallback callback) {
+ mPhoneSwitcherCallbacks.add(callback);
+ }
+
+ /**
+ * Unregister the callback for receiving information from {@link PhoneSwitcher}.
+ *
+ * @param callback The callback.
+ */
+ public void unregisterCallback(@NonNull PhoneSwitcherCallback callback) {
+ mPhoneSwitcherCallbacks.remove(callback);
+ }
+
private void evaluateIfImmediateDataSwitchIsNeeded(String evaluationReason, int switchReason) {
if (onEvaluate(REQUESTS_UNCHANGED, evaluationReason)) {
logDataSwitchEvent(mPreferredDataSubId.get(),
@@ -587,54 +633,54 @@
};
mAutoDataSwitchController = new AutoDataSwitchController(context, looper, this,
mFlags, mAutoDataSwitchCallback);
-
- mContext.registerReceiver(mDefaultDataChangedReceiver,
- new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
+ if (!mFlags.ddsCallback()) {
+ mContext.registerReceiver(mDefaultDataChangedReceiver,
+ new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
+ } else {
+ mSubscriptionManagerService.registerCallback(new SubscriptionManagerServiceCallback(
+ this::post) {
+ @Override
+ public void onDefaultDataSubscriptionChanged(int subId) {
+ evaluateIfImmediateDataSwitchIsNeeded("default data sub changed to " + subId,
+ DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL);
+ }
+ });
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
- final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MCX)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
- .setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ if (!mFlags.supportNetworkProvider()) {
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
+ .setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
+ .forEach(builder::addCapability);
- if (mFlags.satelliteInternet()) {
- // TODO: b/328622096 remove the try/catch
- try {
- builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
- } catch (IllegalArgumentException exception) {
- loge("TRANSPORT_SATELLITE is not supported.");
+ if (mFlags.satelliteInternet()) {
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ loge("TRANSPORT_SATELLITE is not supported.");
+ }
}
- }
- NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
- builder.build(), this);
- // we want to see all requests
- networkFactory.registerIgnoringScore();
+ NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
+ builder.build(), this);
+ // we want to see all requests
+ networkFactory.registerIgnoringScore();
+ }
updateHalCommandToUse();
@@ -1054,11 +1100,12 @@
return false;
}
+ // TODO: Remove after removing TelephonyNetworkFactory
private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory {
private final PhoneSwitcher mPhoneSwitcher;
public PhoneSwitcherNetworkRequestListener (Looper l, Context c,
NetworkCapabilities nc, PhoneSwitcher ps) {
- super(l, c, "PhoneSwitcherNetworkRequstListener", nc);
+ super(l, c, "PhoneSwitcherNetworkRequestListener", nc);
mPhoneSwitcher = ps;
}
@@ -1079,7 +1126,13 @@
}
}
- private void onRequestNetwork(NetworkRequest networkRequest) {
+ /**
+ * Called when receiving a network request.
+ *
+ * @param networkRequest The network request.
+ */
+ // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
+ public void onRequestNetwork(@NonNull NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (!mNetworkRequestList.contains(telephonyNetworkRequest)) {
@@ -1088,7 +1141,13 @@
}
}
- private void onReleaseNetwork(NetworkRequest networkRequest) {
+ /**
+ * Called when releasing a network request.
+ *
+ * @param networkRequest The network request to release.
+ */
+ // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
+ public void onReleaseNetwork(@NonNull NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (mNetworkRequestList.remove(telephonyNetworkRequest)) {
@@ -1102,18 +1161,6 @@
mDefaultNetworkCallback.mSwitchReason = reason;
}
- private void collectRequestNetworkMetrics(NetworkRequest networkRequest) {
- // Request network for MMS will temporary disable the network on default data subscription,
- // this only happen on multi-sim device.
- if (mActiveModemCount > 1 && networkRequest.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_MMS)) {
- OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
- onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
- onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_START;
- TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch);
- }
- }
-
private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
// Release network for MMS will recover the network on default data subscription, this only
// happen on multi-sim device.
@@ -1444,14 +1491,18 @@
mPreferredDataPhoneId = mEmergencyOverride.mPhoneId;
mLastSwitchPreferredDataReason = DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN;
} else {
- int imsRegTech = mImsRegTechProvider.get(mContext, mPhoneIdInVoiceCall);
- if (isAnyVoiceCallActiveOnDevice() && imsRegTech != REGISTRATION_TECH_IWLAN) {
- if (imsRegTech != REGISTRATION_TECH_CROSS_SIM) {
- mPreferredDataPhoneId = shouldSwitchDataDueToInCall()
- ? mPhoneIdInVoiceCall : getFallbackDataPhoneIdForInternetRequests();
+ if (isAnyVoiceCallActiveOnDevice()) {
+ int imsRegTech = mImsRegTechProvider.get(mContext, mPhoneIdInVoiceCall);
+ if (imsRegTech != REGISTRATION_TECH_IWLAN) {
+ if (imsRegTech != REGISTRATION_TECH_CROSS_SIM) {
+ mPreferredDataPhoneId = shouldSwitchDataDueToInCall()
+ ? mPhoneIdInVoiceCall : getFallbackDataPhoneIdForInternetRequests();
+ } else {
+ logl("IMS call on cross-SIM, skip switching data to phone "
+ + mPhoneIdInVoiceCall);
+ }
} else {
- logl("IMS call on cross-SIM, skip switching data to phone "
- + mPhoneIdInVoiceCall);
+ mPreferredDataPhoneId = getFallbackDataPhoneIdForInternetRequests();
}
} else {
mPreferredDataPhoneId = getFallbackDataPhoneIdForInternetRequests();
@@ -1562,6 +1613,7 @@
* If preferred phone changes, or phone activation status changes, registrants
* will be notified.
*/
+ // TODO: Remove after removing TelephonyNetworkFactory
public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
Registrant r = new Registrant(h, what, o);
mActivePhoneRegistrants.add(r);
@@ -1983,6 +2035,10 @@
// Notify all registrants
mActivePhoneRegistrants.notifyRegistrants();
notifyPreferredDataSubIdChanged();
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcherCallbacks.forEach(callback -> callback.invokeFromExecutor(
+ () -> callback.onPreferredDataPhoneIdChanged(phoneId)));
+ }
}
private boolean isPhoneIdValidForRetry(int phoneId) {
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
index ca34ca7..7d1746c 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
@@ -138,31 +138,19 @@
public NetworkCapabilities makeNetworkFilter(int subscriptionId) {
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MCX)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
- .setSubscriptionId(subscriptionId).build());
+ .setSubscriptionId(subscriptionId).build());
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
+ .forEach(builder::addCapability);
if (mFlags.satelliteInternet()) {
// TODO: b/328622096 remove the try/catch
@@ -206,7 +194,7 @@
private int getTransportTypeFromNetworkRequest(TelephonyNetworkRequest networkRequest) {
int transport = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
- int capability = networkRequest.getApnTypeNetworkCapability();
+ int capability = networkRequest.getHighestPriorityApnTypeNetworkCapability();
if (capability >= 0) {
transport = mAccessNetworksManager
.getPreferredTransportByNetworkCapability(capability);
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
new file mode 100644
index 0000000..63edefa
--- /dev/null
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 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.data;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
+import android.net.NetworkProvider.NetworkOfferCallback;
+import android.net.NetworkRequest;
+import android.net.NetworkScore;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.SubscriptionManager;
+import android.util.ArrayMap;
+import android.util.LocalLog;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Map;
+
+/**
+ * TelephonyNetworkProvider is a singleton network provider responsible for providing all
+ * telephony related networks including networks on cellular and IWLAN across all active SIMs.
+ */
+public class TelephonyNetworkProvider extends NetworkProvider implements NetworkOfferCallback {
+
+ public final String LOG_TAG = "TNP";
+
+ /** Android feature flags */
+ @NonNull
+ private final FeatureFlags mFlags;
+
+ /** The event handler */
+ @NonNull
+ private final Handler mHandler;
+
+ /** Phone switcher responsible to determine request routing on dual-SIM device */
+ @NonNull
+ private final PhoneSwitcher mPhoneSwitcher;
+
+ /** Network requests map. Key is the network request, value is the phone id it applies to. */
+ private final Map<TelephonyNetworkRequest, Integer> mNetworkRequests = new ArrayMap<>();
+
+ /** Persisted log */
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(256);
+
+ /**
+ * Constructor
+ *
+ * @param looper The looper for event handling
+ * @param context The context
+ * @param featureFlags Android feature flags
+ */
+ public TelephonyNetworkProvider(@NonNull Looper looper, @NonNull Context context,
+ @NonNull FeatureFlags featureFlags) {
+ super(context, looper, TelephonyNetworkProvider.class.getSimpleName());
+
+ mFlags = featureFlags;
+ mHandler = new Handler(looper);
+ mPhoneSwitcher = PhoneSwitcher.getInstance();
+
+ // Register for subscription changed event.
+ context.getSystemService(SubscriptionManager.class)
+ .addOnSubscriptionsChangedListener(mHandler::post,
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ logl("Subscription changed.");
+ reevaluateNetworkRequests("subscription changed");
+ }});
+
+ // Register for preferred data changed event
+ mPhoneSwitcher.registerCallback(new PhoneSwitcherCallback(mHandler::post) {
+ @Override
+ public void onPreferredDataPhoneIdChanged(int phoneId) {
+ logl("Preferred data sub phone id changed to " + phoneId);
+ reevaluateNetworkRequests("Preferred data subscription changed");
+ }
+ });
+
+ // Register the provider and tell connectivity service what network offer telephony can
+ // provide
+ ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
+ if (cm != null) {
+ cm.registerNetworkProvider(this);
+ NetworkCapabilities caps = makeNetworkFilter();
+ registerNetworkOffer(new NetworkScore.Builder().build(), caps, mHandler::post, this);
+ logl("registerNetworkOffer: " + caps);
+ }
+ }
+
+ /**
+ * Get the phone id for the network request.
+ *
+ * @param request The network request
+ * @return The id of the phone where the network request should route to. If the network request
+ * can't be applied to any phone, {@link SubscriptionManager#INVALID_PHONE_INDEX} will be
+ * returned.
+ */
+ private int getPhoneIdForNetworkRequest(@NonNull TelephonyNetworkRequest request) {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ int phoneId = phone.getPhoneId();
+ if (mPhoneSwitcher.shouldApplyNetworkRequest(request, phoneId)) {
+ // Return here because by design the network request can be only applied to *one*
+ // phone. It's not possible to have two DataNetworkController to attempt to setup
+ // data call for the same network request.
+ return phoneId;
+ }
+ }
+
+ return SubscriptionManager.INVALID_PHONE_INDEX;
+ }
+
+ /**
+ * Called when receiving a network request from connectivity service. This is the entry point
+ * that a network request arrives telephony.
+ *
+ * @param request The network request
+ */
+ @Override
+ public void onNetworkNeeded(@NonNull NetworkRequest request) {
+ TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(request, mFlags);
+ if (mNetworkRequests.containsKey(networkRequest)) {
+ loge("Duplicate network request " + networkRequest);
+ return;
+ }
+
+ mPhoneSwitcher.onRequestNetwork(request);
+
+ // Check with PhoneSwitcher to see where to route the request.
+ int phoneId = getPhoneIdForNetworkRequest(networkRequest);
+ if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ logl("onNetworkNeeded: phoneId=" + phoneId + ", " + networkRequest);
+ PhoneFactory.getPhone(phoneId).getDataNetworkController()
+ .addNetworkRequest(networkRequest);
+ } else {
+ logl("onNetworkNeeded: Not applied. " + networkRequest);
+ }
+
+ mNetworkRequests.put(networkRequest, phoneId);
+ }
+
+ /**
+ * Called when connectivity service remove the network request. Note this will not result in
+ * network tear down. Even there is no network request attached to the network, telephony still
+ * relies on {@link NetworkAgent#onNetworkUnwanted()} to tear down the network.
+ *
+ * @param request The released network request
+ *
+ * @see TelephonyNetworkAgent#onNetworkUnwanted()
+ */
+ @Override
+ public void onNetworkUnneeded(@NonNull NetworkRequest request) {
+ TelephonyNetworkRequest networkRequest = mNetworkRequests.keySet().stream()
+ .filter(r -> r.getNativeNetworkRequest().equals(request))
+ .findFirst()
+ .orElse(null);
+ if (networkRequest == null) {
+ loge("onNetworkUnneeded: Cannot find " + request);
+ return;
+ }
+
+ mPhoneSwitcher.onReleaseNetwork(request);
+ int phoneId = mNetworkRequests.remove(networkRequest);
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone != null) {
+ logl("onNetworkUnneeded: phoneId=" + phoneId + ", " + networkRequest);
+ // Remove the network request from network controller. Note this will not result
+ // in disconnecting the data network.
+ phone.getDataNetworkController().removeNetworkRequest(networkRequest);
+ } else {
+ loge("onNetworkUnneeded: Unable to get phone. phoneId=" + phoneId);
+ }
+ }
+
+ /**
+ * Re-evaluate the existing networks and re-apply to the applicable phone.
+ *
+ * @param reason The reason for re-evaluating network request. Note this can be only used for
+ * debugging message purposes.
+ */
+ private void reevaluateNetworkRequests(@NonNull String reason) {
+ logl("reevaluateNetworkRequests: " + reason + ".");
+ mNetworkRequests.forEach((request, oldPhoneId) -> {
+ int newPhoneId = getPhoneIdForNetworkRequest(request);
+ if (newPhoneId != oldPhoneId) {
+ // We need to move the request from old phone to the new phone. This can happen
+ // when the user changes the default data subscription.
+
+ if (oldPhoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ PhoneFactory.getPhone(oldPhoneId).getDataNetworkController()
+ .removeNetworkRequest(request);
+ }
+
+ if (newPhoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ PhoneFactory.getPhone(newPhoneId).getDataNetworkController()
+ .addNetworkRequest(request);
+ }
+
+ logl("Request moved. phoneId " + oldPhoneId + " -> " + newPhoneId + " " + request);
+ mNetworkRequests.put(request, newPhoneId);
+ }
+ });
+ }
+
+ /**
+ * @return The maximal network capabilities that telephony can support.
+ */
+ @NonNull
+ private NetworkCapabilities makeNetworkFilter() {
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
+ // Ideally TelephonyNetworkProvider should only accept TelephonyNetworkSpecifier,
+ // but this network provider is a singleton across all SIMs, and
+ // TelephonyNetworkSpecifier can't accept more than one subscription id, so we let
+ // the provider accepts all different kinds NetworkSpecifier.
+ .setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
+ .forEach(builder::addCapability);
+
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ log("TRANSPORT_SATELLITE is not supported.");
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Log debug message to logcat.
+ *
+ * @param s The debug message to log
+ */
+ private void log(@NonNull String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+
+ /**
+ * Log error debug messages to logcat.
+ * @param s The error debug messages
+ */
+ private void loge(@NonNull String s) {
+ Rlog.e(LOG_TAG, s);
+ }
+
+ /**
+ * Log to logcat and persisted local log.
+ *
+ * @param s The debug message to log
+ */
+ private void logl(@NonNull String s) {
+ log(s);
+ mLocalLog.log(s);
+ }
+
+ /**
+ * Dump the state of telephony network provider.
+ *
+ * @param fd File descriptor
+ * @param writer Print writer
+ * @param args Arguments
+ */
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println("TelephonyNetworkProvider:");
+ pw.increaseIndent();
+
+ pw.println("mPreferredDataPhoneId=" + mPhoneSwitcher.getPreferredDataPhoneId());
+ int defaultDataSubId = SubscriptionManagerService.getInstance().getDefaultDataSubId();
+ pw.println("DefaultDataSubId=" + defaultDataSubId);
+ pw.println("DefaultDataPhoneId=" + SubscriptionManagerService.getInstance()
+ .getPhoneId(defaultDataSubId));
+
+ pw.println("Registered capabilities: " + makeNetworkFilter());
+ pw.println("Network requests:");
+ pw.increaseIndent();
+ for (Phone phone : PhoneFactory.getPhones()) {
+ pw.println("Phone " + phone.getPhoneId() + ":");
+ pw.increaseIndent();
+ mNetworkRequests.forEach((request, phoneId) -> {
+ if (phoneId == phone.getPhoneId()) {
+ pw.println(request);
+ }
+ });
+ pw.decreaseIndent();
+ }
+ pw.println("Not applied requests:");
+ pw.increaseIndent();
+ mNetworkRequests.forEach((request, phoneId) -> {
+ if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
+ pw.println(request);
+ }
+ });
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ pw.println();
+ pw.println("Local logs:");
+ pw.increaseIndent();
+ mLocalLog.dump(fd, pw, args);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
index 117eb36..ca1ca21 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
@@ -137,10 +137,6 @@
CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN)
);
- /** The phone instance. */
- @NonNull
- private final Phone mPhone;
-
/**
* Native network request from the clients. See {@link NetworkRequest};
*/
@@ -164,8 +160,8 @@
/**
* Data config manager for retrieving data config.
*/
- @NonNull
- private final DataConfigManager mDataConfigManager;
+ @Nullable
+ private DataConfigManager mDataConfigManager;
/**
* The attached data network. Note that the data network could be in any state. {@code null}
@@ -205,7 +201,19 @@
*/
public TelephonyNetworkRequest(@NonNull NetworkRequest request, @NonNull Phone phone,
@NonNull FeatureFlags featureFlags) {
- mPhone = phone;
+ this(request, featureFlags);
+ mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
+ updatePriority();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param request The native network request from the clients.
+ * @param featureFlags The feature flag
+ */
+ public TelephonyNetworkRequest(@NonNull NetworkRequest request,
+ @NonNull FeatureFlags featureFlags) {
mNativeNetworkRequest = request;
mFeatureFlags = featureFlags;
@@ -222,7 +230,15 @@
// to satisfy it.
mState = REQUEST_STATE_UNSATISFIED;
mCreatedTimeMillis = SystemClock.elapsedRealtime();
- mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
+ }
+
+ /**
+ * Update the associated data config manager.
+ *
+ * @param dataConfigManager Data config manager
+ */
+ public void updateDataConfig(@NonNull DataConfigManager dataConfigManager) {
+ mDataConfigManager = dataConfigManager;
updatePriority();
}
@@ -315,13 +331,15 @@
if (mNativeNetworkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
&& !mNativeNetworkRequest.hasTransport(
NetworkCapabilities.TRANSPORT_SATELLITE)) {
- if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
- .getForcedCellularTransportCapabilities()::contains)) {
- // If the request is explicitly for the cellular, then the data profile
- // needs to support cellular.
- if (!dataProfile.getApnSetting().isForInfrastructure(
- ApnSetting.INFRASTRUCTURE_CELLULAR)) {
- return false;
+ if (mDataConfigManager != null) {
+ if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
+ .getForcedCellularTransportCapabilities()::contains)) {
+ // If the request is explicitly for the cellular, then the data profile
+ // needs to support cellular.
+ if (!dataProfile.getApnSetting().isForInfrastructure(
+ ApnSetting.INFRASTRUCTURE_CELLULAR)) {
+ return false;
+ }
}
}
} else if (mNativeNetworkRequest.hasTransport(
@@ -371,10 +389,12 @@
* Update the priority from data config manager.
*/
public void updatePriority() {
- mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
- .map(mDataConfigManager::getNetworkCapabilityPriority)
- .max()
- .orElse(0);
+ if (mDataConfigManager != null) {
+ mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
+ .map(mDataConfigManager::getNetworkCapabilityPriority)
+ .max()
+ .orElse(0);
+ }
}
/**
@@ -385,13 +405,41 @@
* if there is no APN type capabilities in this network request.
*/
@NetCapability
- public int getApnTypeNetworkCapability() {
+ public int getHighestPriorityApnTypeNetworkCapability() {
if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1;
+ if (mDataConfigManager == null) return -1;
return Arrays.stream(getCapabilities()).boxed()
.filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
.max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
.orElse(-1);
}
+
+ /**
+ * A parent set of {@link #getHighestPriorityApnTypeNetworkCapability()}.
+ * Get the network capability from the network request that can lead to data setup. If there are
+ * multiple capabilities, the highest priority one will be returned.
+ *
+ * @return The highest priority traffic descriptor type network capability from this network
+ * request. -1 if there is no traffic descriptor type capabilities in this network request.
+ */
+ @NetCapability
+ public int getHighestPrioritySupportedNetworkCapability() {
+ if (mDataConfigManager == null) return -1;
+ return Arrays.stream(getCapabilities()).boxed()
+ .filter(CAPABILITY_ATTRIBUTE_MAP::containsKey)
+ .max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
+ .orElse(-1);
+ }
+
+ /**
+ * @return Get all the network capabilities that can lead to data setup.
+ */
+ @NonNull
+ @NetCapability
+ public static List<Integer> getAllSupportedNetworkCapabilities() {
+ return CAPABILITY_ATTRIBUTE_MAP.keySet().stream().toList();
+ }
+
/**
* @return The native network request.
*/
@@ -440,7 +488,7 @@
*
* @param evaluation The data evaluation result.
*/
- public void setEvaluation(@NonNull DataEvaluation evaluation) {
+ public void setEvaluation(@Nullable DataEvaluation evaluation) {
mEvaluation = evaluation;
}
@@ -461,14 +509,6 @@
}
/**
- * @return {@code true} if this network request can result in bringing up a metered network.
- */
- public boolean isMeteredRequest() {
- return mDataConfigManager.isAnyMeteredCapability(
- getCapabilities(), mPhone.getServiceState().getDataRoaming());
- }
-
- /**
* Get Os/App id from the network request.
*
* @return Os/App id. {@code null} if the request does not have traffic descriptor based network
@@ -521,7 +561,7 @@
return "[" + mNativeNetworkRequest + ", mPriority=" + mPriority
+ ", state=" + requestStateToString(mState)
+ ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
- ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
+ ? mAttachedDataNetwork.name() : null)
+ ", created time=" + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
+ ", evaluation result=" + mEvaluation + "]";
}
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index fddeb06..681ca12 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -43,6 +43,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.IDomainSelector;
import com.android.internal.telephony.ITransportSelectorCallback;
import com.android.internal.telephony.ITransportSelectorResultCallback;
@@ -50,6 +51,7 @@
import com.android.internal.telephony.IWwanSelectorResultCallback;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
import java.io.PrintWriter;
@@ -69,7 +71,9 @@
protected static final int EVENT_SERVICE_CONNECTED = 3;
protected static final int EVENT_SERVICE_BINDING_TIMEOUT = 4;
protected static final int EVENT_RESET_NETWORK_SCAN_DONE = 5;
- protected static final int EVENT_LAST = EVENT_RESET_NETWORK_SCAN_DONE;
+ protected static final int EVENT_TRIGGER_NETWORK_SCAN_DONE = 6;
+ protected static final int EVENT_MODEM_RESET = 7;
+ protected static final int EVENT_LAST = EVENT_MODEM_RESET;
private static final int DEFAULT_BIND_RETRY_TIMEOUT_MS = 4 * 1000;
@@ -185,7 +189,10 @@
return;
}
DomainSelectionConnection.this.onSelectionTerminated(cause);
- dispose();
+ if (!Flags.hangupEmergencyCallForCrossSimRedialing()
+ || !mIsEmergency || !checkState(STATUS_DOMAIN_SELECTED)) {
+ dispose();
+ }
}
}
}
@@ -304,6 +311,23 @@
mPendingScanRequest.mScanType, false);
}
break;
+ case EVENT_TRIGGER_NETWORK_SCAN_DONE:
+ synchronized (mLock) {
+ if (checkState(STATUS_DISPOSED) || !checkState(STATUS_WAIT_SCAN_RESULT)) {
+ return;
+ }
+ ar = (AsyncResult) msg.obj;
+ if (ar != null && ar.exception != null) {
+ onTriggerNetworkScanError((Integer) ar.userObj,
+ ((CommandException) ar.exception).getCommandError());
+ }
+ }
+ break;
+ case EVENT_MODEM_RESET:
+ synchronized (mLock) {
+ onModemReset();
+ }
+ break;
default:
loge("handleMessage unexpected msg=" + msg.what);
break;
@@ -528,10 +552,13 @@
if (!mRegisteredRegistrant) {
mPhone.registerForEmergencyNetworkScan(mHandler,
EVENT_EMERGENCY_NETWORK_SCAN_RESULT, null);
+ mPhone.mCi.registerForModemReset(mHandler, EVENT_MODEM_RESET, null);
mRegisteredRegistrant = true;
}
setState(STATUS_WAIT_SCAN_RESULT);
- mPhone.triggerEmergencyNetworkScan(preferredNetworks, scanType, null);
+ mPhone.triggerEmergencyNetworkScan(preferredNetworks, scanType,
+ mHandler.obtainMessage(EVENT_TRIGGER_NETWORK_SCAN_DONE,
+ Integer.valueOf(scanType)));
mPendingScanRequest = null;
}
}
@@ -721,6 +748,7 @@
setState(STATUS_DISPOSED);
if (mRegisteredRegistrant) {
mPhone.unregisterForEmergencyNetworkScan(mHandler);
+ mPhone.mCi.unregisterForModemReset(mHandler);
mRegisteredRegistrant = false;
}
onCancel(true);
@@ -745,6 +773,48 @@
}
}
+ private void onTriggerNetworkScanError(int scanType, CommandException.Error error) {
+ loge("onTriggerNetworkScanError scanType=" + scanType + ", error=" + error);
+
+ if (shouldTerminateCallOnRadioNotAvailable()
+ && error == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ clearState(STATUS_WAIT_SCAN_RESULT);
+ onSelectionTerminated(DisconnectCause.POWER_OFF);
+ dispose();
+ return;
+ }
+
+ if (scanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE) {
+ // Handle as unknown network.
+ EmergencyRegistrationResult result = new EmergencyRegistrationResult(
+ AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+
+ if (mHandler != null) {
+ Message msg = mHandler.obtainMessage(EVENT_EMERGENCY_NETWORK_SCAN_RESULT,
+ new AsyncResult(null, result, null));
+ msg.sendToTarget();
+ }
+ }
+ }
+
+ private void onModemReset() {
+ loge("onModemReset status=" + mStatus);
+ if (!shouldTerminateCallOnRadioNotAvailable()) {
+ return;
+ }
+ if (checkState(STATUS_DISPOSED) || checkState(STATUS_DOMAIN_SELECTED)) {
+ return;
+ }
+ onSelectionTerminated(DisconnectCause.POWER_OFF);
+ dispose();
+ }
+
+ private boolean shouldTerminateCallOnRadioNotAvailable() {
+ return mIsEmergency && mSelectorType == DomainSelectionService.SELECTOR_TYPE_CALLING;
+ }
+
/**
* Get the preferred transport.
*
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
index 410f89b..1b66e54 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
@@ -64,8 +64,7 @@
* to be bound to the domain selection controller.
*/
public static void make(Context context, String flattenedComponentName) {
- Log.i(TAG, "make flag=" + Flags.apDomainSelectionEnabled()
- + ", useOem=" + Flags.useOemDomainSelectionService());
+ Log.i(TAG, "make useOem=" + Flags.useOemDomainSelectionService());
if (sInstance == null) {
sInstance = new DomainSelectionResolver(context, flattenedComponentName);
}
diff --git a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
index 66b977d..4153c93 100644
--- a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
@@ -47,6 +47,7 @@
import com.android.internal.telephony.data.AccessNetworksManager;
import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.Flags;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -198,6 +199,32 @@
super.cancelSelection();
}
+ @Override
+ public @NonNull CompletableFuture<Integer> reselectDomain(
+ @NonNull DomainSelectionService.SelectionAttributes attr) {
+ if (Flags.hangupEmergencyCallForCrossSimRedialing()) {
+ int disconnectCause = getDisconnectCause();
+ int preciseDisconnectCause = attr.getCsDisconnectCause();
+ if (disconnectCause == android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE) {
+ preciseDisconnectCause = PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+ } else if (disconnectCause
+ == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE) {
+ preciseDisconnectCause = PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
+ }
+ if (preciseDisconnectCause != attr.getCsDisconnectCause()) {
+ attr = EmergencyCallDomainSelectionConnection.getSelectionAttributes(
+ attr.getSlotIndex(), attr.getSubscriptionId(),
+ attr.isExitedFromAirplaneMode(), attr.getCallId(),
+ (attr.getAddress() != null)
+ ? attr.getAddress().getSchemeSpecificPart() : "",
+ attr.isTestEmergencyNumber(), preciseDisconnectCause,
+ attr.getPsDisconnectCause(),
+ attr.getEmergencyRegistrationResult());
+ }
+ }
+ return super.reselectDomain(attr);
+ }
+
/**
* Returns the attributes required to determine the domain for a telephony service.
*
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 167062f..e5ea0c0 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -20,6 +20,12 @@
import static android.telecom.Connection.STATE_DISCONNECTED;
import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;
+import static android.telephony.TelephonyManager.STOP_REASON_EMERGENCY_SMS_SENT;
+import static android.telephony.TelephonyManager.STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED;
+import static android.telephony.TelephonyManager.STOP_REASON_TIMER_EXPIRED;
+import static android.telephony.TelephonyManager.STOP_REASON_UNKNOWN;
import static com.android.internal.telephony.TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
@@ -65,6 +71,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.telephony.Rlog;
@@ -148,7 +155,8 @@
/** For emergency calls */
private final long mEcmExitTimeoutMs;
// A runnable which is used to automatically exit from Ecm after a period of time.
- private final Runnable mExitEcmRunnable = this::exitEmergencyCallbackMode;
+ private final Runnable mExitEcmRunnable = () -> exitEmergencyCallbackMode(
+ STOP_REASON_TIMER_EXPIRED);
// Tracks emergency calls by callId that have reached {@link Call.State#ACTIVE}.
private final Set<android.telecom.Connection> mActiveEmergencyCalls = new ArraySet<>();
private Phone mPhone;
@@ -184,6 +192,8 @@
private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) -> onCarrierConfigurationChanged(
slotIndex, subId);
+ /** Feature flags */
+ private final FeatureFlags mFeatureFlags;
/**
* Listens for Emergency Callback Mode state change intents
@@ -326,12 +336,14 @@
if (!isSamePhone(mPhone, mSmsPhone)) {
completeEmergencyMode(emergencyType,
DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED);
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
}
} else {
completeEmergencyMode(emergencyType);
mIsEmergencyCallStartedDuringEmergencySms = false;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
}
@@ -343,7 +355,8 @@
if (mIsEmergencyCallStartedDuringEmergencySms) {
mIsEmergencyCallStartedDuringEmergencySms = false;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
}
@@ -409,7 +422,8 @@
// the emergency call was started, needs to exit the emergency mode first.
if (mIsEmergencyCallStartedDuringEmergencySms) {
final Phone smsPhone = mSmsPhone;
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
if (mPhone != null && smsPhone != null
&& !isSamePhone(mPhone, smsPhone)) {
@@ -428,7 +442,7 @@
break;
}
case MSG_EXIT_SCBM: {
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_TIMER_EXPIRED);
break;
}
case MSG_NEW_RINGING_CONNECTION: {
@@ -457,11 +471,13 @@
* @param context The context of the application.
* @param isSuplDdsSwitchRequiredForEmergencyCall Whether gnss supl requires default data for
* emergency call.
+ * @param featureFlags The telephony feature flags.
*/
- public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall) {
+ public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall,
+ @NonNull FeatureFlags featureFlags) {
if (INSTANCE == null) {
INSTANCE = new EmergencyStateTracker(context, Looper.myLooper(),
- isSuplDdsSwitchRequiredForEmergencyCall);
+ isSuplDdsSwitchRequiredForEmergencyCall, featureFlags);
}
}
@@ -481,12 +497,12 @@
* Initializes EmergencyStateTracker.
*/
private EmergencyStateTracker(Context context, Looper looper,
- boolean isSuplDdsSwitchRequiredForEmergencyCall) {
+ boolean isSuplDdsSwitchRequiredForEmergencyCall, @NonNull FeatureFlags featureFlags) {
mEcmExitTimeoutMs = DEFAULT_ECM_EXIT_TIMEOUT_MS;
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
-
+ mFeatureFlags = featureFlags;
PowerManager pm = context.getSystemService(PowerManager.class);
mWakeLock = (pm != null) ? pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"telephony:" + TAG) : null;
@@ -523,12 +539,13 @@
* @param telephonyManagerProxy The {@link TelephonyManagerProxy} to be
* injected.
* @param radioOnHelper The {@link RadioOnHelper} to be injected.
+ * @param featureFlags The {@link FeatureFlags} to be injected.
*/
@VisibleForTesting
public EmergencyStateTracker(Context context, Looper looper,
boolean isSuplDdsSwitchRequiredForEmergencyCall, PhoneFactoryProxy phoneFactoryProxy,
PhoneSwitcherProxy phoneSwitcherProxy, TelephonyManagerProxy telephonyManagerProxy,
- RadioOnHelper radioOnHelper, long ecmExitTimeoutMs) {
+ RadioOnHelper radioOnHelper, long ecmExitTimeoutMs, FeatureFlags featureFlags) {
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
@@ -537,6 +554,7 @@
mTelephonyManagerProxy = telephonyManagerProxy;
mRadioOnHelper = radioOnHelper;
mEcmExitTimeoutMs = ecmExitTimeoutMs;
+ mFeatureFlags = featureFlags;
mWakeLock = null; // Don't declare a wakelock in tests
mConfigManager = context.getSystemService(CarrierConfigManager.class);
mConfigManager.registerCarrierConfigChangeListener(mHandler::post,
@@ -574,7 +592,7 @@
// Case1) When 2nd emergency call is initiated during an active call on the same phone.
// Case2) While the device is in ECBM, an emergency call is initiated on the same phone.
if (isSamePhone(mPhone, phone) && (!mActiveEmergencyCalls.isEmpty() || isInEcm())) {
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
mOngoingConnection = c;
mIsTestEmergencyNumber = isTestEmergencyNumber;
if (isInEcm()) {
@@ -622,7 +640,7 @@
mIsEmergencyCallStartedDuringEmergencySms = false;
}
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
}
if (mIsEmergencyCallStartedDuringEmergencySms) {
@@ -1087,7 +1105,7 @@
* Handles the radio power off request.
*/
public void onCellularRadioPowerOffRequested() {
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_UNKNOWN);
exitEmergencyCallbackMode();
}
@@ -1159,10 +1177,14 @@
setEmergencyCallbackMode(mPhone, EMERGENCY_TYPE_CALL);
- // Post this runnable so we will automatically exit if no one invokes
- // exitEmergencyCallbackMode() directly.
long delayInMillis = TelephonyProperties.ecm_exit_timer()
.orElse(mEcmExitTimeoutMs);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mPhone.startEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL, delayInMillis);
+ }
+
+ // Post this runnable so we will automatically exit if no one invokes
+ // exitEmergencyCallbackMode() directly.
mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
// We don't want to go to sleep while in ECM.
@@ -1170,9 +1192,27 @@
}
/**
- * Exits emergency callback mode and notifies relevant listeners.
+ * Exits the emergency callback mode.
+ *
+ * <p>This method exits the emergency callback mode with an unknown stop reason. It removes
+ * any pending exit requests and notifies relevant listeners about the change in status.
*/
public void exitEmergencyCallbackMode() {
+ exitEmergencyCallbackMode(STOP_REASON_UNKNOWN);
+ }
+
+ /**
+ * Exits the emergency callback mode.
+ *
+ * <p>This method exits the emergency callback mode with the specified stop reason. It removes
+ * any pending exit requests and notifies relevant listeners about the change in status,
+ * providing the reason for exiting.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
+ */
+ public void exitEmergencyCallbackMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
Rlog.d(TAG, "exit ECBM");
// Remove pending exit ECM runnable, if any.
mHandler.removeCallbacks(mExitEcmRunnable);
@@ -1191,6 +1231,10 @@
sendEmergencyCallbackModeChange();
gsmCdmaPhone.notifyEmergencyCallRegistrants(false);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ gsmCdmaPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL, reason);
+ }
+
// Exit emergency mode on modem.
exitEmergencyMode(gsmCdmaPhone, EMERGENCY_TYPE_CALL);
}
@@ -1213,11 +1257,20 @@
}
/**
- * Exits emergency callback mode and triggers runnable after exit response is received.
+ * Exits the emergency callback mode and triggers {@link Runnable} after exit response is
+ * received.
+ *
+ * <p>This method exits the emergency callback mode with the specified stop reason and then
+ * executes the provided {@link Runnable}.
+ *
+ * @param onComplete The {@link Runnable} to execute after exiting emergency callback mode.
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- public void exitEmergencyCallbackMode(Runnable onComplete) {
+ public void exitEmergencyCallbackMode(Runnable onComplete,
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
mOnEcmExitCompleteRunnable = onComplete;
- exitEmergencyCallbackMode();
+ exitEmergencyCallbackMode(reason);
}
/**
@@ -1323,7 +1376,7 @@
// emergency SMS callback mode first.
exitScbmInOtherPhone = true;
mIsEmergencySmsStartedDuringScbm = true;
- exitEmergencySmsCallbackModeAndEmergencyMode();
+ exitEmergencySmsCallbackModeAndEmergencyMode(STOP_REASON_EMERGENCY_SMS_SENT);
} else {
Rlog.e(TAG, "Emergency SMS is in progress on the other slot.");
return CompletableFuture.completedFuture(DisconnectCause.ERROR_UNSPECIFIED);
@@ -1460,6 +1513,9 @@
*/
private void enterEmergencySmsCallbackMode() {
Rlog.d(TAG, "enter SCBM while " + (isInScbm() ? "in" : "not in") + " SCBM");
+
+ boolean shouldRestartEcm = isInScbm();
+
// Remove pending message if present.
mHandler.removeMessages(MSG_EXIT_SCBM);
@@ -1484,17 +1540,29 @@
// Post the message so we will automatically exit if no one invokes
// exitEmergencySmsCallbackModeAndEmergencyMode() directly.
mHandler.sendEmptyMessageDelayed(MSG_EXIT_SCBM, delayInMillis);
+
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ if (shouldRestartEcm) {
+ mSmsPhone.restartEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, delayInMillis);
+ } else {
+ mSmsPhone.startEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, delayInMillis);
+ }
+ }
}
/**
* Exits emergency SMS callback mode and emergency mode if the device is in SCBM and
* the emergency mode is in CALLBACK.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- private void exitEmergencySmsCallbackModeAndEmergencyMode() {
+ private void exitEmergencySmsCallbackModeAndEmergencyMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
Rlog.d(TAG, "exit SCBM and emergency mode");
final Phone smsPhone = mSmsPhone;
boolean wasInScbm = isInScbm();
- exitEmergencySmsCallbackMode();
+ exitEmergencySmsCallbackMode(reason);
// The emergency mode needs to be checked to ensure that there is no ongoing emergency SMS.
if (wasInScbm && mOngoingEmergencySmsIds.isEmpty()) {
@@ -1505,13 +1573,22 @@
/**
* Exits emergency SMS callback mode.
+ *
+ * @param reason The reason for exiting. See
+ * {@link TelephonyManager.EmergencyCallbackModeStopReason} for possible values.
*/
- private void exitEmergencySmsCallbackMode() {
+ private void exitEmergencySmsCallbackMode(
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
// Remove pending message if present.
mHandler.removeMessages(MSG_EXIT_SCBM);
if (isInScbm()) {
Rlog.i(TAG, "exit SCBM");
+
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mSmsPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_SMS, reason);
+ }
+
setIsInScbm(false);
}
@@ -1588,7 +1665,7 @@
final boolean isAirplaneModeOn = isAirplaneModeOn(mContext);
boolean needToTurnOnRadio = !isRadioOn() || isAirplaneModeOn;
final SatelliteController satelliteController = SatelliteController.getInstance();
- boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabled();
+ boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabledOrBeingEnabled();
if (isAirplaneModeOn && !isPowerOff()
&& !phone.getServiceStateTracker().getDesiredPowerState()) {
@@ -1614,7 +1691,7 @@
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
if (!isRadioReady) {
- if (satelliteController.isSatelliteEnabled()) {
+ if (satelliteController.isSatelliteEnabledOrBeingEnabled()) {
// Could not turn satellite off
Rlog.e(TAG, "Failed to turn off satellite modem.");
completeEmergencyMode(emergencyType, DisconnectCause.SATELLITE_ENABLED);
@@ -1647,7 +1724,7 @@
return false;
}
return phone.getServiceStateTracker().isRadioOn()
- && !satelliteController.isSatelliteEnabled();
+ && !satelliteController.isSatelliteEnabledOrBeingEnabled();
}
@Override
@@ -1659,9 +1736,10 @@
}
// onTimeout shall be called only with the Phone for emergency
return phone.getServiceStateTracker().isRadioOn()
- && !satelliteController.isSatelliteEnabled();
+ && !satelliteController.isSatelliteEnabledOrBeingEnabled();
}
- }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout);
+ }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout,
+ /* forNormalRoutingEmergencyCall */ false);
} else {
switchDdsAndSetEmergencyMode(phone, emergencyType);
}
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
index 306f6bb..11162b8 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
@@ -85,7 +85,7 @@
*/
public void triggerRadioOnAndListen(RadioOnStateListener.Callback callback,
boolean forEmergencyCall, Phone phoneForEmergencyCall, boolean isTestEmergencyNumber,
- int emergencyTimeoutIntervalMillis) {
+ int emergencyTimeoutIntervalMillis, boolean forNormalRoutingEmergencyCall) {
setupListeners();
mCallback = callback;
mInProgressListeners.clear();
@@ -102,9 +102,10 @@
mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall
&& phone == phoneForEmergencyCall, timeoutCallbackInterval);
}
- powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber);
- if (SatelliteController.getInstance().isSatelliteEnabled()) {
- powerOffSatellite(phoneForEmergencyCall);
+ powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber,
+ forNormalRoutingEmergencyCall);
+ if (SatelliteController.getInstance().isSatelliteEnabledOrBeingEnabled()) {
+ powerOffSatellite();
}
}
@@ -113,17 +114,25 @@
* get an onServiceStateChanged() callback when the radio successfully comes up.
*/
private void powerOnRadio(boolean forEmergencyCall, Phone phoneForEmergencyCall,
- boolean isTestEmergencyNumber) {
+ boolean isTestEmergencyNumber, boolean forNormalRoutingEmergencyCall) {
// Always try to turn on the radio here independent of APM setting - if we got here in the
// first place, the radio is off independent of APM setting.
for (Phone phone : PhoneFactory.getPhones()) {
Rlog.d(TAG, "powerOnRadio, enabling Radio");
if (isTestEmergencyNumber) {
- phone.setRadioPowerOnForTestEmergencyCall(phone == phoneForEmergencyCall);
+ phone.setRadioPowerOnForTestEmergencyCall(
+ (phone == phoneForEmergencyCall) && !forNormalRoutingEmergencyCall);
} else {
- phone.setRadioPower(true, forEmergencyCall, phone == phoneForEmergencyCall,
- false);
+ if (forNormalRoutingEmergencyCall) {
+ if (phone.getServiceStateTracker() != null) {
+ // Clear all radio off reasons to ensure that the radio is turned on for
+ // normal routing emergency call.
+ phone.getServiceStateTracker().clearAllRadioOffReasons();
+ }
+ }
+ phone.setRadioPower(true, forEmergencyCall && !forNormalRoutingEmergencyCall,
+ (phone == phoneForEmergencyCall) && !forNormalRoutingEmergencyCall, false);
}
}
@@ -150,9 +159,9 @@
* Attempt to power off the satellite modem. We'll eventually get an
* onSatelliteModemStateChanged() callback when the satellite modem is successfully disabled.
*/
- private void powerOffSatellite(Phone phoneForEmergencyCall) {
+ private void powerOffSatellite() {
SatelliteController satelliteController = SatelliteController.getInstance();
- satelliteController.requestSatelliteEnabled(phoneForEmergencyCall.getSubId(),
+ satelliteController.requestSatelliteEnabled(
false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
new IIntegerConsumer.Stub() {
@Override
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index fa0610a..3a3f6c8 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -21,7 +21,6 @@
import android.os.Looper;
import android.os.Message;
import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
import android.telephony.satellite.ISatelliteModemStateCallback;
import com.android.internal.annotations.VisibleForTesting;
@@ -148,6 +147,16 @@
public void onSatelliteModemStateChanged(int state) {
mHandler.obtainMessage(MSG_SATELLITE_ENABLED_CHANGED).sendToTarget();
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ Rlog.d(TAG, "onEmergencyModeChanged: ignored " + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ Rlog.d(TAG, "onRegistrationFailure: causeCode " + causeCode);
+ }
};
private Callback mCallback; // The callback to notify upon completion.
@@ -221,7 +230,7 @@
// Register for RADIO_OFF to handle cases where emergency call is dialed before
// we receive UNSOL_RESPONSE_RADIO_STATE_CHANGED with RADIO_OFF.
registerForRadioOff();
- if (mSatelliteController.isSatelliteEnabled()) {
+ if (mSatelliteController.isSatelliteEnabledOrBeingEnabled()) {
// Register for satellite modem state changed to notify when satellite is disabled.
registerForSatelliteEnabledChanged();
}
@@ -392,8 +401,8 @@
Rlog.d(TAG, "Trying (again) to turn the radio on and satellite modem off.");
mPhone.setRadioPower(true, mForEmergencyCall, mSelectedPhoneForEmergencyCall,
false);
- if (mSatelliteController.isSatelliteEnabled()) {
- mSatelliteController.requestSatelliteEnabled(mPhone.getSubId(),
+ if (mSatelliteController.isSatelliteEnabledOrBeingEnabled()) {
+ mSatelliteController.requestSatelliteEnabled(
false /* enableSatellite */, false /* enableDemoMode */,
false /* isEmergency*/,
new IIntegerConsumer.Stub() {
@@ -497,16 +506,11 @@
}
private void registerForSatelliteEnabledChanged() {
- mSatelliteController.registerForSatelliteModemStateChanged(
- mPhone.getSubId(), mSatelliteCallback);
+ mSatelliteController.registerForSatelliteModemStateChanged(mSatelliteCallback);
}
private void unregisterForSatelliteEnabledChanged() {
- int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- if (mPhone != null) {
- subId = mPhone.getSubId();
- }
- mSatelliteController.unregisterForModemStateChanged(subId, mSatelliteCallback);
+ mSatelliteController.unregisterForModemStateChanged(mSatelliteCallback);
mHandler.removeMessages(MSG_SATELLITE_ENABLED_CHANGED);
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index 4e773f3..c5cc769 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -749,10 +749,12 @@
@Override
public boolean processMessage(Message message) {
if (message.what == CMD_SERVICE_DISCONNECTED) {
+ EuiccSession.get().endAllSessions();
mEuiccService = null;
transitionTo(mDisconnectedState);
return HANDLED;
} else if (message.what == CMD_LINGER_TIMEOUT) {
+ EuiccSession.get().endAllSessions();
unbind();
transitionTo(mAvailableState);
return HANDLED;
@@ -831,6 +833,7 @@
}
case CMD_DOWNLOAD_SUBSCRIPTION: {
DownloadRequest request = (DownloadRequest) message.obj;
+ EuiccSession.get().startSession(EuiccSession.DOWNLOAD);
mEuiccService.downloadSubscription(slotId,
request.mPortIndex,
request.mSubscription,
@@ -845,6 +848,7 @@
.onDownloadComplete(result);
onCommandEnd(callback);
});
+ EuiccSession.get().endSession(EuiccSession.DOWNLOAD);
}
});
break;
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 1a5b99e..cc9d793 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -22,10 +22,10 @@
import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.flags.Flags;
import android.app.compat.CompatChanges;
import android.content.ComponentName;
import android.content.Context;
@@ -71,6 +71,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.UiccController;
@@ -622,24 +623,21 @@
Bundle resolvedBundle, PendingIntent callbackIntent) {
mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
- boolean callerHasAdminPrivileges = false;
- if (Flags.esimManagementEnabled()) {
- callerHasAdminPrivileges = callerCanManageDevicePolicyManagedSubscriptions(
- callingPackage);
- if (callerHasAdminPrivileges && (switchAfterDownload && !shouldAllowSwitchAfterDownload(
- callingPackage))) {
- // Throw error if calling admin does not have privileges to enable
- // subscription silently after download but switchAfterDownload is passed as true.
- sendResult(callbackIntent, ERROR, null);
- return;
- }
- if (mContext.getSystemService(UserManager.class).hasUserRestriction(
- UserManager.DISALLOW_SIM_GLOBALLY) && !callerHasAdminPrivileges) {
- // Only admin managed subscriptions are allowed, but the caller is not authorised to
- // download admin managed subscriptions. Abort.
- sendResult(callbackIntent, ERROR, null);
- return;
- }
+ boolean callerHasAdminPrivileges =
+ callerCanManageDevicePolicyManagedSubscriptions(callingPackage);
+ if (callerHasAdminPrivileges && (switchAfterDownload && !shouldAllowSwitchAfterDownload(
+ callingPackage))) {
+ // Throw error if calling admin does not have privileges to enable
+ // subscription silently after download but switchAfterDownload is passed as true.
+ sendResult(callbackIntent, ERROR, null);
+ return;
+ }
+ if (mContext.getSystemService(UserManager.class).hasUserRestriction(
+ UserManager.DISALLOW_SIM_GLOBALLY) && !callerHasAdminPrivileges) {
+ // Only admin managed subscriptions are allowed, but the caller is not authorised to
+ // download admin managed subscriptions. Abort.
+ sendResult(callbackIntent, ERROR, null);
+ return;
}
// Don't try to resolve the port index for apps which are not targeting on T for backward
// compatibility. instead always use default port 0.
@@ -837,7 +835,7 @@
subscription,
switchAfterDownload,
forceDeactivateSim,
- resolvedBundle,
+ addCallingPackageToBundle(resolvedBundle, callingPackage),
new EuiccConnector.DownloadCommandCallback() {
@Override
public void onDownloadComplete(DownloadSubscriptionResult result) {
@@ -936,6 +934,13 @@
});
}
+ private static Bundle addCallingPackageToBundle(
+ @Nullable Bundle resolvedBundle, String callingPackage) {
+ resolvedBundle = resolvedBundle == null ? new Bundle() : resolvedBundle;
+ resolvedBundle.putString(EuiccService.EXTRA_PACKAGE_NAME, callingPackage);
+ return resolvedBundle;
+ }
+
/**
* Blocking call to {@link EuiccService#onGetEuiccProfileInfoList} of the eUICC with card ID
* {@code cardId}.
@@ -1070,9 +1075,7 @@
public void deleteSubscription(int cardId, int subscriptionId, String callingPackage,
PendingIntent callbackIntent) {
boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions();
- boolean callerIsAdmin =
- Flags.esimManagementEnabled()
- && callerCanManageDevicePolicyManagedSubscriptions(callingPackage);
+ boolean callerIsAdmin = callerCanManageDevicePolicyManagedSubscriptions(callingPackage);
mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
long token = Binder.clearCallingIdentity();
@@ -1088,7 +1091,7 @@
// system or the caller manage the target subscription, we let it continue. This is
// because deleting subscription won't change status of any other subscriptions.
if (!callerCanWriteEmbeddedSubscriptions
- && !mSubscriptionManager.canManageSubscription(sub, callingPackage)
+ && !canManageSubscription(sub, callingPackage)
&& !adminOwned) {
Log.e(TAG, "No permissions: " + subscriptionId + " adminOwned=" + adminOwned);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
@@ -1207,7 +1210,7 @@
if (callerCanWriteEmbeddedSubscriptions) {
passConsent = true;
} else {
- if (!mSubscriptionManager.canManageSubscription(sub, callingPackage)) {
+ if (!canManageSubscription(sub, callingPackage)) {
Log.e(TAG, "Not permitted to switch to sub: " + subscriptionId);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
return;
@@ -1286,7 +1289,7 @@
if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
&& subInfo.isEmbedded()
&& (callerCanWriteEmbeddedSubscriptions
- || mSubscriptionManager.canManageSubscription(subInfo, callingPackage))) {
+ || canManageSubscription(subInfo, callingPackage))) {
return subInfo.getPortIndex();
}
}
@@ -1557,7 +1560,7 @@
// system or the caller can manage the target subscription, we let it continue. This is
// because updating subscription nickname won't affect any other subscriptions.
if (!callerCanWriteEmbeddedSubscriptions
- && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) {
+ && !canManageSubscription(sub, callingPackage)) {
Log.e(TAG, "No permissions: " + subscriptionId);
sendResult(callbackIntent, ERROR, null /* extrasIntent */);
return;
@@ -1745,7 +1748,7 @@
private void refreshSubscriptionsOwnership(boolean isCallerAdmin, String callingPackage,
int cardId, Set<Integer> subscriptionsBefore) {
- if (Flags.esimManagementEnabled() && isCallerAdmin) {
+ if (isCallerAdmin) {
// Mark the newly downloaded subscriptions as being owned by an admin so
// that actions for that subscription can be restricted,
// and the admin is limited to effecting only these subscriptions.
@@ -1854,7 +1857,12 @@
if (bestComponent != null) {
intent.setPackage(bestComponent.packageName);
}
- mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
+ } else {
+ mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS);
+ }
}
@Nullable
@@ -1871,9 +1879,6 @@
}
private Set<Integer> getCurrentEmbeddedSubscriptionIds(int cardId) {
- if (!Flags.esimManagementEnabled()) {
- return new ArraySet<>();
- }
List<SubscriptionInfo> subscriptionInfos =
mSubscriptionManager.getAvailableSubscriptionInfoList();
int subCount = (subscriptionInfos != null) ? subscriptionInfos.size() : 0;
@@ -2064,7 +2069,7 @@
if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId)
&& subInfo.isEmbedded()
&& (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2133,8 +2138,7 @@
if (subInfo.isEmbedded()
&& subInfo.getCardId() == cardId
&& (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)
- && mSubscriptionManager.canManageSubscription(
- subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2153,7 +2157,7 @@
} else {
for (SubscriptionInfo subInfo : subInfoList) {
if (subInfo.isEmbedded()
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) {
+ && canManageSubscription(subInfo, callingPackage)) {
return true;
}
}
@@ -2388,4 +2392,13 @@
methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC);
}
}
+
+ private boolean canManageSubscription(SubscriptionInfo subInfo, String packageName) {
+ if (Flags.hsumPackageManager() && UserManager.isHeadlessSystemUserMode()) {
+ return mSubscriptionManager.canManageSubscriptionAsUser(subInfo, packageName,
+ UserHandle.of(ActivityManager.getCurrentUser()));
+ } else {
+ return mSubscriptionManager.canManageSubscription(subInfo, packageName);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccSession.java b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
new file mode 100644
index 0000000..f17789f
--- /dev/null
+++ b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
@@ -0,0 +1,183 @@
+/*
+ * 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.euicc;
+
+import android.annotation.Nullable;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.uicc.euicc.apdu.ApduSender;
+import com.android.telephony.Rlog;
+
+import java.util.Set;
+
+/**
+ * A eUICC transaction session aims to optimize multiple back-to-back EuiccPort API calls by only
+ * open and close a logical channel once.
+ *
+ * <p>This class is thread-safe.
+ */
+public class EuiccSession {
+ private static final String TAG = "EuiccSession";
+
+ // **** Well known session IDs, see #startSession() ****
+ public static final String DOWNLOAD = "DOWNLOAD";
+
+ @GuardedBy("EuiccSession.class")
+ private static EuiccSession sInstance;
+
+ public static synchronized EuiccSession get() {
+ if (sInstance == null) {
+ sInstance = new EuiccSession();
+ }
+ return sInstance;
+ }
+
+ @GuardedBy("this")
+ private final Set<String> mSessions = new ArraySet<>();
+
+ @GuardedBy("this")
+ private final Set<ApduSender> mApduSenders = new ArraySet<>();
+
+ /**
+ * Marks the start of a eUICC transaction session.
+ *
+ * <p>A session means a long-open logical channel (see {@link ApduSender}) used to
+ * send multiple APDUs for one action e.g. {@link EuiccController#downloadSubscription()}.
+ * Those APDUs can be send by one or multiple {@link EuiccCardController} methods.
+ *
+ * <p>Ideally a session should correespond to one phoneId and hence just one logical channel.
+ * But many {@link EuiccCardController} methods uses first available port and is not specific
+ * to a phoneId. So EuiccController cannot choose one phoneId to use. Hence a session has to
+ * be not specific to phoneId, i.e. for DSDS device both phoneId's will be in a session.
+ *
+ * <p>If called multiple times with different {@code sessionId}'s, the session is truly closed
+ * when the all sessions are ended. See {@link #endSession()}.
+ *
+ * @param sessionId The session ID.
+ */
+ public void startSession(String sessionId) {
+ if (!Flags.optimizationApduSender()) {
+ // Other methods in this class is no-op if no session started.
+ // Do not add flag to other methods, so if the flag gets turned off,
+ // the session can be ended properly.
+ return;
+ }
+ Rlog.i(TAG, "startSession: " + sessionId);
+ synchronized(this) {
+ mSessions.add(sessionId);
+ }
+ }
+
+ /** Returns {@code true} if there is at least one session ongoing. */
+ public boolean hasSession() {
+ boolean hasSession = hasSessionInternal();
+ Rlog.i(TAG, "hasSession: " + hasSession);
+ return hasSession;
+ }
+
+ // The bare metal implementation of hasSession() without logging.
+ private boolean hasSessionInternal() {
+ synchronized(this) {
+ return !mSessions.isEmpty();
+ }
+ }
+
+ /**
+ * Notes that a logical channel may be opened by the {@code apduSender}, which will
+ * be used to close the channel when session ends (see {@link #endSession()}).
+ *
+ * <p>No-op if no session ongoing (see {@link #hasSession()}).
+ *
+ * @param apduSender The ApduSender that will open the channel.
+ */
+ public void noteChannelOpen(ApduSender apduSender) {
+ Rlog.i(TAG, "noteChannelOpen: " + apduSender);
+ synchronized(this) {
+ if (hasSessionInternal()) {
+ mApduSenders.add(apduSender);
+ }
+ }
+ }
+
+ /**
+ * Marks the end of a eUICC transaction session. If this ends the last ongoing session,
+ * try to close the logical channel using the noted {@code apduSender}s
+ * (see {@link #noteChannelOpen()}).
+ *
+ * @param sessionId The session ID.
+ */
+ public void endSession(String sessionId) {
+ Rlog.i(TAG, "endSession: " + sessionId);
+ endSessionInternal(sessionId);
+ }
+
+ /**
+ * Marks the end of all eUICC transaction sessions and close the logical
+ * channels using the noted {@code apduSender}s
+ * (see {@link #noteChannelOpen()}).
+ *
+ * <p>This is useful in global cleanup e.g. when EuiccService
+ * implementation app crashes and indivial {@link #endSession()} calls
+ * won't happen in {@link EuiccConnector}.
+ */
+ public void endAllSessions() {
+ Rlog.i(TAG, "endAllSessions");
+ endSessionInternal(null);
+ }
+
+ // The implementation of endSession(sessionId) or endAllSessions() when the sessionId is null,
+ // without logging.
+ private void endSessionInternal(@Nullable String sessionId) {
+ ApduSender[] apduSenders = new ApduSender[0];
+ synchronized(this) {
+ boolean sessionRemoved = removeOrClear(mSessions, sessionId);
+ // 1. sessionRemoved is false if the `sessionId` was never started or there was
+ // no session. Don't bother invoke `apduSender`.
+ // 2. If some session is removed, and as a result there is no more session, we
+ // can clsoe channels.
+ if (sessionRemoved && !hasSessionInternal()) {
+ // copy mApduSenders to a local variable so we don't call closeAnyOpenChannel()
+ // which can take time in synchronized block.
+ apduSenders = mApduSenders.toArray(apduSenders);
+ mApduSenders.clear();
+ }
+ }
+ for (ApduSender apduSender : apduSenders) {
+ apduSender.closeAnyOpenChannel();
+ }
+ }
+
+ /**
+ * Removes the given element from the set. If the element is null, clears the set.
+ *
+ * @return true if the set changed as a result of the call
+ */
+ private static boolean removeOrClear(Set<String> collection, @Nullable String element) {
+ if (element == null) {
+ boolean collectionChanged = !collection.isEmpty();
+ collection.clear();
+ return collectionChanged;
+ } else {
+ return collection.remove(element);
+ }
+ }
+
+ @VisibleForTesting
+ public EuiccSession() {}
+}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
index 907f158..bf8098f 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmInboundSmsHandler.java
@@ -38,6 +38,7 @@
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.SmsStorageMonitor;
import com.android.internal.telephony.VisualVoicemailSmsFilter;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.UsimServiceTable;
/**
@@ -58,8 +59,8 @@
* Create a new GSM inbound SMS handler.
*/
private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
- Phone phone, Looper looper) {
- super("GsmInboundSmsHandler", context, storageMonitor, phone, looper);
+ Phone phone, Looper looper, FeatureFlags featureFlags) {
+ super("GsmInboundSmsHandler", context, storageMonitor, phone, looper, featureFlags);
phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi, phone.getPhoneId());
mCellBroadcastServiceManager.enable();
@@ -129,9 +130,10 @@
* Wait for state machine to enter startup state. We can't send any messages until then.
*/
public static GsmInboundSmsHandler makeInboundSmsHandler(Context context,
- SmsStorageMonitor storageMonitor, Phone phone, Looper looper) {
+ SmsStorageMonitor storageMonitor, Phone phone, Looper looper,
+ FeatureFlags featureFlags) {
GsmInboundSmsHandler handler =
- new GsmInboundSmsHandler(context, storageMonitor, phone, looper);
+ new GsmInboundSmsHandler(context, storageMonitor, phone, looper, featureFlags);
handler.start();
return handler;
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
index 234723f..f2b5dee 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
@@ -27,6 +27,8 @@
import static android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
+import static com.android.internal.telephony.CommandsInterface.IMS_MMTEL_CAPABILITY_VOICE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -52,21 +54,19 @@
public class ImsNrSaModeHandler extends Handler{
public static final String TAG = "ImsNrSaModeHandler";
- public static final String MMTEL_FEATURE_TAG =
- "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel\"";
private static final int MSG_PRECISE_CALL_STATE_CHANGED = 101;
- private static final int MSG_REQUEST_IS_VONR_ENABLED = 102;
- private static final int MSG_RESULT_IS_VONR_ENABLED = 103;
+ private static final int MSG_RESULT_IS_VONR_ENABLED = 102;
private final @NonNull ImsPhone mPhone;
private @Nullable CarrierConfigManager mCarrierConfigManager;
private @NrSaDisablePolicy int mNrSaDisablePolicy;
private boolean mIsNrSaDisabledForWfc;
- private boolean mIsVowifiRegistered;
+ private boolean mIsWifiRegistered;
private boolean mIsInImsCall;
private boolean mIsNrSaSupported;
+ private boolean mIsVoiceCapable;
private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) -> setNrSaDisablePolicy(subId);
@@ -100,37 +100,16 @@
*/
public void onImsRegistered(
@ImsRegistrationTech int imsRadioTech, @NonNull Set<String> featureTags) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_NONE) {
+ if (!mIsNrSaSupported || mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_NONE) {
return;
}
Log.d(TAG, "onImsRegistered: ImsRegistrationTech = " + imsRadioTech);
- boolean isVowifiRegChanged = false;
-
- if (isVowifiRegistered() && imsRadioTech != REGISTRATION_TECH_IWLAN) {
- setVowifiRegStatus(false);
- isVowifiRegChanged = true;
- } else if (!isVowifiRegistered() && imsRadioTech == REGISTRATION_TECH_IWLAN
- && featureTags.contains(MMTEL_FEATURE_TAG)) {
- setVowifiRegStatus(true);
- isVowifiRegChanged = true;
- }
-
- if (isVowifiRegChanged) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED) {
- setNrSaMode(!isVowifiRegistered());
- } else if ((mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED
- || mNrSaDisablePolicy
- == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED)
- && isImsCallOngoing()) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED) {
- requestIsVonrEnabled(!isVowifiRegistered());
- return;
- }
-
- setNrSaMode(!isVowifiRegistered());
- }
+ final boolean isNewWifiRegistered = imsRadioTech == REGISTRATION_TECH_IWLAN;
+ if (isWifiRegistered() != isNewWifiRegistered) {
+ setWifiRegStatus(isNewWifiRegistered);
+ calculateAndControlNrSaIfNeeded();
}
}
@@ -141,27 +120,15 @@
*/
public void onImsUnregistered(
@ImsRegistrationTech int imsRadioTech) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_NONE
- || imsRadioTech != REGISTRATION_TECH_IWLAN || !isVowifiRegistered()) {
+ if (!mIsNrSaSupported || mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_NONE
+ || imsRadioTech != REGISTRATION_TECH_IWLAN || !isWifiRegistered()) {
return;
}
Log.d(TAG, "onImsUnregistered : ImsRegistrationTech = " + imsRadioTech);
- setVowifiRegStatus(false);
-
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED) {
- setNrSaMode(true);
- } else if ((mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED
- || mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED)
- && isImsCallOngoing()) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED) {
- requestIsVonrEnabled(true);
- return;
- }
-
- setNrSaMode(true);
- }
+ setWifiRegStatus(false);
+ calculateAndControlNrSaIfNeeded();
}
/**
@@ -182,13 +149,23 @@
isImsCallStatusChanged = true;
}
- if (isVowifiRegistered() && isImsCallStatusChanged) {
- if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED) {
- requestIsVonrEnabled(!isImsCallOngoing());
- return;
- }
+ if (isWifiRegistered() && isImsCallStatusChanged) {
+ calculateAndControlNrSaIfNeeded();
+ }
+ }
- setNrSaMode(!isImsCallOngoing());
+ /**
+ * Updates Capability.
+ */
+ public void updateImsCapability(int capabilities) {
+ if (!mIsNrSaSupported || mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_NONE) {
+ return;
+ }
+
+ boolean isVoiceCapable = (IMS_MMTEL_CAPABILITY_VOICE & capabilities) != 0;
+ if (mIsVoiceCapable != isVoiceCapable) {
+ mIsVoiceCapable = isVoiceCapable;
+ calculateAndControlNrSaIfNeeded();
}
}
@@ -200,11 +177,6 @@
case MSG_PRECISE_CALL_STATE_CHANGED :
onPreciseCallStateChanged();
break;
- case MSG_REQUEST_IS_VONR_ENABLED :
- Log.d(TAG, "request isVoNrEnabled");
- mPhone.getDefaultPhone().mCi.isVoNrEnabled(
- obtainMessage(MSG_RESULT_IS_VONR_ENABLED, msg.obj), null);
- break;
case MSG_RESULT_IS_VONR_ENABLED :
ar = (AsyncResult) msg.obj;
@@ -212,8 +184,9 @@
boolean vonrEnabled = ((Boolean) ar.result).booleanValue();
Log.d(TAG, "result isVoNrEnabled = " + vonrEnabled);
- if (!vonrEnabled) {
- setNrSaMode(((Boolean) ar.userObj).booleanValue());
+ if (isWifiCallingOngoing() && !vonrEnabled) {
+ // If still WiFi calling is ongoing and VoNR is disabled, disable NR SA.
+ setNrSaMode(false);
}
}
@@ -262,14 +235,18 @@
if (mPhone.getSubId() == subId && mCarrierConfigManager != null) {
PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(),
KEY_NR_SA_DISABLE_POLICY_INT, KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
- mNrSaDisablePolicy = bundle.getInt(KEY_NR_SA_DISABLE_POLICY_INT);
int[] nrAvailabilities = bundle.getIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
mIsNrSaSupported = nrAvailabilities != null
&& Arrays.stream(nrAvailabilities).anyMatch(
value -> value == CARRIER_NR_AVAILABILITY_SA);
- Log.d(TAG, "setNrSaDisablePolicy : NrSaDisablePolicy = "
- + mNrSaDisablePolicy + ", IsNrSaSupported = " + mIsNrSaSupported);
+ if (!mIsNrSaSupported) {
+ return;
+ }
+
+ mNrSaDisablePolicy = bundle.getInt(KEY_NR_SA_DISABLE_POLICY_INT);
+
+ Log.d(TAG, "setNrSaDisablePolicy : NrSaDisablePolicy = " + mNrSaDisablePolicy);
if (mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED
|| mNrSaDisablePolicy == NR_SA_DISABLE_POLICY_WFC_ESTABLISHED) {
@@ -280,27 +257,20 @@
}
}
- private void requestIsVonrEnabled(boolean onOrOff) {
- Message msg = obtainMessage(MSG_REQUEST_IS_VONR_ENABLED, onOrOff);
- msg.sendToTarget();
- }
-
private void setNrSaMode(boolean onOrOff) {
- if (mIsNrSaSupported) {
- mPhone.getDefaultPhone().setN1ModeEnabled(onOrOff, null);
- Log.i(TAG, "setNrSaMode : " + onOrOff);
+ mPhone.getDefaultPhone().setN1ModeEnabled(onOrOff, null);
+ Log.i(TAG, "setNrSaMode : " + onOrOff);
- setNrSaDisabledForWfc(!onOrOff);
- }
+ setNrSaDisabledForWfc(!onOrOff);
}
/**
- * Sets VoWiFi reg status.
+ * Sets WiFi reg status.
*/
@VisibleForTesting
- public void setVowifiRegStatus(boolean registered) {
- Log.d(TAG, "setVowifiRegStatus : " + registered);
- mIsVowifiRegistered = registered;
+ public void setWifiRegStatus(boolean registered) {
+ Log.d(TAG, "setWifiRegStatus : " + registered);
+ mIsWifiRegistered = registered;
}
/**
@@ -313,8 +283,8 @@
}
@VisibleForTesting
- public boolean isVowifiRegistered() {
- return mIsVowifiRegistered;
+ public boolean isWifiRegistered() {
+ return mIsWifiRegistered;
}
@VisibleForTesting
@@ -322,8 +292,7 @@
return mIsInImsCall;
}
- @VisibleForTesting
- public boolean isNrSaDisabledForWfc() {
+ private boolean isNrSaDisabledForWfc() {
return mIsNrSaDisabledForWfc;
}
@@ -353,4 +322,56 @@
return false;
}
+
+ private void calculateAndControlNrSaIfNeeded() {
+ switch (mNrSaDisablePolicy) {
+ case NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED:
+ if (isNrSaDisabledForWfc() == isWifiRegisteredForVoice()) {
+ // NR SA is already disabled or condition is not met for disabling NR SA.
+ // So, no need for further action
+ return;
+ }
+
+ // Disable NR SA if VoWiFi registered otherwise enable
+ setNrSaMode(!isWifiRegisteredForVoice());
+ return;
+ case NR_SA_DISABLE_POLICY_WFC_ESTABLISHED:
+ if (isNrSaDisabledForWfc() == isWifiCallingOngoing()) {
+ // NR SA is already disabled or condition is not met for disabling NR SA.
+ // So, no need for further action
+ return;
+ }
+
+ // Disable NR SA if VoWiFi call established otherwise enable
+ setNrSaMode(!isWifiCallingOngoing());
+ return;
+ case NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED:
+ if (isNrSaDisabledForWfc() == isWifiCallingOngoing()) {
+ // NR SA is already disabled or condition is not met for disabling NR SA.
+ // So, no need for further action
+ return;
+ }
+
+ if (isWifiCallingOngoing()) {
+ // Query whether VoNR is enabled or not.
+ mPhone.getDefaultPhone().mCi.isVoNrEnabled(
+ obtainMessage(MSG_RESULT_IS_VONR_ENABLED), null);
+ return;
+ }
+
+ // Enable NR SA if there are no VoWiFi calls.
+ setNrSaMode(true);
+ return;
+ default:
+ break;
+ }
+ }
+
+ private boolean isWifiRegisteredForVoice() {
+ return isWifiRegistered() && mIsVoiceCapable;
+ }
+
+ private boolean isWifiCallingOngoing() {
+ return isWifiRegistered() && mIsVoiceCapable && isImsCallOngoing();
+ }
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 10cbe77..22b8a75 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -1016,8 +1016,8 @@
// Only look at the Network portion for mmi
String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
- ImsPhoneMmiCode mmi =
- ImsPhoneMmiCode.newFromDialString(networkPortion, this, wrappedCallback);
+ ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromDialString(networkPortion, this,
+ wrappedCallback, mFeatureFlags);
if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'...");
if (mmi == null) {
@@ -1440,12 +1440,13 @@
}
@Override
- public void sendUssdResponse(String ussdMessge) {
+ public void sendUssdResponse(String ussdMessage) {
logd("sendUssdResponse");
- ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessge, this);
+ ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessage, this,
+ mFeatureFlags);
mPendingMMIs.add(mmi);
mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
- mmi.sendUssd(ussdMessge);
+ mmi.sendUssd(ussdMessage);
}
public void sendUSSD(String ussdString, Message response) {
@@ -1575,14 +1576,12 @@
// also, discard if there is no message to present
ImsPhoneMmiCode mmi;
mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
- isUssdRequest,
- this);
+ isUssdRequest, this, mFeatureFlags);
onNetworkInitiatedUssd(mmi);
} else if (isUssdError) {
ImsPhoneMmiCode mmi;
mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
- true,
- this);
+ true, this, mFeatureFlags);
mmi.onUssdFinishedError();
}
}
@@ -2763,7 +2762,7 @@
}
/**
- * Update IMS registration information to modem.
+ * Update IMS registration information to modem and other modules.
*
* @param capabilities indicate MMTEL capability such as VOICE, VIDEO and SMS.
*/
@@ -2784,6 +2783,8 @@
mDefaultPhone.mCi.updateImsRegistrationInfo(mImsRegistrationState,
mImsRegistrationTech, 0, capabilities, null);
mNotifiedRegisteredState = true;
+
+ mImsNrSaModeHandler.updateImsCapability(capabilities);
}
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index e73eafd..d47f05b 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -70,6 +70,7 @@
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.sysprop.TelephonyProperties;
@@ -1543,7 +1544,11 @@
Intent intent = new Intent(intentAction);
intent.putExtra(ImsManager.EXTRA_PHONE_ID, mPhone.getPhoneId());
if (mPhone != null && mPhone.getContext() != null) {
- mPhone.getContext().sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mPhone.getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mPhone.getContext().sendBroadcast(intent);
+ }
}
}
@@ -1792,7 +1797,8 @@
dialArgs.intentExtras);
}
};
- EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete);
+ EmergencyStateTracker.getInstance().exitEmergencyCallbackMode(onComplete,
+ TelephonyManager.STOP_REASON_OUTGOING_NORMAL_CALL_INITIATED);
} else {
try {
getEcbmInterface().exitEmergencyCallbackMode();
@@ -2878,6 +2884,14 @@
ImsPhoneConnection conn = findConnection(imsCall);
boolean rejectCall = false;
+ if (mFeatureFlags.preventHangupDuringCallMerge()) {
+ if (imsCall != null && imsCall.isCallSessionMergePending()) {
+ if (DBG) log("hangup call failed during call merge");
+
+ throw new CallStateException("can not hangup during call merge");
+ }
+ }
+
String logResult = "(undefined)";
if (call == mRingingCall) {
logResult = "(ringing) hangup incoming";
@@ -3260,6 +3274,12 @@
int cause = DisconnectCause.ERROR_UNSPECIFIED;
int code = maybeRemapReasonCode(reasonInfo);
+
+ if (mFeatureFlags.remapDisconnectCauseSipRequestCancelled() &&
+ code == ImsReasonInfo.CODE_SIP_REQUEST_CANCELLED) {
+ return DisconnectCause.NORMAL;
+ }
+
switch (code) {
case ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL:
return DisconnectCause.IMS_SIP_ALTERNATE_EMERGENCY_CALL;
@@ -4666,8 +4686,14 @@
configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
if (mPhone != null && mPhone.getContext() != null) {
- mPhone.getContext().sendBroadcast(configChangedIntent,
- Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mPhone.getContext().sendBroadcastAsUser(configChangedIntent,
+ UserHandle.ALL,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ } else {
+ mPhone.getContext().sendBroadcast(configChangedIntent,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
}
}
@@ -4951,7 +4977,7 @@
}
case EVENT_SUPP_SERVICE_INDICATION: {
ar = (AsyncResult) msg.obj;
- ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone);
+ ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone, mFeatureFlags);
try {
mmiCode.setIsSsInfo(true);
mmiCode.processImsSsData(ar);
@@ -6327,8 +6353,13 @@
configChangedIntent.putExtra(ImsConfig.EXTRA_CHANGED_ITEM, item);
configChangedIntent.putExtra(ImsConfig.EXTRA_NEW_VALUE, value);
if (mPhone != null && mPhone.getContext() != null) {
- mPhone.getContext().sendBroadcast(
- configChangedIntent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mPhone.getContext().sendBroadcastAsUser(configChangedIntent, UserHandle.ALL,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ } else {
+ mPhone.getContext().sendBroadcast(
+ configChangedIntent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
}
}
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 25fa8a2..d573f5d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -63,6 +63,7 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MmiCode;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.GsmMmiCode;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.telephony.Rlog;
@@ -165,6 +166,9 @@
private static final int NUM_PRESENTATION_ALLOWED = 0;
private static final int NUM_PRESENTATION_RESTRICTED = 1;
+ // Using same value with CallForwardEditPreference#DEFAULT_NO_REPLY_TIMER_FOR_CFNRY
+ private static final int DEFAULT_NO_REPLY_TIMER_FOR_CFNRY = 20;
+
//***** Supplementary Service Query Bundle Keys
// Used by IMS Service layer to put supp. serv. query
// responses into the ssInfo Bundle.
@@ -245,6 +249,8 @@
private static final int MATCH_GROUP_DIALING_NUMBER = 12;
static private String[] sTwoDigitNumberPattern;
+ private final FeatureFlags mFeatureFlags;
+
//***** Public Class methods
/**
@@ -262,12 +268,13 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@VisibleForTesting
- public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone) {
- return newFromDialString(dialString, phone, null);
+ public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+ FeatureFlags featureFlags) {
+ return newFromDialString(dialString, phone, null, featureFlags);
}
- static ImsPhoneMmiCode newFromDialString(String dialString,
- ImsPhone phone, ResultReceiver wrappedCallback) {
+ static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+ ResultReceiver wrappedCallback, FeatureFlags featureFlags) {
Matcher m;
ImsPhoneMmiCode ret = null;
@@ -287,7 +294,7 @@
// Is this formatted like a standard supplementary service code?
if (m.matches()) {
- ret = new ImsPhoneMmiCode(phone);
+ ret = new ImsPhoneMmiCode(phone, featureFlags);
ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
@@ -305,7 +312,7 @@
if (ret.mDialingNumber != null &&
ret.mDialingNumber.endsWith("#") &&
dialString.endsWith("#")){
- ret = new ImsPhoneMmiCode(phone);
+ ret = new ImsPhoneMmiCode(phone, featureFlags);
ret.mPoundString = dialString;
}
} else if (dialString.endsWith("#")) {
@@ -313,7 +320,7 @@
// "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
// (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
- ret = new ImsPhoneMmiCode(phone);
+ ret = new ImsPhoneMmiCode(phone, featureFlags);
ret.mPoundString = dialString;
} else if (GsmMmiCode.isTwoDigitShortCode(phone.getContext(), phone.getSubId(),
dialString)) {
@@ -321,7 +328,7 @@
ret = null;
} else if (isShortCode(dialString, phone)) {
// this may be a short code, as defined in TS 22.030, 6.5.3.2
- ret = new ImsPhoneMmiCode(phone);
+ ret = new ImsPhoneMmiCode(phone, featureFlags);
ret.mDialingNumber = dialString;
}
return ret;
@@ -348,10 +355,10 @@
}
public static ImsPhoneMmiCode newNetworkInitiatedUssd(String ussdMessage,
- boolean isUssdRequest, ImsPhone phone) {
+ boolean isUssdRequest, ImsPhone phone, FeatureFlags featureFlags) {
ImsPhoneMmiCode ret;
- ret = new ImsPhoneMmiCode(phone);
+ ret = new ImsPhoneMmiCode(phone, featureFlags);
ret.mMessage = ussdMessage;
ret.mIsUssdRequest = isUssdRequest;
@@ -368,10 +375,11 @@
return ret;
}
- static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessge, ImsPhone phone) {
- ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone);
+ static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessage, ImsPhone phone,
+ FeatureFlags featureFlags) {
+ ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone, featureFlags);
- ret.mMessage = ussdMessge;
+ ret.mMessage = ussdMessage;
ret.mState = State.PENDING;
ret.mIsPendingUSSD = true;
@@ -584,13 +592,15 @@
//***** Constructor
- public ImsPhoneMmiCode(ImsPhone phone) {
+ public ImsPhoneMmiCode(ImsPhone phone, FeatureFlags featureFlags) {
// The telephony unit-test cases may create ImsPhoneMmiCode's
// in secondary threads
super(phone.getHandler().getLooper());
mPhone = phone;
mContext = phone.getContext();
mIccRecords = mPhone.mDefaultPhone.getIccRecords();
+
+ mFeatureFlags = featureFlags;
}
//***** MmiCode implementation
@@ -907,7 +917,19 @@
String dialingNumber = mSia;
int reason = scToCallForwardReason(mSc);
int serviceClass = siToServiceClass(mSib);
- int time = siToTime(mSic);
+ int time;
+
+ if (mFeatureFlags.useCarrierConfigForCfnryTimeViaMmi()) {
+ // If the code is CFNRy and time is null(empty)
+ // use the default time value from CarrierConfig
+ if (mSc.equals(SC_CFNRy) && isEmptyOrNull(mSic)) {
+ time = getCfnryTime();
+ } else {
+ time = siToTime(mSic);
+ }
+ } else {
+ time = siToTime(mSic);
+ }
if (isInterrogate()) {
mPhone.getCallForwardingOption(reason, serviceClass,
@@ -1147,6 +1169,27 @@
}
}
+ private int getCfnryTime() {
+ CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+ if (configManager == null) {
+ return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+ }
+
+ PersistableBundle carrierConfig = configManager.getConfigForSubId(mPhone.getSubId());
+ if (carrierConfig == null
+ || !carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
+ return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+ }
+
+ int time = carrierConfig.getInt(
+ CarrierConfigManager.KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT,
+ DEFAULT_NO_REPLY_TIMER_FOR_CFNRY);
+
+ Rlog.d(LOG_TAG, "getCfnryTime: " + time);
+ return time;
+ }
+
private boolean isUssdOverImsAllowed() {
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allow_ussd_over_ims)) {
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index a83cd06..e43bf3c 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -1147,7 +1147,8 @@
session.vonrEnabled,
session.isNtn,
session.supportsBusinessCallComposer,
- session.callComposerStatus);
+ session.callComposerStatus,
+ session.preciseCallStateOnSetup);
}
@@ -1474,7 +1475,12 @@
satelliteController.countOfDatagramTypeKeepAliveFail,
satelliteController.countOfAllowedSatelliteAccess,
satelliteController.countOfDisallowedSatelliteAccess,
- satelliteController.countOfSatelliteAccessCheckFail);
+ satelliteController.countOfSatelliteAccessCheckFail,
+ satelliteController.isProvisioned,
+ satelliteController.carrierId,
+ satelliteController.countOfSatelliteAllowedStateChangedEvents,
+ satelliteController.countOfSuccessfulLocationQueries,
+ satelliteController.countOfFailedLocationQueries);
}
private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) {
@@ -1492,7 +1498,11 @@
satelliteSession.countOfIncomingDatagramSuccess,
satelliteSession.countOfIncomingDatagramFailed,
satelliteSession.isDemoMode,
- satelliteSession.maxNtnSignalStrengthLevel);
+ satelliteSession.maxNtnSignalStrengthLevel,
+ satelliteSession.carrierId,
+ satelliteSession.countOfSatelliteNotificationDisplayed,
+ satelliteSession.countOfAutoExitDueToScreenOff,
+ satelliteSession.countOfAutoExitDueToTnNetwork);
}
private static StatsEvent buildStatsEvent(SatelliteIncomingDatagram stats) {
@@ -1501,7 +1511,8 @@
stats.resultCode,
stats.datagramSizeBytes,
stats.datagramTransferTimeMillis,
- stats.isDemoMode);
+ stats.isDemoMode,
+ stats.carrierId);
}
private static StatsEvent buildStatsEvent(SatelliteOutgoingDatagram stats) {
@@ -1511,7 +1522,8 @@
stats.resultCode,
stats.datagramSizeBytes,
stats.datagramTransferTimeMillis,
- stats.isDemoMode);
+ stats.isDemoMode,
+ stats.carrierId);
}
private static StatsEvent buildStatsEvent(SatelliteProvision stats) {
@@ -1520,7 +1532,8 @@
stats.resultCode,
stats.provisioningTimeSec,
stats.isProvisionRequest,
- stats.isCanceled);
+ stats.isCanceled,
+ stats.carrierId);
}
private static StatsEvent buildStatsEvent(SatelliteSosMessageRecommender stats) {
@@ -1533,7 +1546,9 @@
stats.count,
stats.isMultiSim,
stats.recommendingHandoverType,
- stats.isSatelliteAllowedInCurrentLocation);
+ stats.isSatelliteAllowedInCurrentLocation,
+ stats.isWifiConnected,
+ stats.carrierId);
}
private static StatsEvent buildStatsEvent(DataNetworkValidation stats) {
@@ -1578,7 +1593,9 @@
stats.countOfSatelliteNotificationDisplayed,
stats.satelliteSessionGapMinSec,
stats.satelliteSessionGapAvgSec,
- stats.satelliteSessionGapMaxSec);
+ stats.satelliteSessionGapMaxSec,
+ stats.carrierId,
+ stats.isDeviceEntitled);
}
private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) {
@@ -1610,7 +1627,9 @@
stats.isEmergency,
stats.resultCode,
stats.countryCodes,
- stats.configDataSource);
+ stats.configDataSource,
+ stats.carrierId,
+ stats.triggeringEvent);
}
/** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 12dab7a..9f74890 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -771,6 +771,14 @@
atom.countOfDisallowedSatelliteAccess += stats.countOfDisallowedSatelliteAccess;
atom.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
+ atom.isProvisioned = stats.isProvisioned;
+ atom.carrierId = stats.carrierId;
+
+ atom.countOfSatelliteAllowedStateChangedEvents
+ += stats.countOfSatelliteAllowedStateChangedEvents;
+ atom.countOfSuccessfulLocationQueries += stats.countOfSuccessfulLocationQueries;
+ atom.countOfFailedLocationQueries += stats.countOfFailedLocationQueries;
+
mAtoms.satelliteController = atomArray;
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
}
@@ -853,24 +861,24 @@
/** Adds a new {@link CarrierRoamingSatelliteControllerStats} to the storage. */
public synchronized void addCarrierRoamingSatelliteControllerStats(
CarrierRoamingSatelliteControllerStats stats) {
- // CarrierRoamingSatelliteController is a single data point
- CarrierRoamingSatelliteControllerStats[] atomArray =
- mAtoms.carrierRoamingSatelliteControllerStats;
- if (atomArray == null || atomArray.length == 0) {
- atomArray = new CarrierRoamingSatelliteControllerStats[] {new
- CarrierRoamingSatelliteControllerStats()};
+ CarrierRoamingSatelliteControllerStats existingStats = find(stats);
+ if (existingStats != null) {
+ existingStats.configDataSource = stats.configDataSource;
+ existingStats.countOfEntitlementStatusQueryRequest +=
+ stats.countOfEntitlementStatusQueryRequest;
+ existingStats.countOfSatelliteConfigUpdateRequest +=
+ stats.countOfSatelliteConfigUpdateRequest;
+ existingStats.countOfSatelliteNotificationDisplayed +=
+ stats.countOfSatelliteNotificationDisplayed;
+ existingStats.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec;
+ existingStats.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec;
+ existingStats.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec;
+ existingStats.isDeviceEntitled = stats.isDeviceEntitled;
+ } else {
+ mAtoms.carrierRoamingSatelliteControllerStats = insertAtRandomPlace(
+ mAtoms.carrierRoamingSatelliteControllerStats, stats, mMaxNumSatelliteStats);
}
- CarrierRoamingSatelliteControllerStats atom = atomArray[0];
- atom.configDataSource = stats.configDataSource;
- atom.countOfEntitlementStatusQueryRequest += stats.countOfEntitlementStatusQueryRequest;
- atom.countOfSatelliteConfigUpdateRequest += stats.countOfSatelliteConfigUpdateRequest;
- atom.countOfSatelliteNotificationDisplayed += stats.countOfSatelliteNotificationDisplayed;
- atom.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec;
- atom.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec;
- atom.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec;
-
- mAtoms.carrierRoamingSatelliteControllerStats = atomArray;
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
}
@@ -2331,7 +2339,12 @@
&& stats.countOfIncomingDatagramSuccess == key.countOfIncomingDatagramSuccess
&& stats.countOfIncomingDatagramFailed == key.countOfIncomingDatagramFailed
&& stats.isDemoMode == key.isDemoMode
- && stats.maxNtnSignalStrengthLevel == key.maxNtnSignalStrengthLevel) {
+ && stats.maxNtnSignalStrengthLevel == key.maxNtnSignalStrengthLevel
+ && stats.carrierId == key.carrierId
+ && stats.countOfSatelliteNotificationDisplayed
+ == key.countOfSatelliteNotificationDisplayed
+ && stats.countOfAutoExitDueToScreenOff == key.countOfAutoExitDueToScreenOff
+ && stats.countOfAutoExitDueToTnNetwork == key.countOfAutoExitDueToTnNetwork) {
return stats;
}
}
@@ -2350,7 +2363,9 @@
&& stats.isImsRegistered == key.isImsRegistered
&& stats.cellularServiceState == key.cellularServiceState
&& stats.isMultiSim == key.isMultiSim
- && stats.recommendingHandoverType == key.recommendingHandoverType) {
+ && stats.recommendingHandoverType == key.recommendingHandoverType
+ && stats.isWifiConnected == key.isWifiConnected
+ && stats.carrierId == key.carrierId) {
return stats;
}
}
@@ -2375,6 +2390,21 @@
}
/**
+ * Returns CarrierRoamingSatelliteControllerStats atom that has same carrier_id value or
+ * {@code null} if does not exist.
+ */
+ private @Nullable CarrierRoamingSatelliteControllerStats find(
+ CarrierRoamingSatelliteControllerStats key) {
+ for (CarrierRoamingSatelliteControllerStats stats :
+ mAtoms.carrierRoamingSatelliteControllerStats) {
+ if (stats.carrierId == key.carrierId) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns SatelliteEntitlement atom that has same values or {@code null} if it does not exist.
*/
private @Nullable SatelliteEntitlement find(SatelliteEntitlement key) {
diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
index c2b2753..71c1bf3 100644
--- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
@@ -17,6 +17,9 @@
package com.android.internal.telephony.metrics;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+
+import static com.android.internal.telephony.satellite.SatelliteConstants.TRIGGERING_EVENT_UNKNOWN;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
@@ -37,6 +40,7 @@
import com.android.telephony.Rlog;
import java.util.Arrays;
+import java.util.Optional;
/** Tracks Satellite metrics for each phone */
public class SatelliteStats {
@@ -91,6 +95,11 @@
private final int mCountOfAllowedSatelliteAccess;
private final int mCountOfDisallowedSatelliteAccess;
private final int mCountOfSatelliteAccessCheckFail;
+ private static boolean sIsProvisioned;
+ private static int sCarrierId = UNKNOWN_CARRIER_ID;
+ private final int mCountOfSatelliteAllowedStateChangedEvents;
+ private final int mCountOfSuccessfulLocationQueries;
+ private final int mCountOfFailedLocationQueries;
private SatelliteControllerParams(Builder builder) {
this.mCountOfSatelliteServiceEnablementsSuccess =
@@ -136,6 +145,23 @@
builder.mCountOfDisallowedSatelliteAccess;
this.mCountOfSatelliteAccessCheckFail =
builder.mCountOfSatelliteAccessCheckFail;
+
+ // isProvisioned value should be updated only when it is meaningful.
+ if (builder.mIsProvisioned.isPresent()) {
+ this.sIsProvisioned = builder.mIsProvisioned.get();
+ }
+
+ // Carrier ID value should be updated only when it is meaningful.
+ if (builder.mCarrierId.isPresent()) {
+ this.sCarrierId = builder.mCarrierId.get();
+ }
+
+ this.mCountOfSatelliteAllowedStateChangedEvents =
+ builder.mCountOfSatelliteAllowedStateChangedEvents;
+ this.mCountOfSuccessfulLocationQueries =
+ builder.mCountOfSuccessfulLocationQueries;
+ this.mCountOfFailedLocationQueries =
+ builder.mCountOfFailedLocationQueries;
}
public int getCountOfSatelliteServiceEnablementsSuccess() {
@@ -250,6 +276,26 @@
return mCountOfSatelliteAccessCheckFail;
}
+ public boolean isProvisioned() {
+ return sIsProvisioned;
+ }
+
+ public int getCarrierId() {
+ return sCarrierId;
+ }
+
+ public int getCountOfSatelliteAllowedStateChangedEvents() {
+ return mCountOfSatelliteAllowedStateChangedEvents;
+ }
+
+ public int getCountOfSuccessfulLocationQueries() {
+ return mCountOfSuccessfulLocationQueries;
+ }
+
+ public int getCountOfFailedLocationQueries() {
+ return mCountOfFailedLocationQueries;
+ }
+
/**
* A builder class to create {@link SatelliteControllerParams} data structure class
*/
@@ -282,6 +328,11 @@
private int mCountOfAllowedSatelliteAccess = 0;
private int mCountOfDisallowedSatelliteAccess = 0;
private int mCountOfSatelliteAccessCheckFail = 0;
+ private Optional<Boolean> mIsProvisioned = Optional.empty();
+ private Optional<Integer> mCarrierId = Optional.empty();
+ private int mCountOfSatelliteAllowedStateChangedEvents = 0;
+ private int mCountOfSuccessfulLocationQueries = 0;
+ private int mCountOfFailedLocationQueries = 0;
/**
* Sets countOfSatelliteServiceEnablementsSuccess value of {@link SatelliteController}
@@ -561,6 +612,55 @@
}
/**
+ * Sets isProvisioned value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setIsProvisioned(boolean isProvisioned) {
+ this.mIsProvisioned = Optional.of(isProvisioned);
+ return this;
+ }
+
+ /**
+ * Sets Carrier ID value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = Optional.of(carrierId);
+ return this;
+ }
+
+ /**
+ * Sets countOfSatelliteAllowedStateChangedEvents value of {@link SatelliteController}
+ * atom
+ * then returns Builder class
+ */
+ public Builder setCountOfSatelliteAllowedStateChangedEvents(
+ int countOfSatelliteAllowedStateChangedEvents) {
+ this.mCountOfSatelliteAllowedStateChangedEvents =
+ countOfSatelliteAllowedStateChangedEvents;
+ return this;
+ }
+
+ /**
+ * Sets countOfSuccessfulLocationQueries value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfSuccessfulLocationQueries(
+ int countOfSuccessfulLocationQueries) {
+ this.mCountOfSuccessfulLocationQueries = countOfSuccessfulLocationQueries;
+ return this;
+ }
+
+ /**
+ * Sets countOfFailedLocationQueries value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfFailedLocationQueries(int countOfFailedLocationQueries) {
+ this.mCountOfFailedLocationQueries = countOfFailedLocationQueries;
+ return this;
+ }
+
+ /**
* Returns ControllerParams, which contains whole component of
* {@link SatelliteController} atom
*/
@@ -609,6 +709,12 @@
+ ", countOfAllowedSatelliteAccess=" + mCountOfAllowedSatelliteAccess
+ ", countOfDisallowedSatelliteAccess=" + mCountOfDisallowedSatelliteAccess
+ ", countOfSatelliteAccessCheckFail=" + mCountOfSatelliteAccessCheckFail
+ + ", isProvisioned=" + sIsProvisioned
+ + ", carrierId=" + sCarrierId
+ + ", countOfSatelliteAllowedStateChangedEvents="
+ + mCountOfSatelliteAllowedStateChangedEvents
+ + ", countOfSuccessfulLocationQueries=" + mCountOfSuccessfulLocationQueries
+ + ", countOfFailedLocationQueries=" + mCountOfFailedLocationQueries
+ ")";
}
}
@@ -630,6 +736,11 @@
private final int mCountOfIncomingDatagramFailed;
private final boolean mIsDemoMode;
private final @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
+ private final int mCarrierId;
+ private final int mCountOfSatelliteNotificationDisplayed;
+ private final int mCountOfAutoExitDueToScreenOff;
+ private final int mCountOfAutoExitDueToTnNetwork;
+
private SatelliteSessionParams(Builder builder) {
this.mSatelliteServiceInitializationResult =
@@ -646,6 +757,11 @@
this.mCountOfIncomingDatagramFailed = builder.mCountOfIncomingDatagramFailed;
this.mIsDemoMode = builder.mIsDemoMode;
this.mMaxNtnSignalStrengthLevel = builder.mMaxNtnSignalStrengthLevel;
+ this.mCarrierId = builder.mCarrierId;
+ this.mCountOfSatelliteNotificationDisplayed =
+ builder.mCountOfSatelliteNotificationDisplayed;
+ this.mCountOfAutoExitDueToScreenOff = builder.mCountOfAutoExitDueToScreenOff;
+ this.mCountOfAutoExitDueToTnNetwork = builder.mCountOfAutoExitDueToTnNetwork;
}
public int getSatelliteServiceInitializationResult() {
@@ -696,6 +812,22 @@
return mMaxNtnSignalStrengthLevel;
}
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
+ public int getCountOfSatelliteNotificationDisplayed() {
+ return mCountOfSatelliteNotificationDisplayed;
+ }
+
+ public int getCountOfAutoExitDueToScreenOff() {
+ return mCountOfAutoExitDueToScreenOff;
+ }
+
+ public int getCountOfAutoExitDueToTnNetwork() {
+ return mCountOfAutoExitDueToTnNetwork;
+ }
+
/**
* A builder class to create {@link SatelliteSessionParams} data structure class
*/
@@ -713,6 +845,10 @@
private boolean mIsDemoMode = false;
private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel =
NTN_SIGNAL_STRENGTH_NONE;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
+ private int mCountOfSatelliteNotificationDisplayed = -1;
+ private int mCountOfAutoExitDueToScreenOff = -1;
+ private int mCountOfAutoExitDueToTnNetwork = -1;
/**
* Sets satelliteServiceInitializationResult value of {@link SatelliteSession}
@@ -788,13 +924,49 @@
return this;
}
- /** Sets the max ntn signal strength for the satellite session */
+ /** Sets the max ntn signal strength for the satellite session. */
public Builder setMaxNtnSignalStrengthLevel(
@NtnSignalStrength.NtnSignalStrengthLevel int maxNtnSignalStrengthLevel) {
this.mMaxNtnSignalStrengthLevel = maxNtnSignalStrengthLevel;
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
+ /**
+ * Sets Total number of times the user is notified that the device is eligible for
+ * satellite service for this session.
+ */
+ public Builder setCountOfSatelliteNotificationDisplayed(
+ int countOfSatelliteNotificationDisplayed) {
+ this.mCountOfSatelliteNotificationDisplayed = countOfSatelliteNotificationDisplayed;
+ return this;
+ }
+
+ /**
+ * Sets Total number of times exit P2P message service automatically due to screen is
+ * off and timer is expired.
+ */
+ public Builder setCountOfAutoExitDueToScreenOff(
+ int countOfAutoExitDueToScreenOff) {
+ this.mCountOfAutoExitDueToScreenOff = countOfAutoExitDueToScreenOff;
+ return this;
+ }
+
+ /**
+ * Sets Total number of times times exit P2P message service automatically due to
+ * scan TN network.
+ */
+ public Builder setCountOfAutoExitDueToTnNetwork(
+ int countOfAutoExitDueToTnNetwork) {
+ this.mCountOfAutoExitDueToTnNetwork = countOfAutoExitDueToTnNetwork;
+ return this;
+ }
+
/**
* Returns SessionParams, which contains whole component of
* {@link SatelliteSession} atom
@@ -820,6 +992,11 @@
+ ", CountOfIncomingDatagramFailed=" + mCountOfIncomingDatagramFailed
+ ", IsDemoMode=" + mIsDemoMode
+ ", MaxNtnSignalStrengthLevel=" + mMaxNtnSignalStrengthLevel
+ + ", CarrierId=" + mCarrierId
+ + ", CountOfSatelliteNotificationDisplayed"
+ + mCountOfSatelliteNotificationDisplayed
+ + ", CountOfAutoExitDueToScreenOff" + mCountOfAutoExitDueToScreenOff
+ + ", CountOfAutoExitDueToTnNetwork" + mCountOfAutoExitDueToTnNetwork
+ ")";
}
}
@@ -833,12 +1010,14 @@
private final int mDatagramSizeBytes;
private final long mDatagramTransferTimeMillis;
private final boolean mIsDemoMode;
+ private final int mCarrierId;
private SatelliteIncomingDatagramParams(Builder builder) {
this.mResultCode = builder.mResultCode;
this.mDatagramSizeBytes = builder.mDatagramSizeBytes;
this.mDatagramTransferTimeMillis = builder.mDatagramTransferTimeMillis;
this.mIsDemoMode = builder.mIsDemoMode;
+ this.mCarrierId = builder.mCarrierId;
}
public int getResultCode() {
@@ -857,6 +1036,10 @@
return mIsDemoMode;
}
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
/**
* A builder class to create {@link SatelliteIncomingDatagramParams} data structure class
*/
@@ -865,6 +1048,7 @@
private int mDatagramSizeBytes = -1;
private long mDatagramTransferTimeMillis = -1;
private boolean mIsDemoMode = false;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
/**
* Sets resultCode value of {@link SatelliteIncomingDatagram} atom
@@ -902,6 +1086,12 @@
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
/**
* Returns IncomingDatagramParams, which contains whole component of
* {@link SatelliteIncomingDatagram} atom
@@ -919,6 +1109,7 @@
+ ", datagramSizeBytes=" + mDatagramSizeBytes
+ ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis
+ ", isDemoMode=" + mIsDemoMode
+ + ", CarrierId=" + mCarrierId
+ ")";
}
}
@@ -933,6 +1124,7 @@
private final int mDatagramSizeBytes;
private final long mDatagramTransferTimeMillis;
private final boolean mIsDemoMode;
+ private final int mCarrierId;
private SatelliteOutgoingDatagramParams(Builder builder) {
this.mDatagramType = builder.mDatagramType;
@@ -940,6 +1132,7 @@
this.mDatagramSizeBytes = builder.mDatagramSizeBytes;
this.mDatagramTransferTimeMillis = builder.mDatagramTransferTimeMillis;
this.mIsDemoMode = builder.mIsDemoMode;
+ this.mCarrierId = builder.mCarrierId;
}
public int getDatagramType() {
@@ -962,6 +1155,10 @@
return mIsDemoMode;
}
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
/**
* A builder class to create {@link SatelliteOutgoingDatagramParams} data structure class
*/
@@ -971,6 +1168,7 @@
private int mDatagramSizeBytes = -1;
private long mDatagramTransferTimeMillis = -1;
private boolean mIsDemoMode = false;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
/**
* Sets datagramType value of {@link SatelliteOutgoingDatagram} atom
@@ -1017,6 +1215,12 @@
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
/**
* Returns OutgoingDatagramParams, which contains whole component of
* {@link SatelliteOutgoingDatagram} atom
@@ -1035,6 +1239,7 @@
+ ", datagramSizeBytes=" + mDatagramSizeBytes
+ ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis
+ ", isDemoMode=" + mIsDemoMode
+ + ", CarrierId=" + mCarrierId
+ ")";
}
}
@@ -1048,12 +1253,14 @@
private final int mProvisioningTimeSec;
private final boolean mIsProvisionRequest;
private final boolean mIsCanceled;
+ private final int mCarrierId;
private SatelliteProvisionParams(Builder builder) {
this.mResultCode = builder.mResultCode;
this.mProvisioningTimeSec = builder.mProvisioningTimeSec;
this.mIsProvisionRequest = builder.mIsProvisionRequest;
this.mIsCanceled = builder.mIsCanceled;
+ this.mCarrierId = builder.mCarrierId;
}
public int getResultCode() {
@@ -1072,6 +1279,10 @@
return mIsCanceled;
}
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
/**
* A builder class to create {@link SatelliteProvisionParams} data structure class
*/
@@ -1080,6 +1291,7 @@
private int mProvisioningTimeSec = -1;
private boolean mIsProvisionRequest = false;
private boolean mIsCanceled = false;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
/**
* Sets resultCode value of {@link SatelliteProvision} atom
@@ -1117,6 +1329,12 @@
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
/**
* Returns ProvisionParams, which contains whole component of
* {@link SatelliteProvision} atom
@@ -1133,7 +1351,9 @@
+ "resultCode=" + mResultCode
+ ", provisioningTimeSec=" + mProvisioningTimeSec
+ ", isProvisionRequest=" + mIsProvisionRequest
- + ", isCanceled" + mIsCanceled + ")";
+ + ", isCanceled" + mIsCanceled
+ + ", CarrierId=" + mCarrierId
+ + ")";
}
}
@@ -1149,6 +1369,8 @@
private final boolean mIsMultiSim;
private final int mRecommendingHandoverType;
private final boolean mIsSatelliteAllowedInCurrentLocation;
+ private final boolean mIsWifiConnected;
+ private final int mCarrierId;
private SatelliteSosMessageRecommenderParams(Builder builder) {
this.mIsDisplaySosMessageSent = builder.mIsDisplaySosMessageSent;
@@ -1159,6 +1381,8 @@
this.mRecommendingHandoverType = builder.mRecommendingHandoverType;
this.mIsSatelliteAllowedInCurrentLocation =
builder.mIsSatelliteAllowedInCurrentLocation;
+ this.mIsWifiConnected = builder.mIsWifiConnected;
+ this.mCarrierId = builder.mCarrierId;
}
public boolean isDisplaySosMessageSent() {
@@ -1189,6 +1413,14 @@
return mIsSatelliteAllowedInCurrentLocation;
}
+ public boolean isWifiConnected() {
+ return mIsWifiConnected;
+ }
+
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
/**
* A builder class to create {@link SatelliteProvisionParams} data structure class
*/
@@ -1200,6 +1432,8 @@
private boolean mIsMultiSim = false;
private int mRecommendingHandoverType = -1;
private boolean mIsSatelliteAllowedInCurrentLocation = false;
+ private boolean mIsWifiConnected = false;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
/**
@@ -1268,6 +1502,24 @@
}
/**
+ * Sets whether Wi-Fi is connected value of {@link SatelliteSosMessageRecommender} atom
+ * then returns Builder class
+ */
+ public Builder setIsWifiConnected(boolean isWifiConnected) {
+ this.mIsWifiConnected = isWifiConnected;
+ return this;
+ }
+
+ /**
+ * Sets carrier ID value of {@link SatelliteSosMessageRecommender} atom then returns
+ * Builder class.
+ */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
+ /**
* Returns SosMessageRecommenderParams, which contains whole component of
* {@link SatelliteSosMessageRecommenderParams} atom
*/
@@ -1287,7 +1539,10 @@
+ ", isMultiSim=" + mIsMultiSim
+ ", recommendingHandoverType=" + mRecommendingHandoverType
+ ", isSatelliteAllowedInCurrentLocation="
- + mIsSatelliteAllowedInCurrentLocation + ")";
+ + mIsSatelliteAllowedInCurrentLocation
+ + ", isWifiConnected=" + mIsWifiConnected
+ + ", carrierId=" + mCarrierId
+ + ")";
}
}
@@ -1614,6 +1869,8 @@
private final int mSatelliteSessionGapMinSec;
private final int mSatelliteSessionGapAvgSec;
private final int mSatelliteSessionGapMaxSec;
+ private static int sCarrierId;
+ private static boolean sIsDeviceEntitled;
private CarrierRoamingSatelliteControllerStatsParams(Builder builder) {
this.mConfigDataSource = builder.mConfigDataSource;
@@ -1626,6 +1883,16 @@
this.mSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec;
this.mSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec;
this.mSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec;
+
+ // Carrier ID value should be updated only when it is meaningful.
+ if (builder.mCarrierId.isPresent()) {
+ this.sCarrierId = builder.mCarrierId.get();
+ }
+
+ // isDeviceEntitled value should be updated only when it is meaningful.
+ if (builder.mIsDeviceEntitled.isPresent()) {
+ this.sIsDeviceEntitled = builder.mIsDeviceEntitled.get();
+ }
}
public int getConfigDataSource() {
@@ -1657,6 +1924,14 @@
return mSatelliteSessionGapMaxSec;
}
+ public int getCarrierId() {
+ return sCarrierId;
+ }
+
+ public boolean isDeviceEntitled() {
+ return sIsDeviceEntitled;
+ }
+
/**
* A builder class to create {@link CarrierRoamingSatelliteControllerStatsParams}
* data structure class
@@ -1669,6 +1944,8 @@
private int mSatelliteSessionGapMinSec = 0;
private int mSatelliteSessionGapAvgSec = 0;
private int mSatelliteSessionGapMaxSec = 0;
+ private Optional<Integer> mCarrierId = Optional.empty();
+ private Optional<Boolean> mIsDeviceEntitled = Optional.empty();
/**
* Sets configDataSource value of {@link CarrierRoamingSatelliteControllerStats} atom
@@ -1736,6 +2013,18 @@
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = Optional.of(carrierId);
+ return this;
+ }
+
+ /** Sets whether the device is currently entitled or not. */
+ public Builder setIsDeviceEntitled(boolean isDeviceEntitled) {
+ this.mIsDeviceEntitled = Optional.of(isDeviceEntitled);
+ return this;
+ }
+
/**
* Returns CarrierRoamingSatelliteControllerStatsParams, which contains whole component
* of {@link CarrierRoamingSatelliteControllerStats} atom
@@ -1759,6 +2048,8 @@
+ ", satelliteSessionGapMinSec=" + mSatelliteSessionGapMinSec
+ ", satelliteSessionGapAvgSec=" + mSatelliteSessionGapAvgSec
+ ", satelliteSessionGapMaxSec=" + mSatelliteSessionGapMaxSec
+ + ", carrierId=" + sCarrierId
+ + ", isDeviceEntitled=" + sIsDeviceEntitled
+ ")";
}
}
@@ -1990,6 +2281,8 @@
private final @SatelliteManager.SatelliteResult int mResultCode;
private final String[] mCountryCodes;
private final @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+ private final int mCarrierId;
+ private final int mTriggeringEvent;
private SatelliteAccessControllerParams(Builder builder) {
this.mAccessControlType = builder.mAccessControlType;
@@ -2001,6 +2294,8 @@
this.mResultCode = builder.mResultCode;
this.mCountryCodes = builder.mCountryCodes;
this.mConfigDataSource = builder.mConfigDataSource;
+ this.mCarrierId = builder.mCarrierId;
+ this.mTriggeringEvent = builder.mTriggeringEvent;
}
public @SatelliteConstants.AccessControlType int getAccessControlType() {
@@ -2039,6 +2334,14 @@
return mConfigDataSource;
}
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
+ @SatelliteConstants.TriggeringEvent public int getTriggeringEvent() {
+ return mTriggeringEvent;
+ }
+
/**
* A builder class to create {@link SatelliteAccessControllerParams} data structure class
*/
@@ -2052,6 +2355,9 @@
private @SatelliteManager.SatelliteResult int mResultCode;
private String[] mCountryCodes;
private @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+ private int mCarrierId = UNKNOWN_CARRIER_ID;
+ private @SatelliteConstants.TriggeringEvent int mTriggeringEvent =
+ TRIGGERING_EVENT_UNKNOWN;
/**
* Sets AccessControlType value of {@link #SatelliteAccessController}
@@ -2113,6 +2419,19 @@
return this;
}
+ /** Sets the currently active NB-IoT NTN carrier ID. */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
+ /** Sets the triggering evenr for current satellite access controller metric. */
+ public Builder setTriggeringEvent(
+ @SatelliteConstants.TriggeringEvent int triggeringEvent) {
+ this.mTriggeringEvent = triggeringEvent;
+ return this;
+ }
+
/**
* Returns AccessControllerParams, which contains whole component of
* {@link #SatelliteAccessController} atom
@@ -2135,6 +2454,8 @@
+ ", ResultCode=" + mResultCode
+ ", CountryCodes=" + Arrays.toString(mCountryCodes)
+ ", ConfigDataSource=" + mConfigDataSource
+ + ", CarrierId=" + mCarrierId
+ + ", TriggeringEvent=" + mTriggeringEvent
+ ")";
}
}
@@ -2175,6 +2496,16 @@
proto.countOfDemoModeIncomingDatagramFail = param.getCountOfDemoModeIncomingDatagramFail();
proto.countOfDatagramTypeKeepAliveSuccess = param.getCountOfDatagramTypeKeepAliveSuccess();
proto.countOfDatagramTypeKeepAliveFail = param.getCountOfDatagramTypeKeepAliveFail();
+ proto.countOfAllowedSatelliteAccess = param.getCountOfAllowedSatelliteAccess();
+ proto.countOfDisallowedSatelliteAccess = param.getCountOfDisallowedSatelliteAccess();
+ proto.countOfSatelliteAccessCheckFail = param.getCountOfSatelliteAccessCheckFail();
+ proto.isProvisioned = param.isProvisioned();
+ proto.carrierId = param.getCarrierId();
+ proto.countOfSatelliteAllowedStateChangedEvents =
+ param.getCountOfSatelliteAllowedStateChangedEvents();
+ proto.countOfSuccessfulLocationQueries = param.getCountOfSuccessfulLocationQueries();
+ proto.countOfFailedLocationQueries = param.getCountOfFailedLocationQueries();
+
mAtomsStorage.addSatelliteControllerStats(proto);
}
@@ -2195,6 +2526,11 @@
proto.countOfIncomingDatagramFailed = param.getCountOfOutgoingDatagramFailed();
proto.isDemoMode = param.getIsDemoMode();
proto.maxNtnSignalStrengthLevel = param.getMaxNtnSignalStrengthLevel();
+ proto.carrierId = param.getCarrierId();
+ proto.countOfSatelliteNotificationDisplayed =
+ param.getCountOfSatelliteNotificationDisplayed();
+ proto.countOfAutoExitDueToScreenOff = param.getCountOfAutoExitDueToScreenOff();
+ proto.countOfAutoExitDueToTnNetwork = param.getCountOfAutoExitDueToTnNetwork();
mAtomsStorage.addSatelliteSessionStats(proto);
}
@@ -2206,6 +2542,7 @@
proto.datagramSizeBytes = param.getDatagramSizeBytes();
proto.datagramTransferTimeMillis = param.getDatagramTransferTimeMillis();
proto.isDemoMode = param.getIsDemoMode();
+ proto.carrierId = param.getCarrierId();
mAtomsStorage.addSatelliteIncomingDatagramStats(proto);
}
@@ -2218,6 +2555,7 @@
proto.datagramSizeBytes = param.getDatagramSizeBytes();
proto.datagramTransferTimeMillis = param.getDatagramTransferTimeMillis();
proto.isDemoMode = param.getIsDemoMode();
+ proto.carrierId = param.getCarrierId();
mAtomsStorage.addSatelliteOutgoingDatagramStats(proto);
}
@@ -2228,6 +2566,7 @@
proto.provisioningTimeSec = param.getProvisioningTimeSec();
proto.isProvisionRequest = param.getIsProvisionRequest();
proto.isCanceled = param.getIsCanceled();
+ proto.carrierId = param.getCarrierId();
mAtomsStorage.addSatelliteProvisionStats(proto);
}
@@ -2242,6 +2581,8 @@
proto.isMultiSim = param.isMultiSim();
proto.recommendingHandoverType = param.getRecommendingHandoverType();
proto.isSatelliteAllowedInCurrentLocation = param.isSatelliteAllowedInCurrentLocation();
+ proto.isWifiConnected = param.isWifiConnected();
+ proto.carrierId = param.getCarrierId();
proto.count = 1;
mAtomsStorage.addSatelliteSosMessageRecommenderStats(proto);
}
@@ -2280,6 +2621,8 @@
proto.satelliteSessionGapMinSec = param.mSatelliteSessionGapMinSec;
proto.satelliteSessionGapAvgSec = param.mSatelliteSessionGapAvgSec;
proto.satelliteSessionGapMaxSec = param.mSatelliteSessionGapMaxSec;
+ proto.carrierId = param.getCarrierId();
+ proto.isDeviceEntitled = param.isDeviceEntitled();
mAtomsStorage.addCarrierRoamingSatelliteControllerStats(proto);
}
@@ -2317,6 +2660,8 @@
proto.resultCode = param.getResultCode();
proto.countryCodes = param.getCountryCodes();
proto.configDataSource = param.getConfigDataSource();
+ proto.carrierId = param.getCarrierId();
+ proto.triggeringEvent = param.getTriggeringEvent();
mAtomsStorage.addSatelliteAccessControllerStats(proto);
}
}
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index 911424e..b6a26c6 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -26,6 +26,16 @@
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DIALING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_HOLDING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_IDLE;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_INCOMING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_WAITING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_FULLBAND;
@@ -540,6 +550,7 @@
// Compute time it took to fail setup (except for MT calls that have never been picked up)
if (proto.setupFailed && proto.setupBeginMillis != 0L && proto.setupDurationMillis == 0) {
+ proto.preciseCallStateOnSetup = convertCallStateEnumToInt(Call.State.DISCONNECTED);
proto.setupDurationMillis = (int) (getTimeMillis() - proto.setupBeginMillis);
}
@@ -632,6 +643,7 @@
private void checkCallSetup(Connection conn, VoiceCallSession proto) {
if (proto.setupBeginMillis != 0L && isSetupFinished(conn.getCall())) {
+ proto.preciseCallStateOnSetup = convertCallStateEnumToInt(conn.getState());
proto.setupDurationMillis = (int) (getTimeMillis() - proto.setupBeginMillis);
proto.setupBeginMillis = 0L;
}
@@ -1092,4 +1104,29 @@
proto.handoverInProgress = false;
}
}
+
+ private int convertCallStateEnumToInt(Call.State state) {
+ switch (state) {
+ case IDLE:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_IDLE;
+ case ACTIVE:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
+ case HOLDING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_HOLDING;
+ case DIALING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DIALING;
+ case ALERTING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
+ case INCOMING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_INCOMING;
+ case WAITING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_WAITING;
+ case DISCONNECTED:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
+ case DISCONNECTING:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTING;
+ default:
+ return VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index ff2ee9f..9f6edf2 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.satellite;
-import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@@ -253,6 +252,7 @@
@NonNull Consumer<Integer> callback) {
mDatagramDispatcher.sendSatelliteDatagram(subId, datagramType, datagram,
needFullScreenPointingUI, callback);
+ mPointingAppController.onSendDatagramRequested(subId, datagramType);
}
/**
@@ -282,7 +282,7 @@
mSendDatagramTransferState = datagramTransferState;
mSendPendingCount = sendPendingCount;
mSendErrorCode = errorCode;
- notifyDatagramTransferStateChangedToSessionController();
+ notifyDatagramTransferStateChangedToSessionController(mDatagramType);
mPointingAppController.updateSendDatagramTransferState(mSendSubId, mDatagramType,
mSendDatagramTransferState, mSendPendingCount, mSendErrorCode);
retryPollPendingDatagramsInDemoMode();
@@ -311,21 +311,23 @@
* @param receivePendingCount The number of datagrams that are currently pending to be received.
* @param errorCode If datagram transfer failed, the reason for failure.
*/
- public void updateReceiveStatus(int subId,
+ public void updateReceiveStatus(int subId, @SatelliteManager.DatagramType int datagramType,
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int receivePendingCount, int errorCode) {
synchronized (mLock) {
plogd("updateReceiveStatus"
+ " subId: " + subId
+ + " datagramType: " + datagramType
+ " datagramTransferState: " + datagramTransferState
+ " receivePendingCount: " + receivePendingCount + " errorCode: " + errorCode);
mReceiveSubId = subId;
+ mDatagramType = datagramType;
mReceiveDatagramTransferState = datagramTransferState;
mReceivePendingCount = receivePendingCount;
mReceiveErrorCode = errorCode;
- notifyDatagramTransferStateChangedToSessionController();
+ notifyDatagramTransferStateChangedToSessionController(mDatagramType);
mPointingAppController.updateReceiveDatagramTransferState(mReceiveSubId,
mReceiveDatagramTransferState, mReceivePendingCount, mReceiveErrorCode);
retryPollPendingDatagramsInDemoMode();
@@ -344,6 +346,12 @@
return mReceivePendingCount;
}
+
+ /** @return {@code true} if already sent an emergency datagram during a session. */
+ public boolean isEmergencyCommunicationEstablished() {
+ return mDatagramDispatcher.isEmergencyCommunicationEstablished();
+ }
+
/**
* This function is used by {@link SatelliteController} to notify {@link DatagramController}
* that satellite modem state has changed.
@@ -359,6 +367,24 @@
}
/**
+ * Notify SMS received.
+ *
+ * @param subId The subId of the subscription used to receive SMS
+ */
+ public void onSmsReceived(int subId) {
+ // To keep exist notification flow, need to call with each state.
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ updateReceiveStatus(subId, SatelliteManager.DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ getReceivePendingCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ }
+
+ /**
* Set whether the device is aligned with the satellite.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -559,14 +585,16 @@
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
- private void notifyDatagramTransferStateChangedToSessionController() {
+ private void notifyDatagramTransferStateChangedToSessionController(int datagramType) {
SatelliteSessionController sessionController = SatelliteSessionController.getInstance();
if (sessionController == null) {
ploge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
+ " is not initialized yet");
} else {
- sessionController.onDatagramTransferStateChanged(
- mSendDatagramTransferState, mReceiveDatagramTransferState);
+ synchronized (mLock) {
+ sessionController.onDatagramTransferStateChanged(
+ mSendDatagramTransferState, mReceiveDatagramTransferState, datagramType);
+ }
}
}
@@ -609,7 +637,9 @@
}
}
};
- pollPendingSatelliteDatagrams(DEFAULT_SUBSCRIPTION_ID, internalCallback);
+ pollPendingSatelliteDatagrams(
+ SatelliteController.getInstance().getSelectedSatelliteSubId(),
+ internalCallback);
}
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 2c9463f..42aa2aa 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -16,13 +16,16 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,14 +38,15 @@
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.PersistentLogger;
import android.telephony.Rlog;
-import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.SatelliteStats;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
@@ -69,6 +73,8 @@
private static final int EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT = 5;
private static final int EVENT_ABORT_SENDING_SATELLITE_DATAGRAMS_DONE = 6;
private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
+ private static final int CMD_SEND_SMS = 8;
+ private static final int EVENT_SEND_SMS_DONE = 9;
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@@ -88,8 +94,12 @@
private final Object mLock = new Object();
private long mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
+ /** {@code true} if already sent an emergency datagram during a session */
@GuardedBy("mLock")
- private boolean mSendingDatagramInProgress;
+ private boolean mIsEmergencyCommunicationEstablished = false;
+
+ @GuardedBy("mLock")
+ private boolean mSendingInProgress;
/**
* Map key: datagramId, value: SendSatelliteDatagramArgument to retry sending emergency
@@ -107,6 +117,13 @@
private final LinkedHashMap<Long, SendSatelliteDatagramArgument>
mPendingNonEmergencyDatagramsMap = new LinkedHashMap<>();
+ /**
+ * Map key: messageId, value: {@link PendingRequest} which contains all the information to send
+ * carrier roaming nb iot ntn SMS.
+ */
+ @GuardedBy("mLock")
+ private final LinkedHashMap<Long, PendingRequest> mPendingSmsMap = new LinkedHashMap<>();
+
private long mWaitTimeForDatagramSendingResponse;
private long mWaitTimeForDatagramSendingForLastMessageResponse;
@SatelliteManager.DatagramType
@@ -164,7 +181,7 @@
}
synchronized (mLock) {
- mSendingDatagramInProgress = false;
+ mSendingInProgress = false;
}
mWaitTimeForDatagramSendingResponse = getWaitForDatagramSendingResponseTimeoutMillis();
mWaitTimeForDatagramSendingForLastMessageResponse =
@@ -289,13 +306,16 @@
}
stopWaitForDatagramSendingResponseTimer();
- mSendingDatagramInProgress = false;
+ mSendingInProgress = false;
// Log metrics about the outgoing datagram
reportSendDatagramCompleted(argument, error);
// Remove current datagram from pending map.
if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) {
mPendingEmergencyDatagramsMap.remove(argument.datagramId);
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ mIsEmergencyCommunicationEstablished = true;
+ }
} else {
mPendingNonEmergencyDatagramsMap.remove(argument.datagramId);
}
@@ -304,20 +324,20 @@
// Update send status for current datagram
mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
- getPendingDatagramCount(), error);
+ getPendingMessagesCount(), error);
startWaitForSimulatedPollDatagramsDelayTimer(request);
} else {
// Update send status
mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- getPendingDatagramCount(), error);
+ getPendingMessagesCount(), error);
}
- if (getPendingDatagramCount() > 0) {
+ if (getPendingMessagesCount() > 0) {
// Send response for current datagram
argument.callback.accept(error);
// Send pending datagrams
- sendPendingDatagrams();
+ sendPendingMessages();
} else {
mDatagramController.updateSendStatus(argument.subId,
argument.datagramType,
@@ -341,8 +361,7 @@
}
case EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT:
- handleEventDatagramWaitForConnectedStateTimedOut(
- (SendSatelliteDatagramArgument) msg.obj);
+ handleEventDatagramWaitForConnectedStateTimedOut((int) msg.obj);
break;
case EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT:
@@ -351,6 +370,38 @@
(SendSatelliteDatagramArgument) request.argument);
break;
+ case CMD_SEND_SMS: {
+ PendingRequest pendingRequest = (PendingRequest) msg.obj;
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("CMD_SEND_SMS: satellitePhone is null.");
+ return;
+ }
+
+ SmsDispatchersController smsDispatchersController =
+ satellitePhone.getSmsDispatchersController();
+ if (smsDispatchersController == null) {
+ ploge("CMD_SEND_SMS: smsDispatchersController is null.");
+ return;
+ }
+
+ smsDispatchersController.sendCarrierRoamingNbIotNtnText(pendingRequest);
+ break;
+ }
+
+ case EVENT_SEND_SMS_DONE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ int subId = (int) args.arg1;
+ long messageId = (long) args.arg2;
+ boolean success = (boolean) args.arg3;
+ try {
+ handleEventSendSmsDone(subId, messageId, success);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+
default:
plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
@@ -397,28 +448,27 @@
plogd("sendDatagram: wait for satellite connected");
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
- startDatagramWaitForConnectedStateTimer(datagramArgs);
- } else if (!mSendingDatagramInProgress && mDatagramController.isPollingInIdleState()) {
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(datagramArgs.datagramType);
+ } else if (!mSendingInProgress && mDatagramController.isPollingInIdleState()) {
// Modem can be busy receiving datagrams, so send datagram only when modem is
// not busy.
- mSendingDatagramInProgress = true;
+ mSendingInProgress = true;
datagramArgs.setDatagramStartTime();
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArgs, phone);
} else {
- plogd("sendDatagram: mSendingDatagramInProgress="
- + mSendingDatagramInProgress + ", isPollingInIdleState="
- + mDatagramController.isPollingInIdleState());
+ plogd("sendDatagram: mSendingInProgress=" + mSendingInProgress
+ + ", isPollingInIdleState=" + mDatagramController.isPollingInIdleState());
}
}
}
public void retrySendingDatagrams() {
synchronized (mLock) {
- sendPendingDatagrams();
+ sendPendingMessages();
}
}
@@ -500,6 +550,23 @@
removeMessages(EVENT_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_MODE_TIMED_OUT);
}
+ @GuardedBy("mLock")
+ private void sendPendingMessages() {
+ plogd("sendPendingMessages");
+
+ // Pending datagrams are prioritized over pending SMS.
+ if (getPendingDatagramCount() > 0) {
+ sendPendingDatagrams();
+ return;
+ }
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (getPendingSmsCount() > 0) {
+ sendPendingSms();
+ }
+ }
+ }
+
/**
* Send pending satellite datagrams. Emergency datagrams are given priority over
* non-emergency datagrams.
@@ -520,9 +587,9 @@
Phone phone = SatelliteServiceUtils.getPhone();
Set<Entry<Long, SendSatelliteDatagramArgument>> pendingDatagram = null;
- if (!mSendingDatagramInProgress && !mPendingEmergencyDatagramsMap.isEmpty()) {
+ if (!mSendingInProgress && !mPendingEmergencyDatagramsMap.isEmpty()) {
pendingDatagram = mPendingEmergencyDatagramsMap.entrySet();
- } else if (!mSendingDatagramInProgress && !mPendingNonEmergencyDatagramsMap.isEmpty()) {
+ } else if (!mSendingInProgress && !mPendingNonEmergencyDatagramsMap.isEmpty()) {
pendingDatagram = mPendingNonEmergencyDatagramsMap.entrySet();
}
@@ -534,12 +601,12 @@
return;
}
- mSendingDatagramInProgress = true;
+ mSendingInProgress = true;
// Sets the trigger time for getting pending datagrams
datagramArg.setDatagramStartTime();
mDatagramController.updateSendStatus(datagramArg.subId, datagramArg.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArg, phone);
}
}
@@ -583,6 +650,21 @@
plogd("abortSendingPendingDatagrams()");
sendErrorCodeAndCleanupPendingDatagrams(mPendingEmergencyDatagramsMap, errorCode);
sendErrorCodeAndCleanupPendingDatagrams(mPendingNonEmergencyDatagramsMap, errorCode);
+ sendErrorCodeAndCleanupPendingSms(mPendingSmsMap, errorCode);
+ }
+
+ /**
+ * Return pending datagram and SMS count
+ * @return pending messages count
+ */
+ public int getPendingMessagesCount() {
+ synchronized (mLock) {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return getPendingDatagramCount() + getPendingSmsCount();
+ } else {
+ return getPendingDatagramCount();
+ }
+ }
}
/**
@@ -595,6 +677,16 @@
}
}
+ /**
+ * Return pending SMS count
+ * @return pending SMS count
+ */
+ public int getPendingSmsCount() {
+ synchronized (mLock) {
+ return mPendingSmsMap.size();
+ }
+ }
+
/** Return pending user messages count */
public int getPendingUserMessagesCount() {
synchronized (mLock) {
@@ -637,6 +729,7 @@
.setDatagramTransferTimeMillis(argument.datagramStartTime > 0
? (System.currentTimeMillis() - argument.datagramStartTime) : 0)
.setIsDemoMode(mIsDemoMode)
+ .setCarrierId(SatelliteController.getInstance().getSatelliteCarrierId())
.build());
if (resultCode == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
mControllerMetricsStats.reportOutgoingDatagramSuccessCount(argument.datagramType,
@@ -671,13 +764,13 @@
plogd("onSatelliteModemStateChanged: cleaning up resources");
cleanUpResources();
} else if (state == SatelliteManager.SATELLITE_MODEM_STATE_IDLE) {
- sendPendingDatagrams();
+ sendPendingMessages();
}
if (state == SATELLITE_MODEM_STATE_CONNECTED
&& isDatagramWaitForConnectedStateTimerStarted()) {
stopDatagramWaitForConnectedStateTimer();
- sendPendingDatagrams();
+ sendPendingMessages();
}
}
}
@@ -685,18 +778,21 @@
@GuardedBy("mLock")
private void cleanUpResources() {
plogd("cleanUpResources");
- mSendingDatagramInProgress = false;
- if (getPendingDatagramCount() > 0) {
- mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mSendingInProgress = false;
+ mIsEmergencyCommunicationEstablished = false;
+
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
+ if (getPendingMessagesCount() > 0) {
+ mDatagramController.updateSendStatus(subId,
mLastSendRequestDatagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
}
- mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mDatagramController.updateSendStatus(subId,
mLastSendRequestDatagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
- abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ abortSendingPendingDatagrams(subId,
SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
stopSatelliteAlignedTimer();
@@ -709,16 +805,23 @@
mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
}
+ /** @return {@code true} if already sent an emergency datagram during a session. */
+ public boolean isEmergencyCommunicationEstablished() {
+ synchronized (mLock) {
+ return mIsEmergencyCommunicationEstablished;
+ }
+ }
+
private void startDatagramWaitForConnectedStateTimer(
- @NonNull SendSatelliteDatagramArgument datagramArgs) {
+ @SatelliteManager.DatagramType int datagramType) {
if (isDatagramWaitForConnectedStateTimerStarted()) {
plogd("DatagramWaitForConnectedStateTimer is already started");
return;
}
sendMessageDelayed(obtainMessage(
- EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT, datagramArgs),
+ EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT, datagramType),
mDatagramController.getDatagramWaitTimeForConnectedState(
- SatelliteServiceUtils.isLastSosMessage(datagramArgs.datagramType)));
+ SatelliteServiceUtils.isLastSosMessage(datagramType)));
}
private void stopDatagramWaitForConnectedStateTimer() {
@@ -761,20 +864,21 @@
}
private void handleEventDatagramWaitForConnectedStateTimedOut(
- @NonNull SendSatelliteDatagramArgument argument) {
+ @SatelliteManager.DatagramType int datagramType) {
plogw("Timed out to wait for satellite connected before sending datagrams");
synchronized (mLock) {
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
// Update send status
- mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- argument.datagramType,
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- getPendingDatagramCount(),
+ getPendingMessagesCount(),
SATELLITE_RESULT_NOT_REACHABLE);
- mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- argument.datagramType,
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
- abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ abortSendingPendingDatagrams(subId,
SATELLITE_RESULT_NOT_REACHABLE);
}
}
@@ -827,12 +931,12 @@
// Ask vendor service to abort all datagram-sending requests
SatelliteModemInterface.getInstance().abortSendingSatelliteDatagrams(
obtainMessage(EVENT_ABORT_SENDING_SATELLITE_DATAGRAMS_DONE, argument));
- mSendingDatagramInProgress = false;
+ mSendingInProgress = false;
// Update send status
mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- getPendingDatagramCount(), SATELLITE_RESULT_MODEM_TIMEOUT);
+ getPendingMessagesCount(), SATELLITE_RESULT_MODEM_TIMEOUT);
mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -934,6 +1038,164 @@
plogd("setTimeoutDatagramDelayInDemoMode " + mDemoTimeoutDuration + " reset=" + reset);
}
+ /**
+ * Send carrier roaming nb iot ntn sms.
+ *
+ * Store SMS in a pending list until following conditions are met:
+ * - If messages can be sent only when satellite is connected, then wait until modem state
+ * becomes {@link SatelliteManager#SATELLITE_MODEM_STATE_CONNECTED}
+ * - If modem is already sending datagrms/SMS or receiving datagrams, then wait until modem
+ * becomes IDLE to send current SMS.
+ *
+ * @param pendingSms {@link PendingRequest} that contains all the information required to send
+ * carrier roaming nb iot ntn SMS.
+ */
+ public void sendSms(@NonNull PendingRequest pendingSms) {
+ SatelliteController.getInstance().startPointingUI();
+
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
+ long messageId = pendingSms.uniqueMessageId;
+ plogd("sendSms: subId=" + subId + " messageId:" + messageId);
+
+ synchronized (mLock) {
+ // Add SMS to pending list
+ mPendingSmsMap.put(messageId, pendingSms);
+ int datagramType = SatelliteManager.DATAGRAM_TYPE_SMS;
+ mLastSendRequestDatagramType = datagramType;
+
+ if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
+ plogd("sendSms: wait for satellite connected");
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(datagramType);
+ } else if (!mSendingInProgress && mDatagramController.isPollingInIdleState()) {
+ mSendingInProgress = true;
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ getPendingMessagesCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
+
+ sendMessage(obtainMessage(CMD_SEND_SMS, pendingSms));
+ } else {
+ plogd("sendSms: mSendingInProgress=" + mSendingInProgress
+ + ", isPollingInIdleState=" + mDatagramController.isPollingInIdleState());
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void sendPendingSms() {
+ plogd("sendPendingSms");
+ if (!mDatagramController.isPollingInIdleState()) {
+ // Datagram or SMS should be sent to satellite modem when modem is free.
+ plogd("sendPendingSms: modem is receiving datagrams");
+ return;
+ }
+
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
+ Set<Entry<Long, PendingRequest>> pendingSms = null;
+ if (!mSendingInProgress) {
+ pendingSms = mPendingSmsMap.entrySet();
+ }
+
+ if (pendingSms != null && pendingSms.iterator().hasNext()) {
+ if (mDatagramController.needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SMS)) {
+ plogd("sendPendingSms: wait for satellite connected");
+ return;
+ }
+
+ mSendingInProgress = true;
+ PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
+ mDatagramController.updateSendStatus(subId, DATAGRAM_TYPE_SMS,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
+ } else {
+ plogd("sendPendingSms: mSendingInProgress=" + mSendingInProgress
+ + " pendingSmsCount=" + getPendingSmsCount());
+ }
+ }
+
+ /**
+ * Sending MO SMS is completed.
+ * @param subId subscription ID
+ * @param messageId message ID of MO SMS
+ * @param success boolean specifying whether MO SMS is successfully sent or not.
+ */
+ public void onSendSmsDone(int subId, long messageId, boolean success) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = subId;
+ args.arg2 = messageId;
+ args.arg3 = success;
+ sendMessage(obtainMessage(EVENT_SEND_SMS_DONE, args));
+ }
+
+ @GuardedBy("mLock")
+ private void sendErrorCodeAndCleanupPendingSms(
+ LinkedHashMap<Long, PendingRequest> pendingSmsMap,
+ @SatelliteManager.SatelliteResult int errorCode) {
+ if (pendingSmsMap.size() == 0) {
+ plogd("sendErrorCodeAndCleanupPendingSms: pendingSmsMap is empty.");
+ return;
+ }
+ ploge("sendErrorCodeAndCleanupPendingSms: cleaning up resources. "
+ + "pendingSmsMap size=" + getPendingSmsCount());
+
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendErrorCodeAndCleanupPendingSms: satellitePhone is null.");
+ pendingSmsMap.clear();
+ return;
+ }
+
+ SmsDispatchersController smsDispatchersController =
+ satellitePhone.getSmsDispatchersController();
+ if (smsDispatchersController == null) {
+ ploge("sendErrorCodeAndCleanupPendingSms: smsDispatchersController is null.");
+ pendingSmsMap.clear();
+ return;
+ }
+
+ // Send error code to all the pending text
+ for (Entry<Long, PendingRequest> entry : pendingSmsMap.entrySet()) {
+ PendingRequest pendingRequest = entry.getValue();
+ smsDispatchersController.onSendCarrierRoamingNbIotNtnTextError(
+ pendingRequest, errorCode);
+ }
+
+ // Clear pending text map
+ pendingSmsMap.clear();
+ }
+
+ private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
+ synchronized (mLock) {
+ mSendingInProgress = false;
+ mPendingSmsMap.remove(messageId);
+ int datagramType = DATAGRAM_TYPE_SMS;
+
+ plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
+ + " success=" + success);
+ if (success) {
+ // Update send status for current datagram
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+ getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ } else {
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
+ getPendingMessagesCount(), SATELLITE_RESULT_NETWORK_ERROR);
+ }
+
+ if (getPendingMessagesCount() > 0) {
+ sendPendingMessages();
+ } else {
+ mDatagramController.updateSendStatus(subId, datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ }
+ }
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index ea75f03..a921b89 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -352,10 +352,12 @@
if (pendingCount <= 0 && satelliteDatagram == null) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
} else if (satelliteDatagram != null) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -376,6 +378,7 @@
if (pendingCount <= 0) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
pendingCount, SatelliteManager.SATELLITE_RESULT_SUCCESS);
} else {
@@ -455,8 +458,7 @@
if (mIsDemoMode && error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
SatelliteDatagram datagram = mDatagramController.popDemoModeDatagram();
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(
- request.subId, mContext);
+ final int validSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteDatagramListenerHandler listenerHandler =
mSatelliteDatagramListenerHandlers.get(validSubId);
if (listenerHandler != null) {
@@ -474,10 +476,12 @@
plogd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
if (error != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
mDatagramController.updateReceiveStatus(request.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(), error);
mDatagramController.updateReceiveStatus(request.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -518,7 +522,7 @@
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
+ final int validSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteDatagramListenerHandler satelliteDatagramListenerHandler =
mSatelliteDatagramListenerHandlers.get(validSubId);
if (satelliteDatagramListenerHandler == null) {
@@ -544,7 +548,7 @@
*/
public void unregisterForSatelliteDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
+ final int validSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteDatagramListenerHandler handler =
mSatelliteDatagramListenerHandlers.get(validSubId);
if (handler != null) {
@@ -576,7 +580,8 @@
callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
return;
}
- pollPendingSatelliteDatagramsInternal(subId, callback);
+ pollPendingSatelliteDatagramsInternal(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callback);
}
private void handleSatelliteConnectedEvent() {
@@ -615,6 +620,7 @@
mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
callback, SatelliteServiceUtils.getPhone(), subId);
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -624,6 +630,7 @@
}
mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -695,13 +702,17 @@
}
stopDatagramWaitForConnectedStateTimer();
}
+
+ int subId = SatelliteController.getInstance().getSelectedSatelliteSubId();
if (mDatagramController.isReceivingDatagrams()) {
- mDatagramController.updateReceiveStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
}
- mDatagramController.updateReceiveStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mDatagramController.updateReceiveStatus(subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
SatelliteManager.SATELLITE_RESULT_SUCCESS);
cleanupDemoModeResources();
@@ -746,6 +757,7 @@
.setDatagramSizeBytes(datagramSizeRoundedBytes)
.setDatagramTransferTimeMillis(datagramTransferTime)
.setIsDemoMode(mIsDemoMode)
+ .setCarrierId(SatelliteController.getInstance().getSatelliteCarrierId())
.build());
mControllerMetricsStats.reportIncomingDatagramCount(resultCode, mIsDemoMode);
@@ -854,11 +866,13 @@
plogw("Timed out to wait for satellite connected before polling datagrams");
mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
+ SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
mDatagramController.getReceivePendingCount(),
SatelliteManager.SATELLITE_RESULT_SUCCESS);
diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
index 3c31ae8..7b64c61 100644
--- a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
+++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
@@ -131,7 +131,7 @@
NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
ntnSignalStrength.signalStrengthLevel = 0;
mISatelliteListener.onSatelliteModemStateChanged(
- SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ SatelliteModemState.SATELLITE_MODEM_STATE_OUT_OF_SERVICE);
mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
synchronized (mLock) {
@@ -191,7 +191,7 @@
NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
ntnSignalStrength.signalStrengthLevel = 2;
mISatelliteListener.onSatelliteModemStateChanged(
- SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ SatelliteModemState.SATELLITE_MODEM_STATE_IN_SERVICE);
mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
synchronized (mLock) {
diff --git a/src/java/com/android/internal/telephony/satellite/PointingAppController.java b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
index 06281c7..9606150 100644
--- a/src/java/com/android/internal/telephony/satellite/PointingAppController.java
+++ b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
@@ -34,9 +34,11 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.PersistentLogger;
import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.PointingInfo;
import android.telephony.satellite.SatelliteManager;
@@ -189,6 +191,7 @@
public static final int EVENT_SEND_DATAGRAM_STATE_CHANGED = 2;
public static final int EVENT_RECEIVE_DATAGRAM_STATE_CHANGED = 3;
public static final int EVENT_DATAGRAM_TRANSFER_STATE_CHANGED = 4;
+ public static final int EVENT_SEND_DATAGRAM_REQUESTED = 5;
private final ConcurrentHashMap<IBinder, ISatelliteTransmissionUpdateCallback> mListeners;
@@ -277,6 +280,24 @@
break;
}
+ case EVENT_SEND_DATAGRAM_REQUESTED: {
+ logd("Received EVENT_SEND_DATAGRAM_REQUESTED");
+ int datagramType = (int) msg.obj;
+ List<IBinder> toBeRemoved = new ArrayList<>();
+ mListeners.values().forEach(listener -> {
+ try {
+ listener.onSendDatagramRequested(datagramType);
+ } catch (RemoteException e) {
+ logd("EVENT_SEND_DATAGRAM_REQUESTED RemoteException: " + e);
+ toBeRemoved.add(listener.asBinder());
+ }
+ });
+ toBeRemoved.forEach(listener -> {
+ mListeners.remove(listener);
+ });
+ break;
+ }
+
default:
loge("SatelliteTransmissionUpdateHandler unknown event: " + msg.what);
}
@@ -290,6 +311,7 @@
*/
public void registerForSatelliteTransmissionUpdates(int subId,
ISatelliteTransmissionUpdateCallback callback) {
+ subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
if (handler != null) {
@@ -318,6 +340,7 @@
*/
public void unregisterForSatelliteTransmissionUpdates(int subId, Consumer<Integer> result,
ISatelliteTransmissionUpdateCallback callback) {
+ subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
if (handler != null) {
@@ -404,7 +427,7 @@
mLastNeedFullScreenPointingUI = needFullScreenPointingUI;
mLastIsDemoMode = isDemoMode;
mLastIsEmergency = isEmergency;
- mContext.startActivity(launchIntent);
+ mContext.startActivityAsUser(launchIntent, UserHandle.CURRENT);
} catch (ActivityNotFoundException ex) {
ploge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
}
@@ -426,6 +449,7 @@
int sendPendingCount, int errorCode) {
DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest(
datagramType, datagramTransferState, sendPendingCount, errorCode);
+ subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
@@ -439,12 +463,32 @@
}
}
+ /**
+ * This API is used to notify PointingAppController that a send datagram has just been
+ * requested.
+ */
+ public void onSendDatagramRequested(
+ int subId, @SatelliteManager.DatagramType int datagramType) {
+ subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ SatelliteTransmissionUpdateHandler handler =
+ mSatelliteTransmissionUpdateHandlers.get(subId);
+ if (handler != null) {
+ Message msg = handler.obtainMessage(
+ SatelliteTransmissionUpdateHandler.EVENT_SEND_DATAGRAM_REQUESTED,
+ datagramType);
+ msg.sendToTarget();
+ } else {
+ ploge("SatelliteTransmissionUpdateHandler not found for subId: " + subId);
+ }
+ }
+
public void updateReceiveDatagramTransferState(int subId,
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int receivePendingCount, int errorCode) {
DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest(
SatelliteManager.DATAGRAM_TYPE_UNKNOWN, datagramTransferState, receivePendingCount,
errorCode);
+ subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
index 384dfa5..a5afe4a 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
@@ -104,4 +104,22 @@
})
@Retention(RetentionPolicy.SOURCE)
public @interface AccessControlType {}
+
+ //// Unknown reason.
+ public static final int TRIGGERING_EVENT_UNKNOWN = 0;
+ // Satellite Access Controller has been triggered by an external event.
+ public static final int TRIGGERING_EVENT_EXTERNAL_REQUEST = 1;
+ // Satellite Access Controller has been triggered by an MCC change event.
+ public static final int TRIGGERING_EVENT_MCC_CHANGED = 2;
+ //Satellite Access Controller has been triggered due to the location setting being enabled.
+ public static final int TRIGGERING_EVENT_LOCATION_SETTINGS_ENABLED = 3;
+
+ @IntDef(prefix = {"TRIGGERING_EVENT_"}, value = {
+ TRIGGERING_EVENT_UNKNOWN,
+ TRIGGERING_EVENT_EXTERNAL_REQUEST,
+ TRIGGERING_EVENT_MCC_CHANGED,
+ TRIGGERING_EVENT_LOCATION_SETTINGS_ENABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TriggeringEvent {}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 14e7b76..6876ad5 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -16,24 +16,44 @@
package com.android.internal.telephony.satellite;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
import static android.provider.Settings.ACTION_SATELLITE_SETTING;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.SubscriptionManager.isValidSubscriptionId;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
@@ -46,8 +66,10 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.StatusBarManager;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -56,6 +78,8 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.hardware.devicestate.DeviceState;
+import android.hardware.devicestate.DeviceStateManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.nfc.NfcAdapter;
@@ -71,6 +95,7 @@
import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Message;
+import android.os.OutcomeReceiver;
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
@@ -82,6 +107,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Telephony;
+import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.DropBoxManagerLoggerBackend;
@@ -89,6 +115,7 @@
import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.satellite.INtnSignalStrengthCallback;
@@ -102,6 +129,11 @@
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SatelliteSubscriberInfo;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
+import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -116,6 +148,7 @@
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyCountryDetector;
import com.android.internal.telephony.configupdate.ConfigParser;
import com.android.internal.telephony.configupdate.ConfigProviderAdaptor;
import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver;
@@ -125,6 +158,7 @@
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.FunctionalUtils;
@@ -138,6 +172,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -172,7 +207,8 @@
public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2;
/** This is used by CTS to override demo pointing not aligned duration. */
public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3;
-
+ /** This is used by CTS to override evaluate esos profiles prioritization duration. */
+ public static final int TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS = 4;
/** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
"oem_enabled_satellite_provision_status_key";
@@ -180,6 +216,10 @@
public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS =
TimeUnit.SECONDS.toMillis(30);
+ /** Sets report entitled metrics cool down to 23 hours to help enforcing privacy requirement.*/
+ private static final long WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS =
+ TimeUnit.HOURS.toMillis(23);
+
/** Message codes used in handleMessage() */
//TODO: Move the Commands and events related to position updates to PointingAppController
private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1;
@@ -203,7 +243,6 @@
private static final int EVENT_RADIO_STATE_CHANGED = 23;
private static final int CMD_IS_SATELLITE_PROVISIONED = 24;
private static final int EVENT_IS_SATELLITE_PROVISIONED_DONE = 25;
- private static final int EVENT_SATELLITE_PROVISION_STATE_CHANGED = 26;
private static final int EVENT_PENDING_DATAGRAMS = 27;
private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 28;
private static final int EVENT_SET_SATELLITE_PLMN_INFO_DONE = 29;
@@ -216,10 +255,23 @@
private static final int EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE = 36;
private static final int EVENT_SERVICE_STATE_CHANGED = 37;
private static final int EVENT_SATELLITE_CAPABILITIES_CHANGED = 38;
- private static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39;
+ protected static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39;
private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40;
private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41;
private static final int EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT = 42;
+ private static final int CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43;
+ private static final int CMD_UPDATE_PROVISION_SATELLITE_TOKEN = 44;
+ private static final int EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE = 45;
+ private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46;
+ private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 47;
+ private static final int EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT = 48;
+ protected static final int EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT = 49;
+ private static final int CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES = 50;
+ private static final int EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE = 51;
+ protected static final int
+ EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT = 52;
+ private static final int EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT = 53;
+ protected static final int EVENT_SATELLITE_REGISTRATION_FAILURE = 54;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -233,9 +285,16 @@
@NonNull private SessionMetricsStats mSessionMetricsStats;
@NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats;
@NonNull private final SubscriptionManagerService mSubscriptionManagerService;
+ @NonNull private final TelephonyCountryDetector mCountryDetector;
+ @NonNull private final TelecomManager mTelecomManager;
private final CommandsInterface mCi;
private ContentResolver mContentResolver;
private final DeviceStateMonitor mDSM;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected final Object mSatellitePhoneLock = new Object();
+ @GuardedBy("mSatellitePhoneLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected Phone mSatellitePhone = null;
private final Object mRadioStateLock = new Object();
@@ -256,19 +315,30 @@
private boolean mDisableWifiOnSatelliteEnabled = false;
private final Object mSatelliteEnabledRequestLock = new Object();
+ /* This variable is used to store the first enable request that framework has received in the
+ * current session.
+ */
@GuardedBy("mSatelliteEnabledRequestLock")
private RequestSatelliteEnabledArgument mSatelliteEnabledRequest = null;
+ /* This variable is used to store a disable request that framework has received.
+ */
+ @GuardedBy("mSatelliteEnabledRequestLock")
+ private RequestSatelliteEnabledArgument mSatelliteDisabledRequest = null;
+ /* This variable is used to store an enable request that updates the enable attributes of an
+ * existing satellite session.
+ */
+ @GuardedBy("mSatelliteEnabledRequestLock")
+ private RequestSatelliteEnabledArgument mSatelliteEnableAttributesUpdateRequest = null;
/** Flag to indicate that satellite is enabled successfully
* and waiting for all the radios to be disabled so that success can be sent to callback
*/
@GuardedBy("mSatelliteEnabledRequestLock")
private boolean mWaitingForRadioDisabled = false;
-
+ @GuardedBy("mSatelliteEnabledRequestLock")
private boolean mWaitingForDisableSatelliteModemResponse = false;
+ @GuardedBy("mSatelliteEnabledRequestLock")
private boolean mWaitingForSatelliteModemOff = false;
- private final AtomicBoolean mRegisteredForProvisionStateChangedWithSatelliteService =
- new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForPendingDatagramCountWithSatelliteService =
new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithSatelliteService =
@@ -282,6 +352,8 @@
new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged =
new AtomicBoolean(false);
+ private final AtomicBoolean mRegisteredForSatelliteRegistrationFailure =
+ new AtomicBoolean(false);
/**
* Map key: subId, value: callback to get error code of the provision request.
*/
@@ -310,6 +382,12 @@
*/
private final ConcurrentHashMap<IBinder, ISatelliteSupportedStateCallback>
mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>();
+
+ /**
+ * Map key: binder of the callback, value: callback to satellite registration failure
+ */
+ private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback>
+ mSatelliteRegistrationFailureListeners = new ConcurrentHashMap<>();
private final Object mIsSatelliteSupportedLock = new Object();
@GuardedBy("mIsSatelliteSupportedLock")
private Boolean mIsSatelliteSupported = null;
@@ -318,12 +396,18 @@
private final Object mIsSatelliteEnabledLock = new Object();
@GuardedBy("mIsSatelliteEnabledLock")
private Boolean mIsSatelliteEnabled = null;
- private final Object mIsRadioOnLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected final Object mIsRadioOnLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean mIsRadioOn;
@GuardedBy("mIsRadioOnLock")
- private boolean mIsRadioOn = false;
- private final Object mSatelliteViaOemProvisionLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean mRadioOffRequested = false;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected final Object mSatelliteViaOemProvisionLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@GuardedBy("mSatelliteViaOemProvisionLock")
- private Boolean mIsSatelliteViaOemProvisioned = null;
+ protected Boolean mIsSatelliteViaOemProvisioned = null;
@GuardedBy("mSatelliteViaOemProvisionLock")
private Boolean mOverriddenIsSatelliteViaOemProvisioned = null;
private final Object mSatelliteCapabilitiesLock = new Object();
@@ -349,6 +433,8 @@
mCarrierConfigChangeListener;
@NonNull private final ConfigProviderAdaptor.Callback mConfigDataUpdatedCallback;
@NonNull private final Object mCarrierConfigArrayLock = new Object();
+ @NonNull
+ private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener;
@GuardedBy("mCarrierConfigArrayLock")
@NonNull private final SparseArray<PersistableBundle> mCarrierConfigArray = new SparseArray<>();
@GuardedBy("mIsSatelliteEnabledLock")
@@ -380,6 +466,17 @@
@GuardedBy("mSatelliteConnectedLock")
@NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray();
+ /**
+ * Boolean set to {@code true} when device is eligible to connect to carrier roaming
+ * non-terrestrial network else set to {@code false}.
+ */
+ @GuardedBy("mSatellitePhoneLock")
+ private Boolean mLastNotifiedNtnEligibility = null;
+ @GuardedBy("mSatellitePhoneLock")
+ private boolean mNtnEligibilityHysteresisTimedOut = false;
+ @GuardedBy("mSatellitePhoneLock")
+ private boolean mCheckingAccessRestrictionInProgress = false;
+
@GuardedBy("mSatelliteConnectedLock")
@NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats>
mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>();
@@ -422,9 +519,29 @@
@GuardedBy("mSupportedSatelliteServicesLock")
private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>();
private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
+ // key : subscriberId, value : provisioned or not.
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ private Map<String, Boolean> mProvisionedSubscriberId = new HashMap<>();
+ // key : subscriberId, value : subId
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected Map<String, Integer> mSubscriberIdPerSub = new HashMap<>();
+ // key : priority, low value is high, value : List<SubscriptionInfo>
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>();
+ // The ID of the satellite subscription that has highest priority and is provisioned.
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ private int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ // The last ICC ID that framework configured to modem.
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ private String mLastConfiguredIccId;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ @NonNull protected final Object mSatelliteTokenProvisionedLock = new Object();
private long mWaitTimeForSatelliteEnablingResponse;
private long mDemoPointingAlignedDurationMillis;
private long mDemoPointingNotAlignedDurationMillis;
+ private long mEvaluateEsosProfilesPrioritizationDurationMillis;
private final Object mLock = new Object();
@GuardedBy("mLock")
private long mLastEmergencyCallTime;
@@ -450,6 +567,40 @@
// Variable for backup and restore device's screen rotation settings.
private String mDeviceRotationLockToBackupAndRestore = null;
+ // This is used for testing only. Context#getSystemService is a final API and cannot be
+ // mocked. Using this to inject a mock SubscriptionManager to work around this limitation.
+ private SubscriptionManager mInjectSubscriptionManager = null;
+
+ private final Object mIsWifiConnectedLock = new Object();
+ @GuardedBy("mIsWifiConnectedLock")
+ private boolean mIsWifiConnected = false;
+ private boolean mHasSentBroadcast = false;
+ // For satellite CTS test which to configure intent component with the necessary values.
+ private boolean mChangeIntentComponent = false;
+ private String mConfigSatelliteGatewayServicePackage = "";
+ private String mConfigSatelliteCarrierRoamingEsosProvisionedClass = "";
+
+ private boolean mIsNotificationShowing = false;
+ private static final String OPEN_MESSAGE_BUTTON = "open_message_button";
+ private static final String HOW_IT_WORKS_BUTTON = "how_it_works_button";
+ private static final String ACTION_NOTIFICATION_CLICK = "action_notification_click";
+ private static final String ACTION_NOTIFICATION_DISMISS = "action_notification_dismiss";
+ private AtomicBoolean mOverrideNtnEligibility;
+ private BroadcastReceiver
+ mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(
+ SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED)) {
+ plogd("Default SMS subscription changed");
+ sendRequestAsync(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION, null, null);
+ }
+ }
+ };
+
+ // List of device states returned from DeviceStateManager to determine if running on a foldable
+ // device.
+ private List<DeviceState> mDeviceStates = new ArrayList();
/**
* @return The singleton instance of SatelliteController.
@@ -495,12 +646,19 @@
mContext = context;
mFeatureFlags = featureFlags;
Phone phone = SatelliteServiceUtils.getPhone();
+ synchronized (mSatellitePhoneLock) {
+ mSatellitePhone = phone;
+ }
mCi = phone.mCi;
mDSM = phone.getDeviceStateMonitor();
// Create the SatelliteModemInterface singleton, which is used to manage connections
// to the satellite service and HAL interface.
mSatelliteModemInterface = SatelliteModemInterface.make(
mContext, this, mFeatureFlags);
+ mCountryDetector = TelephonyCountryDetector.getInstance(context, mFeatureFlags);
+ mCountryDetector.registerForWifiConnectivityStateChanged(this,
+ EVENT_WIFI_CONNECTIVITY_STATE_CHANGED, null);
+ mTelecomManager = mContext.getSystemService(TelecomManager.class);
// Create the PointingUIController singleton,
// which is used to manage interactions with PointingUI app.
@@ -525,7 +683,6 @@
mIsRadioOn = phone.isRadioOn();
}
- registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForServiceStateChanged();
@@ -553,8 +710,10 @@
mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) ->
handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
- mCarrierConfigManager.registerCarrierConfigChangeListener(
- new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
+ if (mCarrierConfigManager != null) {
+ mCarrierConfigManager.registerCarrierConfigChangeListener(
+ new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
+ }
mConfigDataUpdatedCallback = new ConfigProviderAdaptor.Callback() {
@Override
@@ -577,6 +736,35 @@
getDemoPointingNotAlignedDurationMillisFromResources();
mSatelliteEmergencyModeDurationMillis =
getSatelliteEmergencyModeDurationFromOverlayConfig(context);
+ mEvaluateEsosProfilesPrioritizationDurationMillis =
+ getEvaluateEsosProfilesPrioritizationDurationMillis();
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
+
+ SubscriptionManager subscriptionManager = mContext.getSystemService(
+ SubscriptionManager.class);
+ mSubscriptionsChangedListener = new SatelliteSubscriptionsChangedListener();
+ if (subscriptionManager != null) {
+ subscriptionManager.addOnSubscriptionsChangedListener(
+ new HandlerExecutor(new Handler(looper)), mSubscriptionsChangedListener);
+ }
+ registerDefaultSmsSubscriptionChangedBroadcastReceiver();
+ updateSatelliteProvisionedStatePerSubscriberId();
+ if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) {
+ mDeviceStates = getSupportedDeviceStates();
+ }
+ }
+
+ class SatelliteSubscriptionsChangedListener
+ extends SubscriptionManager.OnSubscriptionsChangedListener {
+
+ /**
+ * Callback invoked when there is any change to any SubscriptionInfo.
+ */
+ @Override
+ public void onSubscriptionsChanged() {
+ handleSubscriptionsChanged();
+ }
}
/**
@@ -939,11 +1127,12 @@
break;
}
mSatelliteProvisionCallbacks.put(argument.subId, argument.callback);
- onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_SERVICE_DONE, request);
// Log the current time for provision triggered
mProvisionMetricsStats.setProvisioningStartTime();
- mSatelliteModemInterface.provisionSatelliteService(argument.token,
- argument.provisionData, onCompleted);
+ Message provisionSatelliteServiceDoneEvent = this.obtainMessage(
+ EVENT_PROVISION_SATELLITE_SERVICE_DONE,
+ new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null));
+ provisionSatelliteServiceDoneEvent.sendToTarget();
break;
}
@@ -962,11 +1151,13 @@
request = (SatelliteControllerHandlerRequest) msg.obj;
ProvisionSatelliteServiceArgument argument =
(ProvisionSatelliteServiceArgument) request.argument;
- onCompleted = obtainMessage(EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, request);
if (argument.callback != null) {
mProvisionMetricsStats.setProvisioningStartTime();
}
- mSatelliteModemInterface.deprovisionSatelliteService(argument.token, onCompleted);
+ Message deprovisionSatelliteServiceDoneEvent = this.obtainMessage(
+ EVENT_DEPROVISION_SATELLITE_SERVICE_DONE,
+ new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null));
+ deprovisionSatelliteServiceDoneEvent.sendToTarget();
break;
}
@@ -1003,64 +1194,50 @@
+ argument.enableSatellite + " was already processed");
return;
}
- stopWaitForSatelliteEnablingResponseTimer(argument);
+ if (shouldStopWaitForEnableResponseTimer(argument)) {
+ stopWaitForSatelliteEnablingResponseTimer(argument);
+ } else {
+ plogd("Still waiting for the OFF state from modem");
+ }
if (error == SATELLITE_RESULT_SUCCESS) {
if (argument.enableSatellite) {
synchronized (mSatelliteEnabledRequestLock) {
mWaitingForRadioDisabled = true;
+ setDemoModeEnabled(argument.enableDemoMode);
}
+ // TODO (b/361139260): Start a timer to wait for other radios off
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE);
setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_TRUE);
evaluateToSendSatelliteEnabledSuccess();
} else {
- /**
- * Unregister Importance Listener for Pointing UI
- * when Satellite is disabled
- */
+ // Unregister importance listener for PointingUI when satellite is disabled
if (mNeedsSatellitePointing) {
mPointingAppController.removeListenerForPointingUI();
}
synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteEnabledRequest != null &&
- mSatelliteEnabledRequest.enableSatellite == true &&
- argument.enableSatellite == false && mWaitingForRadioDisabled) {
- // Previous mSatelliteEnabledRequest is successful but waiting for
- // all radios to be turned off.
- mSatelliteEnabledRequest.callback.accept(
- SATELLITE_RESULT_SUCCESS);
- }
- }
-
- synchronized (mIsSatelliteEnabledLock) {
if (!mWaitingForSatelliteModemOff) {
moveSatelliteToOffStateAndCleanUpResources(
- SATELLITE_RESULT_SUCCESS,
- argument.callback);
- } else {
- plogd("Wait for satellite modem off before updating satellite"
- + " modem state");
+ SATELLITE_RESULT_SUCCESS);
}
mWaitingForDisableSatelliteModemResponse = false;
}
}
- // Request Ntn signal strength report when satellite enabled or disabled done.
+ // Request NTN signal strength report when satellite enabled or disabled done.
mLatestRequestedStateForNtnSignalStrengthReport.set(argument.enableSatellite);
updateNtnSignalStrengthReporting(argument.enableSatellite);
} else {
- synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteEnabledRequest != null &&
- mSatelliteEnabledRequest.enableSatellite == true &&
- argument.enableSatellite == false && mWaitingForRadioDisabled) {
- // Previous mSatelliteEnabledRequest is successful but waiting for
- // all radios to be turned off.
- mSatelliteEnabledRequest.callback.accept(
- SATELLITE_RESULT_SUCCESS);
- }
+ if (argument.enableSatellite) {
+ /* Framework need to abort the enable attributes update request if any since
+ * modem failed to enable satellite.
+ */
+ abortSatelliteEnableAttributesUpdateRequest(
+ SATELLITE_RESULT_REQUEST_ABORTED);
+ resetSatelliteEnabledRequest();
+ } else {
+ resetSatelliteDisabledRequest();
}
- notifyEnablementFailedToSatelliteSessionController();
- resetSatelliteEnabledRequest();
-
+ notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite);
// If Satellite enable/disable request returned Error, no need to wait for radio
argument.callback.accept(error);
}
@@ -1070,7 +1247,8 @@
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setInitializationProcessingTime(
System.currentTimeMillis() - mSessionProcessingTimeStamp)
- .setIsDemoMode(mIsDemoModeEnabled);
+ .setIsDemoMode(mIsDemoModeEnabled)
+ .setCarrierId(getSatelliteCarrierId());
mSessionProcessingTimeStamp = 0;
if (error == SATELLITE_RESULT_SUCCESS) {
@@ -1089,22 +1267,110 @@
.reportSessionMetrics();
mSessionStartTimeStamp = 0;
mSessionProcessingTimeStamp = 0;
-
mControllerMetricsStats.onSatelliteDisabled();
-
handlePersistentLoggingOnSessionEnd(mIsEmergency);
-
- synchronized (mIsSatelliteEnabledLock) {
+ synchronized (mSatelliteEnabledRequestLock) {
mWaitingForDisableSatelliteModemResponse = false;
}
}
break;
}
- case EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT:
+ case EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT: {
handleEventWaitForSatelliteEnablingResponseTimedOut(
(RequestSatelliteEnabledArgument) msg.obj);
break;
+ }
+
+ case CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES: {
+ request = (SatelliteControllerHandlerRequest) msg.obj;
+ RequestSatelliteEnabledArgument argument =
+ (RequestSatelliteEnabledArgument) request.argument;
+
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("UpdateEnableAttributes: carrierRoamingNbIotNtn flag is disabled");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, argument.callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ break;
+ }
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (mSatelliteEnabledRequest != null) {
+ plogd("UpdateEnableAttributes: Satellite is being enabled. Need to "
+ + "wait until enable complete before updating attributes");
+ break;
+ }
+ if (isSatelliteBeingDisabled()) {
+ plogd("UpdateEnableAttributes: Satellite is being disabled. Aborting the "
+ + "enable attributes update request");
+ mSatelliteEnableAttributesUpdateRequest = null;
+ argument.callback.accept(SATELLITE_RESULT_REQUEST_ABORTED);
+ break;
+ }
+ }
+ onCompleted = obtainMessage(EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE, request);
+ SatelliteModemEnableRequestAttributes enableRequestAttributes =
+ createModemEnableRequest(argument);
+ if (enableRequestAttributes == null) {
+ plogw("UpdateEnableAttributes: enableRequestAttributes is null");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ argument.callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ break;
+ }
+ mSatelliteModemInterface.requestSatelliteEnabled(
+ enableRequestAttributes, onCompleted);
+ startWaitForUpdateSatelliteEnableAttributesResponseTimer(argument);
+ break;
+ }
+
+ case EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (SatelliteControllerHandlerRequest) ar.userObj;
+ RequestSatelliteEnabledArgument argument =
+ (RequestSatelliteEnabledArgument) request.argument;
+ int error = SatelliteServiceUtils.getSatelliteError(
+ ar, "updateSatelliteEnableAttributes");
+ plogd("EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE = " + error);
+
+ /*
+ * The timer to wait for EVENT_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_DONE might have
+ * expired and thus the request resources might have been cleaned up.
+ */
+ if (!shouldProcessEventUpdateSatelliteEnableAttributesDone(argument)) {
+ plogw("The update request ID=" + argument.requestId + " was already processed");
+ return;
+ }
+ stopWaitForUpdateSatelliteEnableAttributesResponseTimer(argument);
+
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ setDemoModeEnabled(argument.enableDemoMode);
+ setEmergencyMode(argument.isEmergency);
+ }
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ argument.callback.accept(error);
+ break;
+ }
+
+ case EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT: {
+ RequestSatelliteEnabledArgument argument =
+ (RequestSatelliteEnabledArgument) msg.obj;
+ plogw("Timed out to wait for the response from the modem for the request to "
+ + "update satellite enable attributes, request ID = " + argument.requestId);
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT);
+ break;
+ }
case CMD_IS_SATELLITE_ENABLED: {
request = (SatelliteControllerHandlerRequest) msg.obj;
@@ -1130,7 +1396,7 @@
updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE");
}
} else if (error == SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
- updateSatelliteSupportedStateWhenSatelliteServiceConnected(false);
+ updateSatelliteSupportedState(false);
}
((ResultReceiver) request.argument).send(error, bundle);
break;
@@ -1156,7 +1422,7 @@
boolean supported = (boolean) ar.result;
plogd("isSatelliteSupported: " + supported);
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
- updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
+ updateSatelliteSupportedState(supported);
}
}
((ResultReceiver) request.argument).send(error, bundle);
@@ -1185,11 +1451,12 @@
synchronized (mNeedsSatellitePointingLock) {
mNeedsSatellitePointing = capabilities.isPointingRequired();
}
- if (DBG) plogd("getSatelliteCapabilities: " + capabilities);
- bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
- capabilities);
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
+ overrideSatelliteCapabilitiesIfApplicable();
+ if (DBG) plogd("getSatelliteCapabilities: " + mSatelliteCapabilities);
+ bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
+ mSatelliteCapabilities);
}
}
}
@@ -1236,6 +1503,14 @@
mIsRadioOn = true;
} else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
resetCarrierRoamingSatelliteModeParams();
+ synchronized (mIsRadioOnLock) {
+ if (mRadioOffRequested) {
+ logd("EVENT_RADIO_STATE_CHANGED: set mIsRadioOn to false");
+ stopWaitForCellularModemOffTimer();
+ mIsRadioOn = false;
+ mRadioOffRequested = false;
+ }
+ }
}
}
@@ -1262,8 +1537,10 @@
case CMD_IS_SATELLITE_PROVISIONED: {
request = (SatelliteControllerHandlerRequest) msg.obj;
- onCompleted = obtainMessage(EVENT_IS_SATELLITE_PROVISIONED_DONE, request);
- mSatelliteModemInterface.requestIsSatelliteProvisioned(onCompleted);
+ Message isProvisionedDoneEvent = this.obtainMessage(
+ EVENT_IS_SATELLITE_PROVISIONED_DONE,
+ new AsyncResult(request, SATELLITE_RESULT_SUCCESS, null));
+ isProvisionedDoneEvent.sendToTarget();
break;
}
@@ -1272,15 +1549,6 @@
break;
}
- case EVENT_SATELLITE_PROVISION_STATE_CHANGED:
- ar = (AsyncResult) msg.obj;
- if (ar.result == null) {
- ploge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null");
- } else {
- handleEventSatelliteProvisionStateChanged((boolean) ar.result);
- }
- break;
-
case EVENT_PENDING_DATAGRAMS:
plogd("Received EVENT_PENDING_DATAGRAMS");
IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
@@ -1289,8 +1557,7 @@
plogd("pollPendingSatelliteDatagram result: " + result);
}
};
- pollPendingDatagrams(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, internalCallback);
+ pollPendingDatagrams(internalCallback);
break;
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
@@ -1462,6 +1729,125 @@
break;
}
+ case EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT: {
+ synchronized (mSatellitePhoneLock) {
+ mNtnEligibilityHysteresisTimedOut = true;
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
+ + " isCarrierRoamingNtnEligible=" + eligible);
+ if (eligible) {
+ requestIsSatelliteAllowedForCurrentLocation();
+ }
+ }
+ break;
+ }
+
+ case CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION: {
+ evaluateESOSProfilesPrioritization();
+ break;
+ }
+
+ case CMD_UPDATE_PROVISION_SATELLITE_TOKEN: {
+ request = (SatelliteControllerHandlerRequest) msg.obj;
+ RequestProvisionSatelliteArgument argument =
+ (RequestProvisionSatelliteArgument) request.argument;
+ onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request);
+ boolean provisionChanged = updateSatelliteSubscriptionProvisionState(
+ argument.mSatelliteSubscriberInfoList, argument.mProvisioned);
+ selectBindingSatelliteSubscription();
+ int subId = getSelectedSatelliteSubId();
+ SubscriptionInfo subscriptionInfo =
+ mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (subscriptionInfo == null) {
+ logw("updateSatelliteToken subId=" + subId + " is not found");
+ } else {
+ String iccId = subscriptionInfo.getIccId();
+ argument.setIccId(iccId);
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (!iccId.equals(mLastConfiguredIccId)) {
+ logd("updateSatelliteSubscription subId=" + subId
+ + ", iccId=" + iccId + " to modem");
+ mSatelliteModemInterface.updateSatelliteSubscription(
+ iccId, onCompleted);
+ }
+ }
+ }
+ if (provisionChanged) {
+ handleEventSatelliteSubscriptionProvisionStateChanged();
+ }
+
+ // The response is sent immediately because the ICCID has already been
+ // delivered to the modem.
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(
+ argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS
+ : SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS, true);
+ argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ break;
+ }
+
+ case EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (SatelliteControllerHandlerRequest) ar.userObj;
+ RequestProvisionSatelliteArgument argument =
+ (RequestProvisionSatelliteArgument) request.argument;
+ int error = SatelliteServiceUtils.getSatelliteError(ar,
+ "updateSatelliteSubscription");
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ mLastConfiguredIccId = argument.getIccId();
+ }
+ }
+ logd("updateSatelliteSubscription result=" + error);
+ break;
+ }
+
+ case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: {
+ synchronized (mIsWifiConnectedLock) {
+ ar = (AsyncResult) msg.obj;
+ mIsWifiConnected = (boolean) ar.result;
+ plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected="
+ + mIsWifiConnected);
+ handleStateChangedForCarrierRoamingNtnEligibility();
+ }
+ break;
+ }
+ case EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT: {
+ handleSatelliteAccessRestrictionCheckingResult((boolean) msg.obj);
+ break;
+ }
+
+ case EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT: {
+ plogw("Timed out to wait for cellular modem OFF state");
+ synchronized (mIsRadioOnLock) {
+ mRadioOffRequested = false;
+ }
+ break;
+ }
+
+ case EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT: {
+ // TODO: b/366329504 report carrier roaming metrics for multiple subscription IDs.
+ synchronized (mSupportedSatelliteServicesLock) {
+ int defaultSubId = mSubscriptionManagerService.getDefaultSubId();
+ boolean isEntitled = mSatelliteEntitlementStatusPerCarrier.get(defaultSubId,
+ false);
+ mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(isEntitled);
+ }
+ sendMessageDelayed(obtainMessage(
+ EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT),
+ WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS);
+ break;
+ }
+
+ case EVENT_SATELLITE_REGISTRATION_FAILURE:
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ loge("EVENT_SATELLITE_REGISTRATION_FAILURE: result is null");
+ } else {
+ handleEventSatelliteRegistrationFailure((int) ar.result);
+ }
+ break;
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1469,6 +1855,32 @@
}
}
+ private static final class RequestProvisionSatelliteArgument {
+ public List<SatelliteSubscriberInfo> mSatelliteSubscriberInfoList;
+ @NonNull
+ public ResultReceiver mResult;
+ public long mRequestId;
+ public String mIccId;
+ public boolean mProvisioned;
+
+ RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList,
+ ResultReceiver result, boolean provisioned) {
+ this.mSatelliteSubscriberInfoList = satelliteSubscriberInfoList;
+ this.mResult = result;
+ this.mProvisioned = provisioned;
+ this.mRequestId = sNextSatelliteEnableRequestId.getAndUpdate(
+ n -> ((n + 1) % Long.MAX_VALUE));
+ }
+
+ public void setIccId(String iccId) {
+ mIccId = iccId;
+ }
+
+ public String getIccId() {
+ return mIccId;
+ }
+ }
+
private void handleEventConfigDataUpdated() {
updateSupportedSatelliteServicesForActiveSubscriptions();
int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
@@ -1493,16 +1905,15 @@
* enabled, this will also disable the cellular modem, and if the satellite modem is disabled,
* this will also re-enable the cellular modem.
*
- * @param subId The subId of the subscription to set satellite enabled for.
* @param enableSatellite {@code true} to enable the satellite modem and
* {@code false} to disable.
* @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable.
* @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise.
* @param callback The callback to get the error code of the request.
*/
- public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode,
+ public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
boolean isEmergency, @NonNull IIntegerConsumer callback) {
- plogd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite
+ plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite
+ " enableDemoMode: " + enableDemoMode + " isEmergency: " + isEmergency);
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
@@ -1519,32 +1930,25 @@
SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
return;
}
+ if (mRadioOffRequested) {
+ ploge("Radio is being powering off, can not enable satellite");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
+ return;
+ }
+ }
+
+ if (mTelecomManager.isInEmergencyCall()) {
+ plogd("requestSatelliteEnabled: reject as emergency call is ongoing.");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS, result);
+ return;
}
} else {
/* if disable satellite, always assume demo is also disabled */
enableDemoMode = false;
}
- synchronized (mIsSatelliteEnabledLock) {
- if (mIsSatelliteEnabled != null) {
- if (mIsSatelliteEnabled == enableSatellite) {
- if (enableDemoMode != mIsDemoModeEnabled) {
- ploge("Received invalid demo mode while satellite session is enabled"
- + " enableDemoMode = " + enableDemoMode);
- sendErrorAndReportSessionMetrics(
- SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, result);
- return;
- } else {
- plogd("Enable request matches with current state"
- + " enableSatellite = " + enableSatellite);
- sendErrorAndReportSessionMetrics(
- SatelliteManager.SATELLITE_RESULT_SUCCESS, result);
- return;
- }
- }
- }
- }
-
RequestSatelliteEnabledArgument request =
new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, isEmergency,
result);
@@ -1559,35 +1963,147 @@
* 4. ongoing request = enable, current request = disable: send request to modem
*/
synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteEnabledRequest == null) {
- mSatelliteEnabledRequest = request;
- } else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) {
- plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite
- + " is already in progress.");
- sendErrorAndReportSessionMetrics(
- SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result);
+ if (!isSatelliteEnabledRequestInProgress()) {
+ synchronized (mIsSatelliteEnabledLock) {
+ if (mIsSatelliteEnabled != null && mIsSatelliteEnabled == enableSatellite) {
+ evaluateToUpdateSatelliteEnabledAttributes(result,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS, request,
+ mIsDemoModeEnabled, mIsEmergency);
+ return;
+ }
+ }
+ if (enableSatellite) {
+ mSatelliteEnabledRequest = request;
+ } else {
+ mSatelliteDisabledRequest = request;
+ }
+ } else if (isSatelliteBeingDisabled()) {
+ int resultCode = SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS;
+ if (enableSatellite) {
+ plogw("requestSatelliteEnabled: The enable request cannot be "
+ + "processed since disable satellite is in progress.");
+ resultCode = SatelliteManager.SATELLITE_RESULT_DISABLE_IN_PROGRESS;
+ } else {
+ plogd("requestSatelliteEnabled: Disable is already in progress.");
+ }
+ sendErrorAndReportSessionMetrics(resultCode, result);
return;
- } else if (mSatelliteEnabledRequest.enableSatellite == false
- && request.enableSatellite == true) {
- plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
- + "processed. Disable satellite is already in progress.");
- sendErrorAndReportSessionMetrics(
- SatelliteManager.SATELLITE_RESULT_ERROR, result);
+ } else {
+ // Satellite is being enabled or satellite enable attributes are being updated
+ if (enableSatellite) {
+ if (mSatelliteEnableAttributesUpdateRequest == null) {
+ /* Satellite is being enabled and framework receive a new enable request to
+ * update the enable attributes.
+ */
+ evaluateToUpdateSatelliteEnabledAttributes(result,
+ SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS,
+ request, mSatelliteEnabledRequest.enableDemoMode,
+ mSatelliteEnabledRequest.isEmergency);
+ } else {
+ /* The enable attributes update request is already being processed.
+ * Framework can't handle one more request to update enable attributes.
+ */
+ plogd("requestSatelliteEnabled: enable attributes update request is already"
+ + " in progress.");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result);
+ }
+ return;
+ } else {
+ /* Users might want to end the satellite session while it is being enabled, or
+ * the satellite session need to be disabled for an emergency call. Note: some
+ * carriers want to disable satellite for prioritizing emergency calls. Thus,
+ * we need to push the disable request to modem while enable is in progress.
+ */
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("requestSatelliteEnabled: carrierRoamingNbIotNtn flag is disabled");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ENABLE_IN_PROGRESS, result);
+ return;
+ }
+ mSatelliteDisabledRequest = request;
+ }
+ }
+ }
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ }
+
+ /**
+ * Validate the newly-received enable attributes against the current ones. If the new attributes
+ * are valid and different from the current ones, framework will send a request to update the
+ * enable attributes to modem. Otherwise, framework will return
+ * {@code SATELLITE_RESULT_INVALID_ARGUMENTS} to the requesting clients.
+ *
+ * @param result The callback that returns the result to the requesting client.
+ * @param resultCode The result code to send back to the requesting client when framework does
+ * not need to reconfigure modem.
+ * @param enableRequest The new enable request to update satellite enable attributes.
+ * @param currentDemoMode The current demo mode at framework.
+ * @param currentEmergencyMode The current emergency mode at framework.
+ */
+ private void evaluateToUpdateSatelliteEnabledAttributes(@NonNull Consumer<Integer> result,
+ @SatelliteManager.SatelliteResult int resultCode,
+ @NonNull RequestSatelliteEnabledArgument enableRequest, boolean currentDemoMode,
+ boolean currentEmergencyMode) {
+ boolean needToReconfigureModem = false;
+ if (enableRequest.enableDemoMode != currentDemoMode) {
+ if (enableRequest.enableDemoMode) {
+ ploge("Moving from real mode to demo mode is rejected");
+ sendErrorAndReportSessionMetrics(SATELLITE_RESULT_INVALID_ARGUMENTS, result);
return;
+ } else {
+ plogd("Moving from demo mode to real mode. Need to reconfigure"
+ + " modem with real mode");
+ needToReconfigureModem = true;
+ }
+ } else if (enableRequest.isEmergency != currentEmergencyMode) {
+ if (enableRequest.isEmergency) {
+ plogd("Moving from non-emergency to emergency mode. Need to "
+ + "reconfigure modem");
+ needToReconfigureModem = true;
+ } else {
+ plogd("Non-emergency requests can be served during an emergency"
+ + " satellite session. No need to reconfigure modem.");
}
}
- sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ if (needToReconfigureModem) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnableAttributesUpdateRequest = enableRequest;
+ }
+ sendRequestAsync(
+ CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES, enableRequest, null);
+ } else {
+ if (resultCode != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ plogd("requestSatelliteEnabled enable satellite is already in progress.");
+ }
+ sendErrorAndReportSessionMetrics(resultCode, result);
+ }
+ return;
+ }
+
+ /**
+ * @return {@code true} when either enable request, disable request, or enable attributes update
+ * request is in progress, {@code false} otherwise.
+ */
+ private boolean isSatelliteEnabledRequestInProgress() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ plogd("mSatelliteEnabledRequest: " + (mSatelliteEnabledRequest != null)
+ + ", mSatelliteDisabledRequest: " + (mSatelliteDisabledRequest != null)
+ + ", mSatelliteEnableAttributesUpdateRequest: "
+ + (mSatelliteEnableAttributesUpdateRequest != null));
+ return (mSatelliteEnabledRequest != null || mSatelliteDisabledRequest != null
+ || mSatelliteEnableAttributesUpdateRequest != null);
+ }
}
/**
* Request to get whether the satellite modem is enabled.
*
- * @param subId The subId of the subscription to check whether satellite is enabled for.
* @param result The result receiver that returns whether the satellite modem is enabled
* if the request is successful or an error code if the request failed.
*/
- public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) {
+ public void requestIsSatelliteEnabled(@NonNull ResultReceiver result) {
int error = evaluateOemSatelliteRequestAllowed(false);
if (error != SATELLITE_RESULT_SUCCESS) {
result.send(error, null);
@@ -1613,13 +2129,15 @@
*
* @return {@code true} if the satellite modem is enabled and {@code false} otherwise.
*/
- public boolean isSatelliteEnabled() {
+ private boolean isSatelliteEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
- if (mIsSatelliteEnabled == null) return false;
- return mIsSatelliteEnabled;
+ synchronized (mIsSatelliteEnabledLock) {
+ if (mIsSatelliteEnabled == null) return false;
+ return mIsSatelliteEnabled;
+ }
}
/**
@@ -1627,7 +2145,7 @@
*
* @return {@code true} if the satellite modem is being enabled and {@code false} otherwise.
*/
- public boolean isSatelliteBeingEnabled() {
+ private boolean isSatelliteBeingEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
return false;
@@ -1640,14 +2158,35 @@
}
/**
+ * Get whether the satellite modem is enabled or being enabled.
+ * This will return the cached value instead of querying the satellite modem.
+ *
+ * @return {@code true} if the satellite modem is enabled or being enabled, {@code false}
+ * otherwise.
+ */
+ public boolean isSatelliteEnabledOrBeingEnabled() {
+ return isSatelliteEnabled() || isSatelliteBeingEnabled();
+ }
+
+ /**
+ * Get whether satellite modem is being disabled.
+ *
+ * @return {@code true} if the satellite modem is being disabled and {@code false} otherwise.
+ */
+ public boolean isSatelliteBeingDisabled() {
+ if (mSatelliteSessionController != null) {
+ return mSatelliteSessionController.isInDisablingState();
+ }
+ return false;
+ }
+
+ /**
* Request to get whether the satellite service demo mode is enabled.
*
- * @param subId The subId of the subscription to check whether the satellite demo mode
- * is enabled for.
* @param result The result receiver that returns whether the satellite demo mode is enabled
* if the request is successful or an error code if the request failed.
*/
- public void requestIsDemoModeEnabled(int subId, @NonNull ResultReceiver result) {
+ public void requestIsDemoModeEnabled(@NonNull ResultReceiver result) {
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
result.send(error, null);
@@ -1673,13 +2212,33 @@
}
/**
+ * Request to get whether the satellite enabled request is for emergency or not.
+ *
+ * @param result The result receiver that returns whether the request is for emergency
+ * if the request is successful or an error code if the request failed.
+ */
+ public void requestIsEmergencyModeEnabled(@NonNull ResultReceiver result) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("requestIsEmergencyModeEnabled: oemEnabledSatelliteFlag is disabled");
+ result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
+ return;
+ }
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_EMERGENCY_MODE_ENABLED,
+ getRequestIsEmergency());
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+ }
+
+ /**
* Request to get whether the satellite service is supported on the device.
*
- * @param subId The subId of the subscription to check satellite service support for.
* @param result The result receiver that returns whether the satellite service is supported on
* the device if the request is successful or an error code if the request failed.
*/
- public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
+ public void requestIsSatelliteSupported(@NonNull ResultReceiver result) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
@@ -1690,7 +2249,7 @@
/* We have already successfully queried the satellite modem. */
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
- bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId);
+ bundle.putInt(SATELLITE_SUBSCRIPTION_ID, getSelectedSatelliteSubId());
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
@@ -1702,11 +2261,10 @@
/**
* Request to get the {@link SatelliteCapabilities} of the satellite service.
*
- * @param subId The subId of the subscription to get the satellite capabilities for.
* @param result The result receiver that returns the {@link SatelliteCapabilities}
* if the request is successful or an error code if the request failed.
*/
- public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) {
+ public void requestSatelliteCapabilities(@NonNull ResultReceiver result) {
int error = evaluateOemSatelliteRequestAllowed(false);
if (error != SATELLITE_RESULT_SUCCESS) {
result.send(error, null);
@@ -1731,11 +2289,10 @@
* This can be called by the pointing UI when the user starts pointing to the satellite.
* Modem should continue to report the pointing input as the device or satellite moves.
*
- * @param subId The subId of the subscription to start satellite transmission updates for.
* @param errorCallback The callback to get the error code of the request.
* @param callback The callback to notify of satellite transmission updates.
*/
- public void startSatelliteTransmissionUpdates(int subId,
+ public void startSatelliteTransmissionUpdates(
@NonNull IIntegerConsumer errorCallback,
@NonNull ISatelliteTransmissionUpdateCallback callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
@@ -1745,7 +2302,7 @@
return;
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
+ final int validSubId = getSelectedSatelliteSubId();
mPointingAppController.registerForSatelliteTransmissionUpdates(validSubId, callback);
sendRequestAsync(CMD_START_SATELLITE_TRANSMISSION_UPDATES,
new SatelliteTransmissionUpdateArgument(result, callback, validSubId), null);
@@ -1755,23 +2312,15 @@
* Stop receiving satellite transmission updates.
* This can be called by the pointing UI when the user stops pointing to the satellite.
*
- * @param subId The subId of the subscription to stop satellite transmission updates for.
* @param errorCallback The callback to get the error code of the request.
* @param callback The callback that was passed to {@link #startSatelliteTransmissionUpdates(
* int, IIntegerConsumer, ISatelliteTransmissionUpdateCallback)}.
*/
- public void stopSatelliteTransmissionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
+ public void stopSatelliteTransmissionUpdates(@NonNull IIntegerConsumer errorCallback,
@NonNull ISatelliteTransmissionUpdateCallback callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
- int error = evaluateOemSatelliteRequestAllowed(true);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
- return;
- }
-
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
mPointingAppController.unregisterForSatelliteTransmissionUpdates(
- validSubId, result, callback);
+ getSelectedSatelliteSubId(), result, callback);
// Even if handler is null - which means there are no listeners, the modem command to stop
// satellite transmission updates might have failed. The callers might want to retry
@@ -1783,7 +2332,6 @@
* Register the subscription with a satellite provider.
* This is needed to register the subscription if the provider allows dynamic registration.
*
- * @param subId The subId of the subscription to be provisioned.
* @param token The token to be used as a unique identifier for provisioning with satellite
* gateway.
* @param provisionData Data from the provisioning app that can be used by provisioning server
@@ -1792,7 +2340,7 @@
* @return The signal transport used by the caller to cancel the provision request,
* or {@code null} if the request failed.
*/
- @Nullable public ICancellationSignal provisionSatelliteService(int subId,
+ @Nullable public ICancellationSignal provisionSatelliteService(
@NonNull String token, @NonNull byte[] provisionData,
@NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
@@ -1802,7 +2350,7 @@
return null;
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
+ final int validSubId = getSelectedSatelliteSubId();
if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS);
return null;
@@ -1835,11 +2383,10 @@
* #onSatelliteProvisionStateChanged(boolean)}
* should report as deprovisioned.
*
- * @param subId The subId of the subscription to be deprovisioned.
* @param token The token of the device/subscription to be deprovisioned.
* @param callback The callback to get the error code of the request.
*/
- public void deprovisionSatelliteService(int subId,
+ public void deprovisionSatelliteService(
@NonNull String token, @NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(false);
@@ -1848,38 +2395,44 @@
return;
}
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
- if (satelliteProvisioned == null) {
- result.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
- return;
- }
- if (!satelliteProvisioned) {
+ if (Boolean.FALSE.equals(isSatelliteViaOemProvisioned())) {
result.accept(SATELLITE_RESULT_SUCCESS);
return;
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
- new ProvisionSatelliteServiceArgument(token, null, result, validSubId),
+ new ProvisionSatelliteServiceArgument(token, null,
+ result, getSelectedSatelliteSubId()),
null);
}
/**
* Registers for the satellite provision state changed.
*
- * @param subId The subId of the subscription to register for provision state changed.
* @param callback The callback to handle the satellite provision state changed event.
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
@SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
- int subId, @NonNull ISatelliteProvisionStateCallback callback) {
+ @NonNull ISatelliteProvisionStateCallback callback) {
int error = evaluateOemSatelliteRequestAllowed(false);
if (error != SATELLITE_RESULT_SUCCESS) {
return error;
}
mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback);
+
+ boolean isProvisioned = Boolean.TRUE.equals(isSatelliteViaOemProvisioned());
+ try {
+ callback.onSatelliteProvisionStateChanged(isProvisioned);
+ } catch (RemoteException ex) {
+ loge("registerForSatelliteProvisionStateChanged: " + ex);
+ }
+ synchronized (mSatelliteViaOemProvisionLock) {
+ plogd("registerForSatelliteProvisionStateChanged: report current provisioned "
+ + "state, state=" + isProvisioned);
+ }
+
return SATELLITE_RESULT_SUCCESS;
}
@@ -1887,12 +2440,11 @@
* Unregisters for the satellite provision state changed.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for provision state changed.
* @param callback The callback that was passed to
* {@link #registerForSatelliteProvisionStateChanged(int, ISatelliteProvisionStateCallback)}.
*/
public void unregisterForSatelliteProvisionStateChanged(
- int subId, @NonNull ISatelliteProvisionStateCallback callback) {
+ @NonNull ISatelliteProvisionStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("unregisterForSatelliteProvisionStateChanged: "
+ "oemEnabledSatelliteFlag is disabled");
@@ -1904,12 +2456,11 @@
/**
* Request to get whether the device is provisioned with a satellite provider.
*
- * @param subId The subId of the subscription to get whether the device is provisioned for.
* @param result The result receiver that returns whether the device is provisioned with a
* satellite provider if the request is successful or an error code if the
* request failed.
*/
- public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) {
+ public void requestIsSatelliteProvisioned(@NonNull ResultReceiver result) {
int error = evaluateOemSatelliteRequestAllowed(false);
if (error != SATELLITE_RESULT_SUCCESS) {
result.send(error, null);
@@ -1932,17 +2483,20 @@
/**
* Registers for modem state changed from satellite modem.
*
- * @param subId The subId of the subscription to register for satellite modem state changed.
* @param callback The callback to handle the satellite modem state changed event.
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
- @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
+ @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(
@NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("registerForSatelliteModemStateChanged: add RegistrationFailure Listeners");
+ mSatelliteRegistrationFailureListeners.put(callback.asBinder(), callback);
+ }
if (mSatelliteSessionController != null) {
mSatelliteSessionController.registerForSatelliteModemStateChanged(callback);
} else {
@@ -1957,11 +2511,10 @@
* Unregisters for modem state changed from satellite modem.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for satellite modem state changed.
* @param callback The callback that was passed to
* {@link #registerForSatelliteModemStateChanged(int, ISatelliteModemStateCallback)}.
*/
- public void unregisterForModemStateChanged(int subId,
+ public void unregisterForModemStateChanged(
@NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
@@ -1973,17 +2526,20 @@
ploge("unregisterForModemStateChanged: mSatelliteSessionController"
+ " is not initialized yet");
}
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("unregisterForModemStateChanged: remove RegistrationFailure Listeners");
+ mSatelliteRegistrationFailureListeners.remove(callback.asBinder());
+ }
}
/**
* Register to receive incoming datagrams over satellite.
*
- * @param subId The subId of the subscription to register for incoming satellite datagrams.
* @param callback The callback to handle incoming datagrams over satellite.
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
- @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId,
+ @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
@@ -1993,18 +2549,18 @@
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
plogd("registerForIncomingDatagram: callback=" + callback);
- return mDatagramController.registerForSatelliteDatagram(subId, callback);
+ return mDatagramController.registerForSatelliteDatagram(
+ getSelectedSatelliteSubId(), callback);
}
/**
* Unregister to stop receiving incoming datagrams over satellite.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for incoming satellite datagrams.
* @param callback The callback that was passed to
* {@link #registerForIncomingDatagram(int, ISatelliteDatagramCallback)}.
*/
- public void unregisterForIncomingDatagram(int subId,
+ public void unregisterForIncomingDatagram(
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
@@ -2014,7 +2570,8 @@
return;
}
plogd("unregisterForIncomingDatagram: callback=" + callback);
- mDatagramController.unregisterForSatelliteDatagram(subId, callback);
+ mDatagramController.unregisterForSatelliteDatagram(
+ getSelectedSatelliteSubId(), callback);
}
/**
@@ -2025,10 +2582,9 @@
* {@link android.telephony.satellite.SatelliteDatagramCallback#onSatelliteDatagramReceived(
* long, SatelliteDatagram, int, Consumer)}
*
- * @param subId The subId of the subscription used for receiving datagrams.
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
- public void pollPendingDatagrams(int subId, @NonNull IIntegerConsumer callback) {
+ public void pollPendingDatagrams(@NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
@@ -2036,8 +2592,8 @@
return;
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
- mDatagramController.pollPendingSatelliteDatagrams(validSubId, result);
+ mDatagramController.pollPendingSatelliteDatagrams(
+ getSelectedSatelliteSubId(), result);
}
/**
@@ -2047,7 +2603,6 @@
* input to this method. Datagram received here will be passed down to modem without any
* encoding or encryption.
*
- * @param subId The subId of the subscription to send satellite datagrams for.
* @param datagramType datagram type indicating whether the datagram is of type
* SOS_SMS or LOCATION_SHARING.
* @param datagram encoded gateway datagram which is encrypted by the caller.
@@ -2056,10 +2611,10 @@
* full screen mode.
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
- public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
+ public void sendDatagram(@SatelliteManager.DatagramType int datagramType,
SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull IIntegerConsumer callback) {
- plogd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
+ plogd("sendSatelliteDatagram: datagramType: " + datagramType
+ " needFullScreenPointingUI: " + needFullScreenPointingUI);
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
@@ -2078,19 +2633,17 @@
mIsEmergency);
}
- final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
- mDatagramController.sendSatelliteDatagram(validSubId, datagramType, datagram,
- needFullScreenPointingUI, result);
+ mDatagramController.sendSatelliteDatagram(getSelectedSatelliteSubId(), datagramType,
+ datagram, needFullScreenPointingUI, result);
}
/**
* Request to get the time after which the satellite will be visible.
*
- * @param subId The subId to get the time after which the satellite will be visible for.
* @param result The result receiver that returns the time after which the satellite will
* be visible if the request is successful or an error code if the request failed.
*/
- public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) {
+ public void requestTimeForNextSatelliteVisibility(@NonNull ResultReceiver result) {
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
result.send(error, null);
@@ -2101,12 +2654,11 @@
}
/**
- * Inform whether the device is aligned with satellite for demo mode.
+ * Inform whether the device is aligned with the satellite in both real and demo mode.
*
- * @param subId The subId of the subscription.
* @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}.
*/
- public void setDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(@NonNull boolean isAligned) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
return;
@@ -2114,6 +2666,12 @@
DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned);
mDatagramController.setDeviceAlignedWithSatellite(isAligned);
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.setDeviceAlignedWithSatellite(isAligned);
+ } else {
+ ploge("setDeviceAlignedWithSatellite: mSatelliteSessionController"
+ + " is not initialized yet");
+ }
}
/**
@@ -2220,11 +2778,10 @@
/**
* Request to get the signal strength of the satellite connection.
*
- * @param subId The subId of the subscription to request for.
* @param result Result receiver to get the error code of the request and the current signal
* strength of the satellite connection.
*/
- public void requestNtnSignalStrength(int subId, @NonNull ResultReceiver result) {
+ public void requestNtnSignalStrength(@NonNull ResultReceiver result) {
if (DBG) plogd("requestNtnSignalStrength()");
int error = evaluateOemSatelliteRequestAllowed(true);
@@ -2253,7 +2810,6 @@
* is not successful, a {@link ServiceSpecificException} that contains
* {@link SatelliteManager.SatelliteResult} will be thrown.
*
- * @param subId The id of the subscription to request for.
* @param callback The callback to handle the NTN signal strength changed event. If the
* operation is successful, {@link INtnSignalStrengthCallback#onNtnSignalStrengthChanged(
* NtnSignalStrength)} will return an instance of {@link NtnSignalStrength} with a value of
@@ -2262,11 +2818,11 @@
*
* @throws ServiceSpecificException If the callback registration operation fails.
*/
- public void registerForNtnSignalStrengthChanged(int subId,
+ public void registerForNtnSignalStrengthChanged(
@NonNull INtnSignalStrengthCallback callback) throws RemoteException {
if (DBG) plogd("registerForNtnSignalStrengthChanged()");
- int error = evaluateOemSatelliteRequestAllowed(true);
+ int error = evaluateOemSatelliteRequestAllowed(false);
if (error == SATELLITE_RESULT_SUCCESS) {
mNtnSignalStrengthChangedListeners.put(callback.asBinder(), callback);
synchronized (mNtnSignalsStrengthLock) {
@@ -2287,34 +2843,28 @@
* Unregisters for NTN signal strength changed from satellite modem.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The id of the subscription to unregister for listening NTN signal strength
* changed event.
* @param callback The callback that was passed to
* {@link #registerForNtnSignalStrengthChanged(int, INtnSignalStrengthCallback)}
*/
public void unregisterForNtnSignalStrengthChanged(
- int subId, @NonNull INtnSignalStrengthCallback callback) {
+ @NonNull INtnSignalStrengthCallback callback) {
if (DBG) plogd("unregisterForNtnSignalStrengthChanged()");
-
- int error = evaluateOemSatelliteRequestAllowed(true);
- if (error == SATELLITE_RESULT_SUCCESS) {
- mNtnSignalStrengthChangedListeners.remove(callback.asBinder());
- }
+ mNtnSignalStrengthChangedListeners.remove(callback.asBinder());
}
/**
* Registers for satellite capabilities change event from the satellite service.
*
- * @param subId The id of the subscription to request for.
* @param callback The callback to handle the satellite capabilities changed event.
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
@SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged(
- int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
+ @NonNull ISatelliteCapabilitiesCallback callback) {
if (DBG) plogd("registerForCapabilitiesChanged()");
- int error = evaluateOemSatelliteRequestAllowed(true);
+ int error = evaluateOemSatelliteRequestAllowed(false);
if (error != SATELLITE_RESULT_SUCCESS) return error;
mSatelliteCapabilitiesChangedListeners.put(callback.asBinder(), callback);
@@ -2325,31 +2875,25 @@
* Unregisters for satellite capabilities change event from the satellite service.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The id of the subscription to unregister for listening satellite capabilities
* changed event.
* @param callback The callback that was passed to
* {@link #registerForCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}
*/
public void unregisterForCapabilitiesChanged(
- int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
+ @NonNull ISatelliteCapabilitiesCallback callback) {
if (DBG) plogd("unregisterForCapabilitiesChanged()");
-
- int error = evaluateOemSatelliteRequestAllowed(true);
- if (error == SATELLITE_RESULT_SUCCESS) {
- mSatelliteCapabilitiesChangedListeners.remove(callback.asBinder());
- }
+ mSatelliteCapabilitiesChangedListeners.remove(callback.asBinder());
}
/**
* Registers for the satellite supported state changed.
*
- * @param subId The subId of the subscription to register for supported state changed.
* @param callback The callback to handle the satellite supported state changed event.
*
* @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*/
@SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
- int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ @NonNull ISatelliteSupportedStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
@@ -2363,12 +2907,11 @@
* Unregisters for the satellite supported state changed.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for supported state changed.
* @param callback The callback that was passed to
* {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}.
*/
public void unregisterForSatelliteSupportedStateChanged(
- int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ @NonNull ISatelliteSupportedStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
plogd("unregisterForSatelliteSupportedStateChanged: "
+ "oemEnabledSatelliteFlag is disabled");
@@ -2381,26 +2924,28 @@
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
+ * @param provisioned Whether satellite should be provisioned or not.
* @return {@code true} if the satellite vendor service is set successfully,
* {@code false} otherwise.
*/
- public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) {
- if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- plogd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
- return false;
- }
+ public boolean setSatelliteServicePackageName(@Nullable String servicePackageName,
+ String provisioned) {
if (!isMockModemAllowed()) {
plogd("setSatelliteServicePackageName: mock modem not allowed");
return false;
}
// Cached states need to be cleared whenever switching satellite vendor services.
- plogd("setSatelliteServicePackageName: Resetting cached states");
+ plogd("setSatelliteServicePackageName: Resetting cached states, provisioned="
+ + provisioned);
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = null;
}
synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = null;
+ mIsSatelliteViaOemProvisioned = Optional.ofNullable(provisioned)
+ .filter(s -> s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false"))
+ .map(s -> s.equalsIgnoreCase("true"))
+ .orElse(null);
}
synchronized (mIsSatelliteEnabledLock) {
mIsSatelliteEnabled = null;
@@ -2433,6 +2978,21 @@
}
/**
+ * This API can be used by only CTS to control ingoring cellular service state event.
+ *
+ * @param enabled Whether to enable boolean config.
+ * @return {@code true} if the value is set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) {
+ plogd("setSatelliteIgnoreCellularServiceState - " + enabled);
+ if (mSatelliteSessionController == null) {
+ ploge("setSatelliteIgnoreCellularServiceState is not initialized yet");
+ return false;
+ }
+ return mSatelliteSessionController.setSatelliteIgnoreCellularServiceState(enabled);
+ }
+
+ /**
* This API can be used by only CTS to override timeout durations used by DatagramController
* module.
*
@@ -2511,6 +3071,14 @@
} else {
mDemoPointingNotAlignedDurationMillis = timeoutMillis;
}
+ } else if (timeoutType
+ == TIMEOUT_TYPE_EVALUATE_ESOS_PROFILES_PRIORITIZATION_DURATION_MILLIS) {
+ if (reset) {
+ mEvaluateEsosProfilesPrioritizationDurationMillis =
+ getEvaluateEsosProfilesPrioritizationDurationMillis();
+ } else {
+ mEvaluateEsosProfilesPrioritizationDurationMillis = timeoutMillis;
+ }
} else {
plogw("Invalid timeoutType=" + timeoutType);
return false;
@@ -2642,21 +3210,20 @@
plogd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
return;
}
+
if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
- synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported == null) {
- ResultReceiver receiver = new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(
- int resultCode, Bundle resultData) {
- plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
- + " resultCode=" + resultCode);
- }
- };
- requestIsSatelliteSupported(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, receiver);
+ plogd("onSatelliteServiceConnected");
+ // Vendor service might have just come back from a crash
+ moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_ERROR);
+ ResultReceiver receiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(
+ int resultCode, Bundle resultData) {
+ plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ + " resultCode=" + resultCode);
}
- }
+ };
+ requestIsSatelliteSupported(receiver);
} else {
plogd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+ " Ignored the event");
@@ -2665,27 +3232,80 @@
/**
* This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify
- * {@link SatelliteController} that it has received a request to power off the cellular radio
- * modem. {@link SatelliteController} will then power off the satellite modem.
+ * {@link SatelliteController} that it has received a request to power on or off the cellular
+ * radio modem.
+ *
+ * @param powerOn {@code true} means cellular radio is about to be powered on, {@code false}
+ * means cellular modem is about to be powered off.
*/
- public void onCellularRadioPowerOffRequested() {
- logd("onCellularRadioPowerOffRequested()");
+ public void onSetCellularRadioPowerStateRequested(boolean powerOn) {
+ logd("onSetCellularRadioPowerStateRequested: powerOn=" + powerOn);
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- plogd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
+ plogd("onSetCellularRadioPowerStateRequested: oemEnabledSatelliteFlag is disabled");
return;
}
synchronized (mIsRadioOnLock) {
- mIsRadioOn = false;
+ mRadioOffRequested = !powerOn;
}
- requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- plogd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
- }
- });
+ if (powerOn) {
+ stopWaitForCellularModemOffTimer();
+ } else {
+ requestSatelliteEnabled(
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("onSetCellularRadioPowerStateRequested: requestSatelliteEnabled"
+ + " result=" + result);
+ }
+ });
+ startWaitForCellularModemOffTimer();
+ }
+ }
+
+ /**
+ * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify
+ * {@link SatelliteController} that the request to power off the cellular radio modem has
+ * failed.
+ */
+ public void onPowerOffCellularRadioFailed() {
+ logd("onPowerOffCellularRadioFailed");
+ synchronized (mIsRadioOnLock) {
+ mRadioOffRequested = false;
+ stopWaitForCellularModemOffTimer();
+ }
+ }
+
+ /**
+ * Notify SMS received.
+ *
+ * @param subId The subId of the subscription used to receive SMS
+ */
+ public void onSmsReceived(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("onSmsReceived: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (!isSatelliteEnabled()) {
+ logd("onSmsReceived: satellite is not enabled");
+ return;
+ }
+
+ int satelliteSubId = getSelectedSatelliteSubId();
+ if (subId != satelliteSubId) {
+ logd("onSmsReceived: SMS received " + subId
+ + ", but not satellite subscription " + satelliteSubId);
+ return;
+ }
+
+ if (mDatagramController != null) {
+ mDatagramController.onSmsReceived(subId);
+ } else {
+ logd("onSmsReceived: DatagramController is not initialized");
+ }
}
/**
@@ -2839,7 +3459,7 @@
* @return {@code Pair<true, subscription ID>} if any subscription on the device is connected to
* satellite, {@code Pair<false, null>} otherwise.
*/
- private Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() {
+ Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("isUsingNonTerrestrialNetwork: carrierEnabledSatelliteFlag is disabled");
return new Pair<>(false, null);
@@ -2910,8 +3530,9 @@
return true;
}
- if (getWwanIsInService(serviceState)) {
- // Device is connected to terrestrial network which has coverage
+ if (getWwanIsInService(serviceState)
+ || serviceState.getState() == ServiceState.STATE_POWER_OFF) {
+ // Device is connected to terrestrial network which has coverage or radio is turned off
resetCarrierRoamingSatelliteModeParams(subId);
return false;
}
@@ -2934,6 +3555,81 @@
}
/**
+ * @return {@code true} if should exit satellite mode unless already sent a datagram in this
+ * esos session.
+ */
+ public boolean shouldTurnOffCarrierSatelliteForEmergencyCall() {
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone == null) return false;
+ return !mDatagramController.isEmergencyCommunicationEstablished()
+ && getConfigForSubId(mSatellitePhone.getSubId()).getBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
+ }
+ }
+
+ /**
+ * Return whether the satellite request is for an emergency or not.
+ *
+ * @return {@code true} if the satellite request is for an emergency and
+ * {@code false} otherwise.
+ */
+ public boolean getRequestIsEmergency() {
+ return mIsEmergency;
+ }
+
+ /**
+ * @return {@code true} if device is in carrier roaming nb iot ntn mode,
+ * else {@return false}
+ */
+ public boolean isInCarrierRoamingNbIotNtn() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
+ + "feature flag is disabled");
+ return false;
+ }
+
+ if (!isSatelliteEnabled()) {
+ plogd("iisInCarrierRoamingNbIotNtn: satellite is disabled");
+ return false;
+ }
+
+ Phone satellitePhone = getSatellitePhone();
+ if (!isCarrierRoamingNtnEligible(satellitePhone)) {
+ plogd("isInCarrierRoamingNbIotNtn: not carrier roaming ntn eligible.");
+ return false;
+ }
+ plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible.");
+ return true;
+ }
+
+ /**
+ * @return {@code true} if phone is in carrier roaming nb iot ntn mode,
+ * else {@return false}
+ */
+ public boolean isInCarrierRoamingNbIotNtn(@NonNull Phone phone) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
+ + "feature flag is disabled");
+ return false;
+ }
+
+ if (!isSatelliteEnabled()) {
+ plogd("iisInCarrierRoamingNbIotNtn: satellite is disabled");
+ return false;
+ }
+
+ if (!isCarrierRoamingNtnEligible(phone)) {
+ plogd("isInCarrierRoamingNbIotNtn: phone associated with subId "
+ + phone.getSubId()
+ + " is not carrier roaming ntn eligible.");
+ return false;
+ }
+ plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible for phone"
+ + " associated with subId " + phone.getSubId());
+ return true;
+ }
+
+ /**
* Return capabilities of carrier roaming satellite network.
*
* @param phone phone object
@@ -3073,6 +3769,13 @@
if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
logd("update the carrier satellite enabled to " + entitlementEnabled);
mSatelliteEntitlementStatusPerCarrier.put(subId, entitlementEnabled);
+ mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(entitlementEnabled);
+ if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) {
+ removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT);
+ sendMessageDelayed(obtainMessage(
+ EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT),
+ WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS);
+ }
try {
mSubscriptionManagerService.setSubscriptionProperty(subId,
SATELLITE_ENTITLEMENT_STATUS, entitlementEnabled ? "1" : "0");
@@ -3132,7 +3835,7 @@
* We have not successfully checked whether the modem supports satellite service.
* Thus, we need to retry it now.
*/
- requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ requestIsSatelliteSupported(
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -3156,6 +3859,7 @@
mProvisionMetricsStats
.setResultCode(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE)
.setIsProvisionRequest(true)
+ .setCarrierId(getSatelliteCarrierId())
.reportProvisionMetrics();
mControllerMetricsStats.reportProvisionCount(
SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
@@ -3174,6 +3878,7 @@
}
mProvisionMetricsStats.setResultCode(result)
.setIsProvisionRequest(true)
+ .setCarrierId(getSatelliteCarrierId())
.reportProvisionMetrics();
mControllerMetricsStats.reportProvisionCount(result);
}
@@ -3203,6 +3908,7 @@
}
mProvisionMetricsStats.setResultCode(result)
.setIsProvisionRequest(false)
+ .setCarrierId(getSatelliteCarrierId())
.reportProvisionMetrics();
mControllerMetricsStats.reportDeprovisionCount(result);
}
@@ -3241,38 +3947,6 @@
}
/**
- * Posts the specified command to be executed on the main thread. As this is a synchronous
- * request, it waits until the request is complete and then return the result.
- *
- * @param command command to be executed on the main thread
- * @param argument additional parameters required to perform of the operation
- * @param phone phone object used to perform the operation.
- * @return result of the operation
- */
- private @Nullable Object sendRequest(int command, @NonNull Object argument,
- @Nullable Phone phone) {
- if (Looper.myLooper() == this.getLooper()) {
- throw new RuntimeException("This method will deadlock if called from the main thread");
- }
-
- SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest(
- argument, phone);
- Message msg = this.obtainMessage(command, request);
- msg.sendToTarget();
-
- synchronized (request) {
- while(request.result == null) {
- try {
- request.wait();
- } catch (InterruptedException e) {
- // Do nothing, go back and wait until the request is complete.
- }
- }
- }
- return request.result;
- }
-
- /**
* Check if satellite is provisioned for a subscription on the device.
* @return true if satellite is provisioned on the given subscription else return false.
*/
@@ -3284,41 +3958,54 @@
return mOverriddenIsSatelliteViaOemProvisioned;
}
- if (mIsSatelliteViaOemProvisioned != null) {
- return mIsSatelliteViaOemProvisioned;
+ if (mIsSatelliteViaOemProvisioned == null) {
+ mIsSatelliteViaOemProvisioned = getPersistedOemEnabledSatelliteProvisionStatus();
}
+ return mIsSatelliteViaOemProvisioned;
}
-
- requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- plogd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
- }
- });
- return null;
}
private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) {
RequestSatelliteEnabledArgument argument =
(RequestSatelliteEnabledArgument) request.argument;
handlePersistentLoggingOnSessionStart(argument);
+ selectBindingSatelliteSubscription();
+ SatelliteModemEnableRequestAttributes enableRequestAttributes =
+ createModemEnableRequest(argument);
+ if (enableRequestAttributes == null) {
+ plogw("handleSatelliteEnabled: enableRequestAttributes is null");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE, argument.callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (argument.enableSatellite) {
+ mSatelliteEnabledRequest = null;
+ } else {
+ mSatelliteDisabledRequest = null;
+ }
+ }
+ return;
+ }
+
if (mSatelliteSessionController != null) {
mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite);
} else {
ploge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet");
}
+ /* Framework will send back the disable result to the requesting client only after receiving
+ * both confirmation for the disable request from modem, and OFF state from modem if the
+ * modem is not in OFF state.
+ */
if (!argument.enableSatellite && mSatelliteModemInterface.isSatelliteServiceSupported()) {
- synchronized (mIsSatelliteEnabledLock) {
+ synchronized (mSatelliteEnabledRequestLock) {
mWaitingForDisableSatelliteModemResponse = true;
- mWaitingForSatelliteModemOff = true;
+ if (!isSatelliteDisabled()) mWaitingForSatelliteModemOff = true;
}
}
Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
- mSatelliteModemInterface.requestSatelliteEnabled(argument.enableSatellite,
- argument.enableDemoMode, argument.isEmergency, onCompleted);
+ mSatelliteModemInterface.requestSatelliteEnabled(
+ enableRequestAttributes, onCompleted);
startWaitForSatelliteEnablingResponseTimer(argument);
// Logs satellite session timestamps for session metrics
if (argument.enableSatellite) {
@@ -3327,6 +4014,22 @@
mSessionProcessingTimeStamp = System.currentTimeMillis();
}
+ /** Get the request attributes that modem needs to enable/disable satellite */
+ @Nullable private SatelliteModemEnableRequestAttributes createModemEnableRequest(
+ @NonNull RequestSatelliteEnabledArgument arg) {
+ int subId = getSelectedSatelliteSubId();
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (subInfo == null) {
+ loge("createModemEnableRequest: no SubscriptionInfo found for subId=" + subId);
+ return null;
+ }
+ String iccid = subInfo.getIccId();
+ String apn = getConfigForSubId(subId).getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+ return new SatelliteModemEnableRequestAttributes(
+ arg.enableSatellite, arg.enableDemoMode, arg.isEmergency,
+ new SatelliteSubscriptionInfo(iccid, apn));
+ }
+
private void handleRequestSatelliteAttachRestrictionForCarrierCmd(
SatelliteControllerHandlerRequest request) {
RequestHandleSatelliteAttachRestrictionForCarrierArgument argument =
@@ -3342,48 +4045,49 @@
evaluateEnablingSatelliteForCarrier(argument.subId, argument.reason, argument.callback);
}
- private void updateSatelliteSupportedStateWhenSatelliteServiceConnected(boolean supported) {
+ private void updateSatelliteSupportedState(boolean supported) {
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = supported;
}
mSatelliteSessionController = SatelliteSessionController.make(
mContext, getLooper(), mFeatureFlags, supported);
- plogd("create a new SatelliteSessionController due to isSatelliteSupported state has "
- + "changed to " + supported);
+ plogd("updateSatelliteSupportedState: create a new SatelliteSessionController because "
+ + "satellite supported state has changed to " + supported);
if (supported) {
- registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForNtnSignalStrengthChanged();
registerForCapabilitiesChanged();
+ registerForSatelliteRegistrationFailure();
- requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ requestIsSatelliteProvisioned(
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- plogd("requestIsSatelliteProvisioned: resultCode=" + resultCode
- + ", resultData=" + resultData);
- requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false, false, false,
+ plogd("updateSatelliteSupportedState.requestIsSatelliteProvisioned: "
+ + "resultCode=" + resultCode + ", resultData=" + resultData);
+ requestSatelliteEnabled(false, false, false,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- plogd("requestSatelliteEnabled: result=" + result);
+ plogd("updateSatelliteSupportedState."
+ + "requestSatelliteEnabled: result=" + result);
}
});
}
});
- requestSatelliteCapabilities(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ requestSatelliteCapabilities(
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- plogd("requestSatelliteCapabilities: resultCode=" + resultCode
- + ", resultData=" + resultData);
+ plogd("updateSatelliteSupportedState.requestSatelliteCapabilities: "
+ + "resultCode=" + resultCode + ", resultData=" + resultData);
}
});
}
registerForSatelliteSupportedStateChanged();
+ selectBindingSatelliteSubscription();
}
private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -3401,16 +4105,6 @@
}
}
- private void registerForSatelliteProvisionStateChanged() {
- if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
- if (!mRegisteredForProvisionStateChangedWithSatelliteService.get()) {
- mSatelliteModemInterface.registerForSatelliteProvisionStateChanged(
- this, EVENT_SATELLITE_PROVISION_STATE_CHANGED, null);
- mRegisteredForProvisionStateChangedWithSatelliteService.set(true);
- }
- }
- }
-
private void registerForPendingDatagramCount() {
if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
if (!mRegisteredForPendingDatagramCountWithSatelliteService.get()) {
@@ -3471,6 +4165,16 @@
}
}
+ private void registerForSatelliteRegistrationFailure() {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (!mRegisteredForSatelliteRegistrationFailure.get()) {
+ mSatelliteModemInterface.registerForSatelliteRegistrationFailure(this,
+ EVENT_SATELLITE_REGISTRATION_FAILURE, null);
+ mRegisteredForSatelliteRegistrationFailure.set(true);
+ }
+ }
+ }
+
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
@@ -3493,42 +4197,110 @@
});
}
+ private boolean updateSatelliteSubscriptionProvisionState(List<SatelliteSubscriberInfo> newList,
+ boolean provisioned) {
+ logd("updateSatelliteSubscriptionProvisionState: List=" + newList + " , provisioned="
+ + provisioned);
+ boolean provisionChanged = false;
+ synchronized (mSatelliteTokenProvisionedLock) {
+ for (SatelliteSubscriberInfo subscriberInfo : newList) {
+ if (mProvisionedSubscriberId.getOrDefault(subscriberInfo.getSubscriberId(), false)
+ == provisioned) {
+ continue;
+ }
+ provisionChanged = true;
+ mProvisionedSubscriberId.put(subscriberInfo.getSubscriberId(), provisioned);
+ int subId = mSubscriberIdPerSub.getOrDefault(subscriberInfo.getSubscriberId(),
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ try {
+ mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
+ provisioned);
+ plogd("updateSatelliteSubscriptionProvisionState: set Provision state to db "
+ + "subId=" + subId);
+ } catch (IllegalArgumentException | SecurityException ex) {
+ ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
+ + ex);
+ }
+ }
+ }
+ return provisionChanged;
+ }
+
+ private void handleEventSatelliteSubscriptionProvisionStateChanged() {
+ List<SatelliteSubscriberProvisionStatus> informList =
+ getPrioritizedSatelliteSubscriberProvisionStatusList();
+ plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
+ notifySatelliteSubscriptionProvisionStateChanged(informList);
+ // Report updated provisioned status
+ synchronized (mSatelliteTokenProvisionedLock) {
+ boolean isProvisioned = !mProvisionedSubscriberId.isEmpty()
+ && mProvisionedSubscriberId.containsValue(Boolean.TRUE);
+ mControllerMetricsStats.setIsProvisioned(isProvisioned);
+ }
+ selectBindingSatelliteSubscription();
+ handleStateChangedForCarrierRoamingNtnEligibility();
+ }
+
+ private void notifySatelliteSubscriptionProvisionStateChanged(
+ @NonNull List<SatelliteSubscriberProvisionStatus> list) {
+ List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
+ mSatelliteProvisionStateChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onSatelliteSubscriptionProvisionStateChanged(list);
+ } catch (RemoteException e) {
+ plogd("notifySatelliteSubscriptionProvisionStateChanged: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSatelliteProvisionStateChangedListeners.remove(listener.asBinder());
+ });
+ }
+
private void handleEventSatelliteModemStateChanged(
@SatelliteManager.SatelliteModemState int state) {
plogd("handleEventSatelliteModemStateChanged: state=" + state);
if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
|| state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
- synchronized (mIsSatelliteEnabledLock) {
- if ((state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE)
- || ((mIsSatelliteEnabled == null || isSatelliteEnabled())
- && !mWaitingForDisableSatelliteModemResponse)) {
- int error = (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF)
- ? SATELLITE_RESULT_SUCCESS
- : SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE;
- Consumer<Integer> callback = null;
- synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteEnabledRequest != null) {
- callback = mSatelliteEnabledRequest.callback;
- }
- }
- moveSatelliteToOffStateAndCleanUpResources(error, callback);
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (!mWaitingForDisableSatelliteModemResponse) {
+ moveSatelliteToOffStateAndCleanUpResources(
+ SATELLITE_RESULT_SUCCESS);
} else {
- plogd("Either waiting for the response of disabling satellite modem or the"
- + " event should be ignored because isSatelliteEnabled="
- + isSatelliteEnabled()
- + ", mIsSatelliteEnabled=" + mIsSatelliteEnabled);
+ notifyModemStateChangedToSessionController(
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF);
}
mWaitingForSatelliteModemOff = false;
}
} else {
- if (mSatelliteSessionController != null) {
- mSatelliteSessionController.onSatelliteModemStateChanged(state);
+ if (isSatelliteEnabledOrBeingEnabled() || isSatelliteBeingDisabled()) {
+ notifyModemStateChangedToSessionController(state);
} else {
- ploge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
+ // Telephony framework and modem are out of sync. We need to disable modem
+ synchronized (mSatelliteEnabledRequestLock) {
+ plogw("Satellite modem is in a bad state. Disabling satellite modem now ...");
+ Consumer<Integer> result = integer -> plogd(
+ "handleEventSatelliteModemStateChanged: disabling satellite result="
+ + integer);
+ mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */, result);
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, mSatelliteDisabledRequest, null);
+ }
}
}
}
+ private void notifyModemStateChangedToSessionController(
+ @SatelliteManager.SatelliteModemState int state) {
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onSatelliteModemStateChanged(state);
+ } else {
+ ploge("notifyModemStateChangedToSessionController: mSatelliteSessionController is "
+ + "null");
+ }
+ }
+
private void handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
logd("handleEventNtnSignalStrengthChanged: ntnSignalStrength=" + ntnSignalStrength);
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
@@ -3568,8 +4340,11 @@
List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>();
mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> {
+ synchronized (this.mSatelliteCapabilitiesLock) {
+ overrideSatelliteCapabilitiesIfApplicable();
+ }
try {
- listener.onSatelliteCapabilitiesChanged(capabilities);
+ listener.onSatelliteCapabilitiesChanged(this.mSatelliteCapabilities);
} catch (RemoteException e) {
plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
deadCallersList.add(listener);
@@ -3592,7 +4367,7 @@
return;
}
- updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
+ updateSatelliteSupportedState(supported);
/* In case satellite has been reported as not support from modem, but satellite is
enabled, request disable satellite. */
@@ -3600,15 +4375,13 @@
if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) {
plogd("Invoke requestSatelliteEnabled(), supported=false, "
+ "mIsSatelliteEnabled=true");
- requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false /* enableSatellite */, false /* enableDemoMode */,
+ requestSatelliteEnabled(false /* enableSatellite */, false /* enableDemoMode */,
false /* isEmergency */,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
plogd("handleSatelliteSupportedStateChangedEvent: request "
- + "satellite disable, result="
- + result);
+ + "satellite disable, result=" + result);
}
});
@@ -3653,7 +4426,8 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void setSettingsKeyToAllowDeviceRotation(int val) {
// Only allows on a foldable device type.
- if (!isFoldable(mContext)) {
+ if (!isFoldable(mContext, mDeviceStates)) {
+ logd("setSettingsKeyToAllowDeviceRotation(" + val + "), device was not a foldable");
return;
}
@@ -3694,10 +4468,19 @@
* If the device type is foldable.
*
* @param context context
+ * @param deviceStates list of {@link DeviceState}s provided from {@link DeviceStateManager}
* @return {@code true} if device type is foldable. {@code false} for otherwise.
*/
- private boolean isFoldable(Context context) {
- return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isFoldable(Context context, List<DeviceState> deviceStates) {
+ if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) {
+ return deviceStates.stream().anyMatch(deviceState -> deviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY)
+ || deviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY));
+ } else {
+ return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+ }
}
/**
@@ -3762,8 +4545,6 @@
if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null)
&& mWaitingForRadioDisabled) {
plogd("Sending success to callback that sent enable satellite request");
- setDemoModeEnabled(mSatelliteEnabledRequest.enableDemoMode);
- mIsEmergency = mSatelliteEnabledRequest.isEmergency;
synchronized (mIsSatelliteEnabledLock) {
mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite;
}
@@ -3771,8 +4552,21 @@
updateSatelliteEnabledState(
mSatelliteEnabledRequest.enableSatellite,
"EVENT_SET_SATELLITE_ENABLED_DONE");
+ setEmergencyMode(mSatelliteEnabledRequest.isEmergency);
+ if (mSatelliteEnabledRequest.enableSatellite
+ && !mSatelliteEnabledRequest.isEmergency) {
+ plogd("Starting pointingUI needFullscreenPointingUI=" + true
+ + "mIsDemoModeEnabled=" + mIsDemoModeEnabled + ", isEmergency="
+ + mSatelliteEnabledRequest.isEmergency);
+ mPointingAppController.startPointingUI(true, mIsDemoModeEnabled, false);
+ }
mSatelliteEnabledRequest = null;
mWaitingForRadioDisabled = false;
+
+ if (mSatelliteEnableAttributesUpdateRequest != null) {
+ sendRequestAsync(CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES,
+ mSatelliteEnableAttributesUpdateRequest, null);
+ }
}
}
}
@@ -3785,21 +4579,41 @@
}
}
- private void moveSatelliteToOffStateAndCleanUpResources(
- @SatelliteManager.SatelliteResult int error, @Nullable Consumer<Integer> callback) {
+ private void resetSatelliteDisabledRequest() {
+ plogd("resetSatelliteDisabledRequest");
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteDisabledRequest = null;
+ mWaitingForDisableSatelliteModemResponse = false;
+ mWaitingForSatelliteModemOff = false;
+ }
+ }
+
+ /**
+ * Move to OFF state and clean up resources.
+ *
+ * @param resultCode The result code will be returned to requesting clients.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void moveSatelliteToOffStateAndCleanUpResources(
+ @SatelliteManager.SatelliteResult int resultCode) {
plogd("moveSatelliteToOffStateAndCleanUpResources");
synchronized (mIsSatelliteEnabledLock) {
- resetSatelliteEnabledRequest();
setDemoModeEnabled(false);
handlePersistentLoggingOnSessionEnd(mIsEmergency);
- mIsEmergency = false;
+ setEmergencyMode(false);
mIsSatelliteEnabled = false;
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
- if (callback != null) callback.accept(error);
+ abortSatelliteDisableRequest(resultCode);
+ abortSatelliteEnableRequest(resultCode);
+ abortSatelliteEnableAttributesUpdateRequest(resultCode);
+ resetSatelliteEnabledRequest();
+ resetSatelliteDisabledRequest();
+ // TODO (b/361139260): Stop timer to wait for other radios off
updateSatelliteEnabledState(
false, "moveSatelliteToOffStateAndCleanUpResources");
}
+ selectBindingSatelliteSubscription();
}
private void setDemoModeEnabled(boolean enabled) {
@@ -3808,6 +4622,18 @@
plogd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled);
}
+ private void setEmergencyMode(boolean isEmergency) {
+ plogd("setEmergencyMode: mIsEmergency=" + mIsEmergency + ", isEmergency=" + isEmergency);
+ if (mIsEmergency != isEmergency) {
+ mIsEmergency = isEmergency;
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onEmergencyModeChanged(mIsEmergency);
+ } else {
+ plogw("setEmergencyMode: mSatelliteSessionController is null");
+ }
+ }
+ }
+
private boolean isMockModemAllowed() {
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
@@ -3963,14 +4789,32 @@
}
@NonNull private PersistableBundle getConfigForSubId(int subId) {
- PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId,
- KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
- KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
- KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
- KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
- KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
- KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
- KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT);
+ PersistableBundle config = null;
+ if (mCarrierConfigManager != null) {
+ try {
+ config = mCarrierConfigManager.getConfigForSubId(subId,
+ KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL,
+ KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
+ KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+ KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
+ KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+ KEY_SATELLITE_ESOS_SUPPORTED_BOOL,
+ KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL,
+ KEY_SATELLITE_NIDD_APN_NAME_STRING,
+ KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+ KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT,
+ KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
+ KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT
+ );
+ } catch (Exception e) {
+ logw("getConfigForSubId: " + e);
+ }
+ }
if (config == null || config.isEmpty()) {
config = CarrierConfigManager.getDefaultConfig();
}
@@ -3987,10 +4831,21 @@
}
updateCarrierConfig(subId);
+ updateSatelliteESOSSupported(subId);
+ updateSatelliteProvisionedStatePerSubscriberId();
updateEntitlementPlmnListPerCarrier(subId);
updateSupportedSatelliteServicesForActiveSubscriptions();
processNewCarrierConfigData(subId);
resetCarrierRoamingSatelliteModeParams(subId);
+ handleStateChangedForCarrierRoamingNtnEligibility();
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
+ }
+
+ // imsi, msisdn, default sms subId change
+ private void handleSubscriptionsChanged() {
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ mEvaluateEsosProfilesPrioritizationDurationMillis);
}
private void processNewCarrierConfigData(int subId) {
@@ -4050,6 +4905,54 @@
}
}
+ /**
+ * Update the value of SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED stored in the database based
+ * on the value in the carrier config.
+ */
+ private void updateSatelliteESOSSupported(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+
+ boolean isSatelliteESosSupportedFromDB =
+ mSubscriptionManagerService.getSatelliteESOSSupported(subId);
+ boolean isSatelliteESosSupportedFromCarrierConfig = getConfigForSubId(subId).getBoolean(
+ KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false);
+ if (isSatelliteESosSupportedFromDB != isSatelliteESosSupportedFromCarrierConfig) {
+ mSubscriptionManagerService.setSatelliteESOSSupported(subId,
+ isSatelliteESosSupportedFromCarrierConfig);
+ logd("updateSatelliteESOSSupported: " + isSatelliteESosSupportedFromCarrierConfig);
+ }
+ }
+
+ /** If the provision state per subscriberId for the cached is not exist, check the database for
+ * the corresponding value and use it. */
+ private void updateSatelliteProvisionedStatePerSubscriberId() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+
+ List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ for (SubscriptionInfo info : allSubInfos) {
+ int subId = info.getSubscriptionId();
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(
+ mSubscriptionManagerService.getSubscriptionInfo(subId));
+ String subscriberId = subscriberIdPair.first;
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (mProvisionedSubscriberId.get(subscriberId) == null) {
+ boolean Provisioned = mSubscriptionManagerService
+ .isSatelliteProvisionedForNonIpDatagram(subId);
+ if (Provisioned) {
+ mProvisionedSubscriberId.put(subscriberId, true);
+ logd("updateSatelliteProvisionStatePerSubscriberId: " + subscriberId
+ + " set true");
+ }
+ }
+ }
+ }
+ }
+
@NonNull
private String[] readStringArrayFromOverlayConfig(@ArrayRes int id) {
String[] strArray = null;
@@ -4070,6 +4973,46 @@
}
/**
+ * Return whether the device support P2P SMS mode from carrier config.
+ *
+ * @param subId Associated subscription ID
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean isSatelliteRoamingP2pSmSSupported(int subId) {
+ return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL);
+ }
+
+ /**
+ * Return whether the device support ESOS mode from carrier config.
+ *
+ * @param subId Associated subscription ID
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean isSatelliteEsosSupported(int subId) {
+ return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
+ }
+
+ /**
+ * Return whether the device allows to turn off satellite session for emergency call.
+ *
+ * @param subId Associated subscription ID
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean turnOffSatelliteSessionForEmergencyCall(int subId) {
+ return getConfigForSubId(subId).getBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
+ }
+
+ private int getCarrierRoamingNtnConnectType(int subId) {
+ return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT);
+ }
+
+ protected int getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(int subId) {
+ return getConfigForSubId(subId).getInt(
+ KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT);
+ }
+
+ /**
* Check if satellite attach is enabled by user for the carrier associated with the
* {@code subId}.
*
@@ -4176,6 +5119,13 @@
}
boolean result = entitlementStatus.equals("1");
mSatelliteEntitlementStatusPerCarrier.put(subId, result);
+ mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(result);
+ if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) {
+ removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT);
+ sendMessageDelayed(obtainMessage(
+ EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT),
+ WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS);
+ }
}
if (!mSatelliteEntitlementStatusPerCarrier.get(subId, false)) {
@@ -4320,6 +5270,7 @@
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteProvisioned) {
+ plogd("evaluateOemSatelliteRequestAllowed: satellite service is not provisioned");
return SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
}
}
@@ -4348,6 +5299,7 @@
mSessionMetricsStats.setInitializationResult(error)
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setIsDemoMode(mIsDemoModeEnabled)
+ .setCarrierId(getSatelliteCarrierId())
.reportSessionMetrics();
mSessionStartTimeStamp = 0;
mSessionProcessingTimeStamp = 0;
@@ -4363,22 +5315,26 @@
}
private void handleEventServiceStateChanged() {
+ handleStateChangedForCarrierRoamingNtnEligibility();
handleServiceStateForSatelliteConnectionViaCarrier();
- determineSystemNotification();
}
private void handleServiceStateForSatelliteConnectionViaCarrier() {
for (Phone phone : PhoneFactory.getPhones()) {
int subId = phone.getSubId();
ServiceState serviceState = phone.getServiceState();
- if (serviceState == null) {
+ if (serviceState == null || subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
continue;
}
synchronized (mSatelliteConnectedLock) {
CarrierRoamingSatelliteSessionStats sessionStats =
mCarrierRoamingSatelliteSessionStatsMap.get(subId);
-
+ if (DEBUG) {
+ plogd("handleServiceStateForSatelliteConnectionViaCarrier : SubId = " + subId
+ + " isUsingNonTerrestrialNetwork = "
+ + serviceState.isUsingNonTerrestrialNetwork());
+ }
if (serviceState.isUsingNonTerrestrialNetwork()) {
if (sessionStats != null) {
sessionStats.onSignalStrength(phone);
@@ -4400,7 +5356,8 @@
}
} else {
Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId);
- if (getWwanIsInService(serviceState)) {
+ if (getWwanIsInService(serviceState)
+ || serviceState.getState() == ServiceState.STATE_POWER_OFF) {
resetCarrierRoamingSatelliteModeParams(subId);
} else if (connected != null && connected) {
// The device just got disconnected from a satellite network
@@ -4424,11 +5381,11 @@
updateLastNotifiedNtnModeAndNotify(phone);
}
}
+ determineAutoConnectSystemNotification();
}
private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
-
if (phone == null) {
return;
}
@@ -4443,6 +5400,9 @@
mLastNotifiedNtnMode.put(subId, currNtnMode);
phone.notifyCarrierRoamingNtnModeChanged(currNtnMode);
logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode);
+ if(mIsNotificationShowing && !currNtnMode) {
+ dismissSatelliteNotification();
+ }
}
}
}
@@ -4467,37 +5427,169 @@
}
}
+ private void handleStateChangedForCarrierRoamingNtnEligibility() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ synchronized (mSatellitePhoneLock) {
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
+ + "isCarrierRoamingNtnEligible=" + eligible);
+
+ if (eligible) {
+ if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
+ startNtnEligibilityHysteresisTimer();
+ }
+ } else {
+ mNtnEligibilityHysteresisTimedOut = false;
+ stopNtnEligibilityHysteresisTimer();
+ updateLastNotifiedNtnEligibilityAndNotify(false);
+ }
+ }
+ }
+
+ private boolean shouldStartNtnEligibilityHysteresisTimer(boolean eligible) {
+ if (!eligible) {
+ return false;
+ }
+
+ if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) {
+ plogd("shouldStartNtnEligibilityHysteresisTimer: Timer is already running.");
+ return false;
+ }
+
+ synchronized (mSatellitePhoneLock) {
+ if (mLastNotifiedNtnEligibility != null && mLastNotifiedNtnEligibility) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void startNtnEligibilityHysteresisTimer() {
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone == null) {
+ ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null.");
+ return;
+ }
+
+ int subId = getSelectedSatelliteSubId();
+ long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId);
+ mNtnEligibilityHysteresisTimedOut = false;
+ plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId
+ + ", phoneId=" + mSatellitePhone.getPhoneId() + ", timeout=" + timeout);
+ sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT),
+ timeout);
+ }
+ }
+
+ private void stopNtnEligibilityHysteresisTimer() {
+ if (hasMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT)) {
+ removeMessages(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT);
+ }
+ }
+
+ private void updateLastNotifiedNtnEligibilityAndNotify(boolean currentNtnEligibility) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("notifyNtnEligibility: carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ if (mOverrideNtnEligibility != null) {
+ mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ return;
+ }
+
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone == null) {
+ ploge("notifyNtnEligibility: mSatellitePhone is null");
+ return;
+ }
+
+ plogd("notifyNtnEligibility: phoneId=" + mSatellitePhone.getPhoneId()
+ + " currentNtnEligibility=" + currentNtnEligibility);
+ if (mLastNotifiedNtnEligibility == null
+ || mLastNotifiedNtnEligibility != currentNtnEligibility) {
+ mLastNotifiedNtnEligibility = currentNtnEligibility;
+ mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ updateSatelliteSystemNotification(getSelectedSatelliteSubId(),
+ CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL,
+ currentNtnEligibility);
+ }
+ }
+ }
+
private long getSatelliteConnectionHysteresisTimeMillis(int subId) {
PersistableBundle config = getPersistableBundle(subId);
return (config.getInt(
KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L);
}
+ private long getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ return (config.getInt(
+ KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT) * 1000L);
+ }
+
private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
synchronized (mSatelliteViaOemProvisionLock) {
plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
-
- if (!loadSatelliteSharedPreferences()) return;
-
- if (mSharedPreferences == null) {
- ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ try {
+ mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
+ isProvisioned);
+ plogd("persistOemEnabledSatelliteProvisionStatus: subId=" + subId);
+ } catch (IllegalArgumentException | SecurityException ex) {
+ ploge("setIsSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
+ + ex);
+ }
+ } else {
+ plogd("persistOemEnabledSatelliteProvisionStatus: INVALID_SUBSCRIPTION_ID");
+ }
} else {
- mSharedPreferences.edit().putBoolean(
- OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply();
+ if (!loadSatelliteSharedPreferences()) return;
+
+ if (mSharedPreferences == null) {
+ ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ } else {
+ mSharedPreferences.edit().putBoolean(
+ OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply();
+ }
}
}
}
- private boolean getPersistedOemEnabledSatelliteProvisionStatus() {
+ @Nullable
+ private Boolean getPersistedOemEnabledSatelliteProvisionStatus() {
+ plogd("getPersistedOemEnabledSatelliteProvisionStatus:");
synchronized (mSatelliteViaOemProvisionLock) {
- if (!loadSatelliteSharedPreferences()) return false;
-
- if (mSharedPreferences == null) {
- ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
- return false;
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
+ subId);
+ } else {
+ plogd("getPersistedOemEnabledSatelliteProvisionStatus: "
+ + "subId=INVALID_SUBSCRIPTION_ID, return null");
+ return null;
+ }
} else {
- return mSharedPreferences.getBoolean(
- OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, false);
+ if (!loadSatelliteSharedPreferences()) return false;
+
+ if (mSharedPreferences == null) {
+ ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is "
+ + "null");
+ return false;
+ } else {
+ return mSharedPreferences.getBoolean(
+ OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, false);
+ }
}
}
}
@@ -4518,31 +5610,13 @@
}
private void handleIsSatelliteProvisionedDoneEvent(@NonNull AsyncResult ar) {
+ logd("handleIsSatelliteProvisionedDoneEvent:");
SatelliteControllerHandlerRequest request = (SatelliteControllerHandlerRequest) ar.userObj;
- int error = SatelliteServiceUtils.getSatelliteError(
- ar, "handleIsSatelliteProvisionedDoneEvent");
- boolean isSatelliteProvisionedInModem = false;
- if (error == SATELLITE_RESULT_SUCCESS) {
- if (ar.result == null) {
- ploge("handleIsSatelliteProvisionedDoneEvent: result is null");
- error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
- } else {
- isSatelliteProvisionedInModem = ((int[]) ar.result)[0] == 1;
- }
- } else if (error == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
- plogd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
- isSatelliteProvisionedInModem = true;
- }
- boolean isSatelliteViaOemProvisioned =
- isSatelliteProvisionedInModem && getPersistedOemEnabledSatelliteProvisionStatus();
- plogd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
- + ", isSatelliteViaOemProvisioned=" + isSatelliteViaOemProvisioned);
+
Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, isSatelliteViaOemProvisioned);
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = isSatelliteViaOemProvisioned;
- }
- ((ResultReceiver) request.argument).send(error, bundle);
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
+ Boolean.TRUE.equals(isSatelliteViaOemProvisioned()));
+ ((ResultReceiver) request.argument).send(SATELLITE_RESULT_SUCCESS, bundle);
}
private long getWaitForSatelliteEnablingResponseTimeoutMillis() {
@@ -4550,6 +5624,32 @@
R.integer.config_wait_for_satellite_enabling_response_timeout_millis);
}
+ private long getWaitForCellularModemOffTimeoutMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis);
+ }
+
+ private void startWaitForCellularModemOffTimer() {
+ synchronized (mIsRadioOnLock) {
+ if (hasMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT)) {
+ plogd("startWaitForCellularModemOffTimer: the timer was already started");
+ return;
+ }
+ long timeoutMillis = getWaitForCellularModemOffTimeoutMillis();
+ plogd("Start timer to wait for cellular modem OFF state, timeoutMillis="
+ + timeoutMillis);
+ sendMessageDelayed(obtainMessage(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT),
+ timeoutMillis);
+ }
+ }
+
+ private void stopWaitForCellularModemOffTimer() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ plogd("Stop timer to wait for cellular modem OFF state");
+ removeMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT);
+ }
+ }
+
private void startWaitForSatelliteEnablingResponseTimer(
@NonNull RequestSatelliteEnabledArgument argument) {
synchronized (mSatelliteEnabledRequestLock) {
@@ -4586,78 +5686,96 @@
}
}
+ private void startWaitForUpdateSatelliteEnableAttributesResponseTimer(
+ @NonNull RequestSatelliteEnabledArgument argument) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (hasMessages(EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT,
+ argument)) {
+ plogd("WaitForUpdateSatelliteEnableAttributesResponseTimer of request ID "
+ + argument.requestId + " was already started");
+ return;
+ }
+ plogd("Start timer to wait for response of the update satellite enable attributes"
+ + " request ID=" + argument.requestId
+ + ", enableSatellite=" + argument.enableSatellite
+ + ", mWaitTimeForSatelliteEnablingResponse="
+ + mWaitTimeForSatelliteEnablingResponse);
+ sendMessageDelayed(obtainMessage(
+ EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT,
+ argument), mWaitTimeForSatelliteEnablingResponse);
+ }
+ }
+
+ private void stopWaitForUpdateSatelliteEnableAttributesResponseTimer(
+ @NonNull RequestSatelliteEnabledArgument argument) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ plogd("Stop timer to wait for response of the enable attributes update request ID="
+ + argument.requestId + ", enableSatellite=" + argument.enableSatellite);
+ removeMessages(
+ EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT, argument);
+ }
+ }
+
+ private boolean shouldProcessEventUpdateSatelliteEnableAttributesDone(
+ @NonNull RequestSatelliteEnabledArgument argument) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (hasMessages(EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT,
+ argument)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
private void handleEventWaitForSatelliteEnablingResponseTimedOut(
@NonNull RequestSatelliteEnabledArgument argument) {
plogw("Timed out to wait for response of the satellite enabling request ID="
+ argument.requestId + ", enableSatellite=" + argument.enableSatellite);
- synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteEnabledRequest != null) {
- if (mSatelliteEnabledRequest.enableSatellite && !argument.enableSatellite
- && mWaitingForRadioDisabled) {
- // Previous mSatelliteEnabledRequest is successful but waiting for
- // all radios to be turned off.
- mSatelliteEnabledRequest.callback.accept(SATELLITE_RESULT_SUCCESS);
- resetSatelliteEnabledRequest();
- } else if (mSatelliteEnabledRequest.requestId == argument.requestId) {
- resetSatelliteEnabledRequest();
- }
- }
- }
argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT);
-
synchronized (mIsSatelliteEnabledLock) {
if (argument.enableSatellite) {
- if (!mWaitingForDisableSatelliteModemResponse && !mWaitingForSatelliteModemOff) {
- resetSatelliteEnabledRequest();
- IIntegerConsumer callback = new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
- + "disable satellite result=" + result);
- }
- };
- Consumer<Integer> result =
- FunctionalUtils.ignoreRemoteException(callback::accept);
- RequestSatelliteEnabledArgument request = new RequestSatelliteEnabledArgument(
- false, false, false, result);
- synchronized (mSatelliteEnabledRequestLock) {
- mSatelliteEnabledRequest = request;
+ resetSatelliteEnabledRequest();
+ abortSatelliteEnableAttributesUpdateRequest(SATELLITE_RESULT_REQUEST_ABORTED);
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (mSatelliteDisabledRequest == null) {
+ IIntegerConsumer callback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
+ + "disable satellite result=" + result);
+ }
+ };
+ Consumer<Integer> result =
+ FunctionalUtils.ignoreRemoteException(callback::accept);
+ mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(
+ false, false, false, result);
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, mSatelliteDisabledRequest,
+ null);
}
- sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
}
- notifyEnablementFailedToSatelliteSessionController();
+
mControllerMetricsStats.reportServiceEnablementFailCount();
mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setInitializationProcessingTime(
System.currentTimeMillis() - mSessionProcessingTimeStamp)
.setIsDemoMode(mIsDemoModeEnabled)
+ .setCarrierId(getSatelliteCarrierId())
.reportSessionMetrics();
- mSessionStartTimeStamp = 0;
- mSessionProcessingTimeStamp = 0;
} else {
- /*
- * Unregister Importance Listener for Pointing UI when Satellite is disabled
- */
- synchronized (mNeedsSatellitePointingLock) {
- if (mNeedsSatellitePointing) {
- mPointingAppController.removeListenerForPointingUI();
- }
- }
- moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_TIMEOUT, null);
+ resetSatelliteDisabledRequest();
mControllerMetricsStats.onSatelliteDisabled();
- mWaitingForDisableSatelliteModemResponse = false;
- mWaitingForSatelliteModemOff = false;
mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setTerminationProcessingTime(
System.currentTimeMillis() - mSessionProcessingTimeStamp)
.setSessionDurationSec(calculateSessionDurationTimeSec())
.reportSessionMetrics();
- mSessionStartTimeStamp = 0;
- mSessionProcessingTimeStamp = 0;
}
+ notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite);
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
}
}
@@ -4668,7 +5786,7 @@
return;
}
- if (!isSatelliteEnabled()) {
+ if (!isSatelliteEnabledOrBeingEnabled()) {
plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
+ "disabled");
return;
@@ -4730,102 +5848,213 @@
return true;
}
- private void determineSystemNotification() {
+ private void determineAutoConnectSystemNotification() {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("determineSystemNotification: carrierEnabledSatelliteFlag is disabled");
return;
}
Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier();
+ boolean notificationKeyStatus = mSharedPreferences.getBoolean(
+ SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false);
+ if (DEBUG) {
+ logd("determineAutoConnectSystemNotification: isNtn.first = " + isNtn.first
+ + " IsNotiToShow = " + !notificationKeyStatus + " mIsNotificationShowing = "
+ + mIsNotificationShowing);
+ }
if (isNtn.first) {
- if (mSharedPreferences == null) {
- try {
- mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
- Context.MODE_PRIVATE);
- } catch (Exception e) {
- loge("Cannot get default shared preferences: " + e);
- }
+ if (!notificationKeyStatus && getCarrierRoamingNtnConnectType(isNtn.second)
+ == CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC) {
+ updateSatelliteSystemNotification(isNtn.second,
+ CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC,
+ /*visible*/ true);
}
- if (mSharedPreferences == null) {
- loge("determineSystemNotification: Cannot get default shared preferences");
- return;
- }
- if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) {
- showSatelliteSystemNotification(isNtn.second);
- mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY,
- true).apply();
- }
+ } else if (mIsNotificationShowing
+ && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+ // Dismiss the notification if it is still displaying.
+ dismissSatelliteNotification();
}
}
- private void showSatelliteSystemNotification(int subId) {
- plogd("showSatelliteSystemNotification");
+ private void dismissSatelliteNotification() {
+ mIsNotificationShowing = false;
+ updateSatelliteSystemNotification(-1, -1,/*visible*/ false);
+ }
+
+ /**
+ * Update the system notification to reflect the current satellite status, that's either already
+ * connected OR needs to be manually enabled. The device should only display one notification
+ * at a time to prevent confusing the user, so the same NOTIFICATION_CHANNEL and NOTIFICATION_ID
+ * are used.
+ *
+ * @param subId The subId that provides the satellite connection.
+ * @param carrierRoamingNtnConnectType {@link CarrierConfigManager
+ * .CARRIER_ROAMING_NTN_CONNECT_TYPE}
+ * @param visible {@code true} to show the notification, {@code false} to cancel it.
+ */
+ private void updateSatelliteSystemNotification(int subId,
+ @CARRIER_ROAMING_NTN_CONNECT_TYPE int carrierRoamingNtnConnectType, boolean visible) {
+ plogd("updateSatelliteSystemNotification subId=" + subId + ", carrierRoamingNtnConnectType="
+ + SatelliteServiceUtils.carrierRoamingNtnConnectTypeToString(
+ carrierRoamingNtnConnectType) + ", visible=" + visible);
final NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL,
- NotificationManager.IMPORTANCE_DEFAULT
- );
+ NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setSound(null, null);
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
+ if (notificationManager == null) {
+ ploge("updateSatelliteSystemNotification: notificationManager is null");
+ return;
+ }
+ if (!visible) { // Cancel if any.
+ notificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, UserHandle.ALL);
+ return;
+ }
notificationManager.createNotificationChannel(notificationChannel);
- Notification.Builder notificationBuilder = new Notification.Builder(mContext)
- .setContentTitle(mContext.getResources().getString(
- R.string.satellite_notification_title))
- .setContentText(mContext.getResources().getString(
- R.string.satellite_notification_summary))
+ // if carrierRoamingNtnConnectType is CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
+ int title = R.string.satellite_notification_title;
+ int summary = R.string.satellite_notification_summary;
+ if (carrierRoamingNtnConnectType
+ == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ title = R.string.satellite_notification_manual_title;
+ summary = R.string.satellite_notification_manual_summary;
+ }
+
+ Notification.Builder notificationBuilder = new Notification.Builder(mContext,
+ NOTIFICATION_CHANNEL_ID)
+ .setContentTitle(mContext.getResources().getString(title))
+ .setContentText(mContext.getResources().getString(summary))
.setSmallIcon(R.drawable.ic_android_satellite_24px)
- .setChannelId(NOTIFICATION_CHANNEL_ID)
.setAutoCancel(true)
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color))
.setVisibility(Notification.VISIBILITY_PUBLIC);
- // Add action to invoke message application.
- // getDefaultSmsPackage and getLaunchIntentForPackage are nullable.
- Optional<Intent> nullableIntent = Optional.ofNullable(
- Telephony.Sms.getDefaultSmsPackage(mContext))
- .flatMap(packageName -> {
- PackageManager pm = mContext.getPackageManager();
- return Optional.ofNullable(pm.getLaunchIntentForPackage(packageName));
- });
- // If nullableIntent is null, create new Intent for most common way to invoke message app.
- Intent finalIntent = nullableIntent.map(intent -> {
- // Invoke the home screen of default message application.
- intent.setAction(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- return intent;
- }).orElseGet(() -> {
- ploge("showSatelliteSystemNotification: no default sms package name, Invoke "
- + "default sms compose window instead");
- Intent newIntent = new Intent(Intent.ACTION_VIEW);
- newIntent.setData(Uri.parse("sms:"));
- return newIntent;
- });
-
- PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0,
- finalIntent, PendingIntent.FLAG_IMMUTABLE);
+ // Intent for `Open Messages` [Button 1]
+ Intent openMessageIntent = new Intent();
+ openMessageIntent.setAction(OPEN_MESSAGE_BUTTON);
+ PendingIntent openMessagePendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ openMessageIntent, PendingIntent.FLAG_IMMUTABLE);
Notification.Action actionOpenMessage = new Notification.Action.Builder(0,
mContext.getResources().getString(R.string.satellite_notification_open_message),
- pendingIntentOpenMessage).build();
- notificationBuilder.addAction(actionOpenMessage);
+ openMessagePendingIntent).build();
+ notificationBuilder.addAction(actionOpenMessage); // Handle `Open Messages` button
- // Add action to invoke Satellite setting activity in Settings.
- Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING);
- intentSatelliteSetting.putExtra("sub_id", subId);
- PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0,
- intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE);
-
- Notification.Action actionOpenSatelliteSetting = new Notification.Action.Builder(null,
+ // Button for `How it works` [Button 2]
+ Intent howItWorksIntent = new Intent();
+ howItWorksIntent.setAction(HOW_IT_WORKS_BUTTON);
+ howItWorksIntent.putExtra("SUBID", subId);
+ PendingIntent howItWorksPendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ howItWorksIntent, PendingIntent.FLAG_IMMUTABLE);
+ Notification.Action actionHowItWorks = new Notification.Action.Builder(0,
mContext.getResources().getString(R.string.satellite_notification_how_it_works),
- pendingIntentSatelliteSetting).build();
- notificationBuilder.addAction(actionOpenSatelliteSetting);
+ howItWorksPendingIntent).build();
+ notificationBuilder.addAction(actionHowItWorks); // Handle `How it works` button
+
+ // Intent for clicking the main notification body
+ Intent notificationClickIntent = new Intent(ACTION_NOTIFICATION_CLICK);
+ PendingIntent notificationClickPendingIntent = PendingIntent.getBroadcast(mContext, 0,
+ notificationClickIntent, PendingIntent.FLAG_IMMUTABLE);
+ notificationBuilder.setContentIntent(
+ notificationClickPendingIntent); // Handle notification body click
+
+ // Intent for dismissing/swiping the notification
+ Intent deleteIntent = new Intent(ACTION_NOTIFICATION_DISMISS);
+ PendingIntent deletePendingIntent = PendingIntent.getBroadcast(mContext, 0, deleteIntent,
+ PendingIntent.FLAG_IMMUTABLE);
+ notificationBuilder.setDeleteIntent(
+ deletePendingIntent); // Handle notification swipe/dismiss
notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
notificationBuilder.build(), UserHandle.ALL);
+ // The Intent filter is to receive the above four events.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(OPEN_MESSAGE_BUTTON);
+ filter.addAction(HOW_IT_WORKS_BUTTON);
+ filter.addAction(ACTION_NOTIFICATION_CLICK);
+ filter.addAction(ACTION_NOTIFICATION_DISMISS);
+ mContext.registerReceiver(mNotificationInteractionBroadcastReceiver, filter,
+ Context.RECEIVER_EXPORTED);
+
+ mIsNotificationShowing = true;
mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed();
+ mCarrierRoamingSatelliteControllerStats.reportCarrierId(getSatelliteCarrierId());
+ mSessionMetricsStats.addCountOfSatelliteNotificationDisplayed();
+ }
+
+ private final BroadcastReceiver mNotificationInteractionBroadcastReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent receivedIntent) {
+ String intentAction = receivedIntent.getAction();
+ if (TextUtils.isEmpty(intentAction)) {
+ loge("Received empty action from the notification");
+ return;
+ }
+ if (DBG) {
+ plogd("Notification Broadcast recvd action = "
+ + receivedIntent.getAction());
+ }
+ boolean closeStatusBar = true;
+ switch (intentAction) {
+ case OPEN_MESSAGE_BUTTON -> {
+ // Add action to invoke message application.
+ // getDefaultSmsPackage and getLaunchIntentForPackage are nullable.
+ Optional<Intent> nullableIntent = Optional.ofNullable(
+ Telephony.Sms.getDefaultSmsPackage(context)).flatMap(
+ packageName -> {
+ PackageManager pm = context.getPackageManager();
+ return Optional.ofNullable(
+ pm.getLaunchIntentForPackage(packageName));
+ });
+ // If nullableIntent is null, create new Intent for most common way to
+ // invoke
+ // message app.
+ Intent finalIntent = nullableIntent.map(intent -> {
+ // Invoke the home screen of default message application.
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ return intent;
+ }).orElseGet(() -> {
+ ploge("showSatelliteSystemNotification: no default sms package "
+ + "name, Invoke default sms compose window instead");
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.setData(Uri.parse("sms:"));
+ return newIntent;
+ });
+ context.startActivity(finalIntent);
+ }
+ case HOW_IT_WORKS_BUTTON -> {
+ int subId = receivedIntent.getIntExtra("SUBID", -1);
+ Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING);
+ intentSatelliteSetting.putExtra("sub_id", subId);
+ intentSatelliteSetting.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intentSatelliteSetting);
+
+ }
+ case ACTION_NOTIFICATION_DISMISS -> closeStatusBar = false;
+ }
+ // Note : ACTION_NOTIFICATION_DISMISS is not required to handled
+ dismissNotificationAndUpdatePref(closeStatusBar);
+ }
+ };
+
+ private void dismissNotificationAndUpdatePref(boolean closeStatusBar) {
+ dismissSatelliteNotification();
+ if (closeStatusBar) {
+ // Collapse the status bar once user interact with notification.
+ StatusBarManager statusBarManager = mContext.getSystemService(StatusBarManager.class);
+ if (statusBarManager != null) {
+ statusBarManager.collapsePanels();
+ }
+ }
+ // update the sharedpref only when user interacted with the notification.
+ mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply();
+ mContext.unregisterReceiver(mNotificationInteractionBroadcastReceiver);
}
private void resetCarrierRoamingSatelliteModeParams() {
@@ -4846,8 +6075,15 @@
}
}
+ /**
+ * Read carrier config items for satellite
+ *
+ * @param subId Associated subscription ID
+ * @return PersistableBundle including carrier config values
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@NonNull
- private PersistableBundle getPersistableBundle(int subId) {
+ public PersistableBundle getPersistableBundle(int subId) {
synchronized (mCarrierConfigArrayLock) {
PersistableBundle config = mCarrierConfigArray.get(subId);
if (config == null) {
@@ -4866,15 +6102,61 @@
- mSessionMetricsStats.getSessionTerminationProcessingTimeMillis()) / 1000);
}
- private void notifyEnablementFailedToSatelliteSessionController() {
+ private void notifyEnablementFailedToSatelliteSessionController(boolean enabled) {
if (mSatelliteSessionController != null) {
- mSatelliteSessionController.onSatelliteEnablementFailed();
+ mSatelliteSessionController.onSatelliteEnablementFailed(enabled);
} else {
ploge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController"
+ " is not initialized yet");
}
}
+ private void abortSatelliteEnableRequest(@SatelliteManager.SatelliteResult int resultCode) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (mSatelliteEnabledRequest != null) {
+ plogw("abortSatelliteEnableRequest");
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ resultCode = SATELLITE_RESULT_REQUEST_ABORTED;
+ }
+ mSatelliteEnabledRequest.callback.accept(resultCode);
+ stopWaitForSatelliteEnablingResponseTimer(mSatelliteEnabledRequest);
+ mSatelliteEnabledRequest = null;
+ }
+ }
+ }
+
+ private void abortSatelliteDisableRequest(@SatelliteManager.SatelliteResult int resultCode) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (mSatelliteDisabledRequest != null) {
+ plogd("abortSatelliteDisableRequest");
+ mSatelliteDisabledRequest.callback.accept(resultCode);
+ stopWaitForSatelliteEnablingResponseTimer(mSatelliteDisabledRequest);
+ mSatelliteDisabledRequest = null;
+ }
+ }
+ }
+
+ private void abortSatelliteEnableAttributesUpdateRequest(
+ @SatelliteManager.SatelliteResult int resultCode) {
+ synchronized (mSatelliteEnabledRequestLock) {
+ if (mSatelliteEnableAttributesUpdateRequest != null) {
+ plogd("abortSatelliteEnableAttributesUpdateRequest");
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ resultCode = SATELLITE_RESULT_REQUEST_ABORTED;
+ }
+ mSatelliteEnableAttributesUpdateRequest.callback.accept(resultCode);
+ stopWaitForUpdateSatelliteEnableAttributesResponseTimer(
+ mSatelliteEnableAttributesUpdateRequest);
+ mSatelliteEnableAttributesUpdateRequest = null;
+ }
+ }
+ }
+
+ private void stopWaitForEnableResponseTimers() {
+ plogd("stopWaitForEnableResponseTimers");
+ removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT);
+ }
+
private long getDemoPointingAlignedDurationMillisFromResources() {
long durationMillis = 15000L;
try {
@@ -4909,10 +6191,13 @@
return mDemoPointingNotAlignedDurationMillis;
}
- private boolean getWwanIsInService(ServiceState serviceState) {
+ /** Returns {@code true} if WWAN is in service, else {@code false}.*/
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean getWwanIsInService(@NonNull ServiceState serviceState) {
List<NetworkRegistrationInfo> nriList = serviceState
.getNetworkRegistrationInfoListForTransportType(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
for (NetworkRegistrationInfo nri : nriList) {
if (nri.isInService()) {
logv("getWwanIsInService: return true");
@@ -5033,4 +6318,726 @@
}
return TimeUnit.SECONDS.toMillis(duration);
}
+
+ private long getEvaluateEsosProfilesPrioritizationDurationMillis() {
+ return TimeUnit.MINUTES.toMillis(1);
+ }
+
+ /**
+ * Calculate priority
+ * 1. Active eSOS profiles are higher priority than inactive eSOS profiles.
+ * 2. Carrier Enabled eSOS profile is higher priority than OEM enabled eSOS profile.
+ * 3. Among active carrier eSOS profiles user selected(default SMS SIM) eSOS profile will be
+ * the highest priority.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected void evaluateESOSProfilesPrioritization() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("evaluateESOSProfilesPrioritization: Flag CarrierRoamingNbIotNtn is disabled");
+ return;
+ }
+ boolean isChanged = false;
+ List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ // Key : priority - lower value has higher priority; Value : List<SubscriptionInfo>
+ TreeMap<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new TreeMap<>();
+ plogd("evaluateESOSProfilesPrioritization: allSubInfos.size()=" + allSubInfos.size());
+ synchronized (mSatelliteTokenProvisionedLock) {
+ for (SubscriptionInfo info : allSubInfos) {
+ int subId = info.getSubscriptionId();
+ boolean isActive = info.isActive();
+ boolean isDefaultSmsSubId =
+ mSubscriptionManagerService.getDefaultSmsSubId() == subId;
+ boolean isNtnOnly = info.isOnlyNonTerrestrialNetwork();
+ boolean isESOSSupported = info.isSatelliteESOSSupported();
+ if (!isNtnOnly && !isESOSSupported) {
+ continue;
+ }
+
+ int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
+ : (isESOSSupported && isActive) ? 1
+ : (isNtnOnly) ? 2 : (isESOSSupported) ? 3 : -1;
+ if (keyPriority != -1) {
+ newSubsInfoListPerPriority.computeIfAbsent(keyPriority,
+ k -> new ArrayList<>()).add(info);
+ } else {
+ plogw("evaluateESOSProfilesPrioritization: Got -1 keyPriority for subId="
+ + info.getSubscriptionId());
+ }
+
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(info);
+ String newSubscriberId = subscriberIdPair.first;
+ Optional<String> oldSubscriberId = mSubscriberIdPerSub.entrySet().stream()
+ .filter(entry -> entry.getValue().equals(subId))
+ .map(Map.Entry::getKey).findFirst();
+
+ if (oldSubscriberId.isPresent()
+ && !newSubscriberId.equals(oldSubscriberId.get())) {
+ mSubscriberIdPerSub.remove(oldSubscriberId.get());
+ mProvisionedSubscriberId.remove(oldSubscriberId.get());
+ logd("Old phone number is removed: id = " + subId);
+ isChanged = true;
+ }
+ }
+ }
+ plogd("evaluateESOSProfilesPrioritization: newSubsInfoListPerPriority.size()="
+ + newSubsInfoListPerPriority.size());
+
+ if (!mHasSentBroadcast && newSubsInfoListPerPriority.size() == 0) {
+ logd("evaluateESOSProfilesPrioritization: no satellite subscription available");
+ return;
+ }
+
+ // If priority has changed, send broadcast for provisioned ESOS subs IDs
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority)
+ || isChanged) {
+ mSubsInfoListPerPriority = newSubsInfoListPerPriority;
+ sendBroadCastForProvisionedESOSSubs();
+ mHasSentBroadcast = true;
+ selectBindingSatelliteSubscription();
+ }
+ }
+ }
+
+ // The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
+ // subscriberId is the Imsi prefix 6 digit + phone number.
+ private Pair<String, Integer> getSubscriberIdAndType(SubscriptionInfo info) {
+ String subscriberId = "";
+ @SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
+ SatelliteSubscriberInfo.ICCID;
+ if (info.isSatelliteESOSSupported()) {
+ subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
+ }
+ if (info.isOnlyNonTerrestrialNetwork()) {
+ subscriberId = info.getIccId();
+ }
+ logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
+ + subscriberIdType);
+ return new Pair<>(subscriberId, subscriberIdType);
+ }
+
+ private String getPhoneNumberBasedCarrier(int subId) {
+ SubscriptionInfoInternal internal = mSubscriptionManagerService.getSubscriptionInfoInternal(
+ subId);
+ SubscriptionManager subscriptionManager = mContext.getSystemService(
+ SubscriptionManager.class);
+ if (mInjectSubscriptionManager != null) {
+ logd("getPhoneNumberBasedCarrier: InjectSubscriptionManager");
+ subscriptionManager = mInjectSubscriptionManager;
+ }
+ String phoneNumber = subscriptionManager.getPhoneNumber(subId);
+ if (phoneNumber == null) {
+ logd("getPhoneNumberBasedCarrier: phoneNumber null");
+ return "";
+ }
+ return internal.getImsi() == null ? "" : internal.getImsi().substring(0, 6)
+ + phoneNumber.replaceFirst("^\\+", "");
+ }
+
+ private boolean isPriorityChanged(Map<Integer, List<SubscriptionInfo>> currentMap,
+ Map<Integer, List<SubscriptionInfo>> newMap) {
+ if (currentMap.size() == 0 || currentMap.size() != newMap.size()) {
+ return true;
+ }
+
+ for (Map.Entry<Integer, List<SubscriptionInfo>> entry : currentMap.entrySet()) {
+ List<SubscriptionInfo> currentList = entry.getValue();
+ List<SubscriptionInfo> newList = newMap.get(entry.getKey());
+ if (newList == null || currentList == null || currentList.size() != newList.size()) {
+ return true;
+ }
+ for (int i = 0; i < currentList.size(); i++) {
+ if (currentList.get(i).getSubscriptionId() != newList.get(i).getSubscriptionId()) {
+ logd("isPriorityChanged: cur=" + currentList.get(i) + " , new=" + newList.get(
+ i));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void sendBroadCastForProvisionedESOSSubs() {
+ String packageName = getConfigSatelliteGatewayServicePackage();
+ String className = getConfigSatelliteCarrierRoamingEsosProvisionedClass();
+ if (packageName == null || className == null || packageName.isEmpty()
+ || className.isEmpty()) {
+ logd("sendBroadCastForProvisionedESOSSubs: packageName or className is null or empty.");
+ return;
+ }
+ String action = SatelliteManager.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED;
+
+ Intent intent = new Intent(action);
+ intent.setComponent(new ComponentName(packageName, className));
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
+ logd("sendBroadCastForProvisionedESOSSubs" + intent);
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ protected String getStringFromOverlayConfig(int resourceId) {
+ String name;
+ try {
+ name = mContext.getResources().getString(resourceId);
+ } catch (Resources.NotFoundException ex) {
+ loge("getStringFromOverlayConfig: ex=" + ex);
+ name = null;
+ }
+ return name;
+ }
+
+ /**
+ * Request to get list of prioritized satellite tokens to be used for provision.
+ *
+ * @param result The result receiver, which returns the list of prioritized satellite tokens
+ * to be used for provision if the request is successful or an error code if the request failed.
+ */
+ public void requestSatelliteSubscriberProvisionStatus(@NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ return;
+ }
+ List<SatelliteSubscriberProvisionStatus> list =
+ getPrioritizedSatelliteSubscriberProvisionStatusList();
+ logd("requestSatelliteSubscriberProvisionStatus: " + list);
+ final Bundle bundle = new Bundle();
+ bundle.putParcelableList(SatelliteManager.KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN, list);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+
+ private List<SatelliteSubscriberProvisionStatus>
+ getPrioritizedSatelliteSubscriberProvisionStatusList() {
+ List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
+ synchronized (mSatelliteTokenProvisionedLock) {
+ for (int priority : mSubsInfoListPerPriority.keySet()) {
+ List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
+ if (infoList == null) {
+ logd("getPrioritySatelliteSubscriberProvisionStatusList: no exist this "
+ + "priority " + priority);
+ continue;
+ }
+ for (SubscriptionInfo info : infoList) {
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(info);
+ String subscriberId = subscriberIdPair.first;
+ int carrierId = info.getCarrierId();
+ String apn = getConfigForSubId(info.getSubscriptionId())
+ .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+ logd("getPrioritySatelliteSubscriberProvisionStatusList: subscriberId:"
+ + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
+ if (subscriberId.isEmpty()) {
+ logd("getPrioritySatelliteSubscriberProvisionStatusList: getSubscriberId "
+ + "failed skip this subscriberId.");
+ continue;
+ }
+ SatelliteSubscriberInfo satelliteSubscriberInfo =
+ new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
+ .setCarrierId(carrierId).setNiddApn(apn)
+ .setSubId(info.getSubscriptionId())
+ .setSubscriberIdType(subscriberIdPair.second)
+ .build();
+ boolean provisioned = mProvisionedSubscriberId.getOrDefault(subscriberId,
+ false);
+ logd("getPrioritySatelliteSubscriberProvisionStatusList: "
+ + "satelliteSubscriberInfo=" + satelliteSubscriberInfo
+ + ", provisioned=" + provisioned);
+ list.add(new SatelliteSubscriberProvisionStatus.Builder()
+ .setSatelliteSubscriberInfo(satelliteSubscriberInfo)
+ .setProvisionStatus(provisioned).build());
+ mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId());
+ }
+ }
+ }
+ return list;
+ }
+
+ public int getSelectedSatelliteSubId() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSelectedSatelliteSubId;
+ }
+ }
+
+ private void selectBindingSatelliteSubscription() {
+ if (isSatelliteEnabled() || isSatelliteBeingEnabled()) {
+ plogd("selectBindingSatelliteSubscription: satellite subscription will be selected "
+ + "once the satellite session ends");
+ return;
+ }
+
+ int selectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscribers =
+ getPrioritizedSatelliteSubscriberProvisionStatusList();
+ for (SatelliteSubscriberProvisionStatus status : satelliteSubscribers) {
+ // TODO: need to check if satellite is allowed at current location for the subscription
+ int subId = getSubIdFromSubscriberId(
+ status.getSatelliteSubscriberInfo().getSubscriberId());
+ if (status.getProvisionStatus() && isActiveSubId(subId)) {
+ selectedSubId = subId;
+ break;
+ }
+ }
+
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ && isSatelliteSupportedViaOem()) {
+ selectedSubId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ }
+ mSelectedSatelliteSubId = selectedSubId;
+ setSatellitePhone(selectedSubId);
+ }
+ plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId="
+ + mSelectedSatelliteSubId);
+ }
+
+ private int getSubIdFromSubscriberId(String subscriberId) {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSubscriberIdPerSub.getOrDefault(subscriberId,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+ }
+
+ private boolean isActiveSubId(int subId) {
+ return mSubscriptionManagerService.getSubscriptionInfo(subId).isActive();
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean isSubscriptionProvisioned(int subId) {
+ plogd("isSubscriptionProvisioned: subId=" + subId);
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("isSubscriptionProvisioned: carrierRoamingNbIotNtn flag is disabled");
+ return false;
+ }
+
+ String subscriberId = getSubscriberIdAndType(
+ mSubscriptionManagerService.getSubscriptionInfo(subId)).first;
+ if (subscriberId.isEmpty()) {
+ plogd("isSubscriptionProvisioned: subId=" + subId + " subscriberId is empty.");
+ return false;
+ }
+
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mProvisionedSubscriberId.getOrDefault(subscriberId, false);
+ }
+ }
+
+ /**
+ * Deliver the list of provisioned satellite subscriber ids.
+ *
+ * @param list List of provisioned satellite subscriber ids.
+ * @param result The result receiver that returns whether deliver success or fail.
+ */
+ public void provisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
+ @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ logd("provisionSatellite: carrierRoamingNbIotNtn not support");
+ return;
+ }
+ if (list.isEmpty()) {
+ result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
+ logd("provisionSatellite: SatelliteSubscriberInfo list is empty");
+ return;
+ }
+
+ logd("provisionSatellite:" + list);
+ RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
+ result, true);
+ sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ }
+
+ /**
+ * Deliver the list of deprovisioned satellite subscriber ids.
+ *
+ * @param list List of deprovisioned satellite subscriber ids.
+ * @param result The result receiver that returns whether deliver success or fail.
+ */
+ public void deprovisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
+ @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ logd("deprovisionSatellite: carrierRoamingNbIotNtn not support");
+ return;
+ }
+ if (list.isEmpty()) {
+ result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
+ logd("deprovisionSatellite: SatelliteSubscriberInfo list is empty");
+ return;
+ }
+
+ logd("deprovisionSatellite:" + list);
+ RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
+ result, false);
+ sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void setSatellitePhone(int subId) {
+ synchronized (mSatellitePhoneLock) {
+ mSatellitePhone = SatelliteServiceUtils.getPhone(subId);
+ if (mSatellitePhone == null) {
+ mSatellitePhone = SatelliteServiceUtils.getPhone();
+ }
+ plogd("mSatellitePhone:" + (mSatellitePhone != null) + ", subId=" + subId);
+ int carrierId = mSatellitePhone.getCarrierId();
+ if (carrierId != UNKNOWN_CARRIER_ID) {
+ mControllerMetricsStats.setCarrierId(carrierId);
+ } else {
+ logd("setSatellitePhone: Carrier ID is UNKNOWN_CARRIER_ID");
+ }
+ }
+ }
+
+ /** Return the carrier ID of the binding satellite subscription. */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public int getSatelliteCarrierId() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(
+ mSelectedSatelliteSubId);
+ if (subInfo == null) {
+ logd("getSatelliteCarrierId: returns UNKNOWN_CARRIER_ID");
+ return UNKNOWN_CARRIER_ID;
+ }
+ return subInfo.getCarrierId();
+ }
+ }
+
+ /**
+ * Get whether phone is eligible to connect to carrier roaming non-terrestrial network.
+ *
+ * @param phone phone object
+ * return {@code true} when the subscription is eligible for satellite
+ * communication if all the following conditions are met:
+ * <ul>
+ * <li>Subscription supports P2P satellite messaging which is defined by
+ * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li>
+ * <li>{@link CarrierConfigManager#KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT} set to
+ * {@link CarrierConfigManager#CARRIER_ROAMING_NTN_CONNECT_MANUAL} </li>
+ * <li>The device is in {@link ServiceState#STATE_OUT_OF_SERVICE}, not connected to Wi-Fi. </li>
+ * </ul>
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isCarrierRoamingNtnEligible(@Nullable Phone phone) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("isCarrierRoamingNtnEligible: carrierRoamingNbIotNtn flag is disabled");
+ return false;
+ }
+
+ if (phone == null) {
+ plogd("isCarrierRoamingNtnEligible: phone is null");
+ return false;
+ }
+
+ int subId = phone.getSubId();
+ if (!isSatelliteRoamingP2pSmSSupported(subId)) {
+ plogd("isCarrierRoamingNtnEligible: doesn't support P2P SMS");
+ return false;
+ }
+
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ + "]: satellite is not supported via carrier");
+ return false;
+ }
+
+ if (!isSubscriptionProvisioned(subId)) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ + "]: subscription is not provisioned to use satellite.");
+ return false;
+ }
+
+ if (!isSatelliteServiceSupportedByCarrier(subId,
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ + "]: SMS is not supported by carrier");
+ return false;
+ }
+
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId() + "]: not manual "
+ + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType);
+ return false;
+ }
+
+ if (mOverrideNtnEligibility != null) {
+ // TODO need to send the value from `mOverrideNtnEligibility` or simply true ?
+ return true;
+ }
+
+ if (SatelliteServiceUtils.isCellularAvailable()) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ + "]: cellular is available");
+ return false;
+ }
+
+ synchronized (mIsWifiConnectedLock) {
+ if (mIsWifiConnected) {
+ plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ + "]: Wi-Fi is connected");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean isSatelliteServiceSupportedByCarrier(int subId,
+ @NetworkRegistrationInfo.ServiceType int serviceType) {
+ List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId);
+ for (String satellitePlmn : satellitePlmnList) {
+ if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** return satellite phone */
+ @Nullable
+ public Phone getSatellitePhone() {
+ synchronized (mSatellitePhoneLock) {
+ return mSatellitePhone;
+ }
+ }
+
+ /** Start PointingUI if it is required. */
+ public void startPointingUI() {
+ synchronized (mNeedsSatellitePointingLock) {
+ plogd("startPointingUI: mNeedsSatellitePointing=" + mNeedsSatellitePointing
+ + ", mIsDemoModeEnabled=" + mIsDemoModeEnabled
+ + ", mIsEmergency=" + mIsEmergency);
+ if (mNeedsSatellitePointing) {
+ mPointingAppController.startPointingUI(false /*needFullScreenPointingUI*/,
+ mIsDemoModeEnabled, mIsEmergency);
+ }
+ }
+ }
+
+ private void requestIsSatelliteAllowedForCurrentLocation() {
+ plogd("requestIsSatelliteAllowedForCurrentLocation()");
+ synchronized (mSatellitePhoneLock) {
+ if (mCheckingAccessRestrictionInProgress) {
+ plogd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
+ return;
+ }
+ mCheckingAccessRestrictionInProgress = true;
+ }
+
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ plogd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
+ sendMessage(obtainMessage(
+ EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, result));
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException ex) {
+ plogd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
+ sendMessage(obtainMessage(
+ EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, false));
+ }
+ };
+ requestIsSatelliteCommunicationAllowedForCurrentLocation(callback);
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ @NonNull OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback) {
+ SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
+ if (satelliteManager == null) {
+ ploge("requestIsSatelliteCommunicationAllowedForCurrentLocation: "
+ + "SatelliteManager is null");
+ return;
+ }
+
+ satelliteManager.requestIsCommunicationAllowedForCurrentLocation(
+ this::post, callback);
+ }
+
+ private void handleSatelliteAccessRestrictionCheckingResult(boolean satelliteAllowed) {
+ synchronized (mSatellitePhoneLock) {
+ mCheckingAccessRestrictionInProgress = false;
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("handleSatelliteAccessRestrictionCheckingResult:"
+ + " satelliteAllowed=" + satelliteAllowed
+ + ", isCarrierRoamingNtnEligible=" + eligible
+ + ", mNtnEligibilityHysteresisTimedOut=" + mNtnEligibilityHysteresisTimedOut);
+ if (satelliteAllowed && eligible && mNtnEligibilityHysteresisTimedOut) {
+ updateLastNotifiedNtnEligibilityAndNotify(true);
+ mNtnEligibilityHysteresisTimedOut = false;
+ }
+ }
+ }
+
+ private void handleEventSatelliteRegistrationFailure(int causeCode) {
+ plogd("handleEventSatelliteRegistrationFailure: " + causeCode);
+
+ List<ISatelliteModemStateCallback> deadCallersList = new ArrayList<>();
+ mSatelliteRegistrationFailureListeners.values().forEach(listener -> {
+ try {
+ listener.onRegistrationFailure(causeCode);
+ } catch (RemoteException e) {
+ logd("handleEventSatelliteRegistrationFailure RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSatelliteRegistrationFailureListeners.remove(listener.asBinder());
+ });
+ }
+
+ /**
+ * This API can be used by only CTS to override the cached value for the device overlay config
+ * value :
+ * config_satellite_gateway_service_package and
+ * config_satellite_carrier_roaming_esos_provisioned_class.
+ * These values are set before sending an intent to broadcast there are any change to list of
+ * subscriber informations.
+ *
+ * @param name the name is one of the following that constitute an intent.
+ * component package name, or component class name.
+ * @return {@code true} if the setting is successful, {@code false} otherwise.
+ */
+ public boolean setSatelliteSubscriberIdListChangedIntentComponent(String name) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("setSatelliteSubscriberIdListChangedIntentComponent: carrierRoamingNbIotNtn is "
+ + "disabled");
+ return false;
+ }
+ if (!isMockModemAllowed()) {
+ logd("setSatelliteSubscriberIdListChangedIntentComponent: mock modem is not allowed");
+ return false;
+ }
+ logd("setSatelliteSubscriberIdListChangedIntentComponent:" + name);
+
+ if (name.contains("/")) {
+ mChangeIntentComponent = true;
+ } else {
+ mChangeIntentComponent = false;
+ return true;
+ }
+ boolean result = true;
+ String[] cmdPart = name.split("/");
+ switch (cmdPart[0]) {
+ case "-p": {
+ mConfigSatelliteGatewayServicePackage = cmdPart[1];
+ break;
+ }
+ case "-c": {
+ mConfigSatelliteCarrierRoamingEsosProvisionedClass = cmdPart[1];
+ break;
+ }
+ default:
+ logd("setSatelliteSubscriberIdListChangedIntentComponent: invalid name " + name);
+ result = false;
+ break;
+ }
+ return result;
+ }
+
+ private String getConfigSatelliteGatewayServicePackage() {
+ if (!mChangeIntentComponent) {
+ return getStringFromOverlayConfig(
+ R.string.config_satellite_gateway_service_package);
+ }
+ logd("getConfigSatelliteGatewayServicePackage: " + mConfigSatelliteGatewayServicePackage);
+ return mConfigSatelliteGatewayServicePackage;
+ }
+
+ private String getConfigSatelliteCarrierRoamingEsosProvisionedClass() {
+ if (!mChangeIntentComponent) {
+ return getStringFromOverlayConfig(
+ R.string.config_satellite_carrier_roaming_esos_provisioned_class);
+ }
+ logd("getConfigSatelliteCarrierRoamingEsosProvisionedClass: "
+ + mConfigSatelliteCarrierRoamingEsosProvisionedClass);
+ return mConfigSatelliteCarrierRoamingEsosProvisionedClass;
+ }
+
+ private void registerDefaultSmsSubscriptionChangedBroadcastReceiver() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("registerDefaultSmsSubscriptionChangedBroadcastReceiver: Flag "
+ + "CarrierRoamingNbIotNtn is disabled");
+ return;
+ }
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED);
+ mContext.registerReceiver(mDefaultSmsSubscriptionChangedBroadcastReceiver, intentFilter);
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return mContext.getSystemService(DeviceStateManager.class).getSupportedDeviceStates();
+ }
+
+ FeatureFlags getFeatureFlags() {
+ return mFeatureFlags;
+ }
+
+ private boolean isSatelliteDisabled() {
+ synchronized (mIsSatelliteEnabledLock) {
+ return ((mIsSatelliteEnabled != null) && !mIsSatelliteEnabled);
+ }
+ }
+
+ private boolean shouldStopWaitForEnableResponseTimer(
+ @NonNull RequestSatelliteEnabledArgument argument) {
+ if (argument.enableSatellite) return true;
+ synchronized (mSatelliteEnabledRequestLock) {
+ return !mWaitingForSatelliteModemOff;
+ }
+ }
+
+ /**
+ * Method to override the Carrier roaming Non-terrestrial network eligibility check
+ *
+ * @param state flag to enable or disable the Ntn eligibility check.
+ * @param resetRequired reset overriding the check with adb command.
+ */
+ public boolean overrideCarrierRoamingNtnEligibilityChanged(boolean state,
+ boolean resetRequired) {
+ Log.d(TAG, "overrideCarrierRoamingNtnEligibilityChanged state = " + state
+ + " resetRequired = " + resetRequired);
+ if (resetRequired) {
+ mOverrideNtnEligibility = null;
+ } else {
+ if (mOverrideNtnEligibility == null) {
+ mOverrideNtnEligibility = new AtomicBoolean(state);
+ } else {
+ mOverrideNtnEligibility.set(state);
+ }
+ if (this.mSatellitePhone != null) {
+ updateLastNotifiedNtnEligibilityAndNotify(state);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * This method check for the key KEY_SATELLITE_MAX_DATAGRAM_SIZE in carrier config. If
+ * available it fetches the value and override the same in SatelliteCapabilities. Otherwise it
+ * uses the value in the existed mSatelliteCapabilities.
+ */
+ private void overrideSatelliteCapabilitiesIfApplicable() {
+ synchronized (this.mSatellitePhoneLock) {
+ if (this.mSatellitePhone == null) {
+ return;
+ }
+ }
+ int subId = getSelectedSatelliteSubId();
+ PersistableBundle config = getPersistableBundle(subId);
+ if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE)) {
+ int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE);
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (!(subInfo == null || subInfo.isOnlyNonTerrestrialNetwork())) {
+ this.mSatelliteCapabilities.setMaxBytesPerOutgoingDatagram(datagramSize);
+ }
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index da4c69b..a19f802 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -40,6 +40,7 @@
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteManager.SatelliteException;
+import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
import android.telephony.satellite.stub.INtnSignalStrengthConsumer;
import android.telephony.satellite.stub.ISatellite;
import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
@@ -86,8 +87,6 @@
private boolean mIsBinding;
@Nullable private PersistentLogger mPersistentLogger = null;
- @NonNull private final RegistrantList mSatelliteProvisionStateChangedRegistrants =
- new RegistrantList();
@NonNull private final RegistrantList mSatellitePositionInfoChangedRegistrants =
new RegistrantList();
@NonNull private final RegistrantList mDatagramTransferStateChangedRegistrants =
@@ -103,6 +102,8 @@
new RegistrantList();
@NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants =
new RegistrantList();
+ @NonNull private final RegistrantList mSatelliteRegistrationFailureRegistrants =
+ new RegistrantList();
private class SatelliteListener extends ISatelliteListener.Stub {
@@ -113,11 +114,6 @@
}
@Override
- public void onSatelliteProvisionStateChanged(boolean provisioned) {
- mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned);
- }
-
- @Override
public void onSatelliteDatagramReceived(
android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
if (notifyResultIfExpectedListener()) {
@@ -193,7 +189,7 @@
@Override
public void onRegistrationFailure(int causeCode) {
- // TO-DO notify registrants
+ mSatelliteRegistrationFailureRegistrants.notifyResult(causeCode);
}
private boolean notifyResultIfExpectedListener() {
@@ -403,27 +399,6 @@
}
/**
- * Registers for the satellite provision state changed.
- *
- * @param h Handler for notification message.
- * @param what User-defined message code.
- * @param obj User object.
- */
- public void registerForSatelliteProvisionStateChanged(
- @NonNull Handler h, int what, @Nullable Object obj) {
- mSatelliteProvisionStateChangedRegistrants.add(h, what, obj);
- }
-
- /**
- * Unregisters for the satellite provision state changed.
- *
- * @param h Handler to be removed from the registrant list.
- */
- public void unregisterForSatelliteProvisionStateChanged(@NonNull Handler h) {
- mSatelliteProvisionStateChangedRegistrants.remove(h);
- }
-
- /**
* Registers for satellite position info changed from satellite modem.
*
* @param h Handler for notification message.
@@ -591,6 +566,27 @@
}
/**
+ * Registers for the satellite registration failed.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForSatelliteRegistrationFailure(
+ @NonNull Handler h, int what, @Nullable Object obj) {
+ mSatelliteRegistrationFailureRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for the satellite registration failed.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForSatelliteRegistrationFailure(@NonNull Handler h) {
+ mSatelliteRegistrationFailureRegistrants.remove(h);
+ }
+
+ /**
* Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
@@ -682,17 +678,16 @@
* is enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
* this may also re-enable the cellular modem.
*
- * @param enableSatellite True to enable the satellite modem and false to disable.
- * @param enableDemoMode True to enable demo mode and false to disable.
- * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise.
+ * @param enableAttributes info needed to allow carrier to roam to satellite.
* @param message The Message to send to result of the operation to.
*/
- public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- boolean isEmergency, @NonNull Message message) {
+ public void requestSatelliteEnabled(SatelliteModemEnableRequestAttributes enableAttributes,
+ @NonNull Message message) {
if (mSatelliteService != null) {
try {
- mSatelliteService.requestSatelliteEnabled(enableSatellite, enableDemoMode,
- isEmergency, new IIntegerConsumer.Stub() {
+ mSatelliteService.requestSatelliteEnabled(SatelliteServiceUtils
+ .toSatelliteModemEnableRequestAttributes(enableAttributes),
+ new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
@@ -889,113 +884,6 @@
}
/**
- * Provision the device with a satellite provider.
- * This is needed if the provider allows dynamic registration.
- * Once provisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report true.
- *
- * @param token The token to be used as a unique identifier for provisioning with satellite
- * gateway.
- * @param provisionData Data from the provisioning app that can be used by provisioning server
- * @param message The Message to send to result of the operation to.
- */
- public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData,
- @NonNull Message message) {
- if (mSatelliteService != null) {
- try {
- mSatelliteService.provisionSatelliteService(token, provisionData,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- plogd("provisionSatelliteService: " + error);
- Binder.withCleanCallingIdentity(() ->
- sendMessageWithResult(message, null, error));
- }
- });
- } catch (RemoteException e) {
- ploge("provisionSatelliteService: RemoteException " + e);
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
- }
- } else {
- ploge("provisionSatelliteService: Satellite service is unavailable.");
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
- }
- }
-
- /**
- * Deprovision the device with the satellite provider.
- * This is needed if the provider allows dynamic registration.
- * Once deprovisioned, ISatelliteListener#onSatelliteProvisionStateChanged should report false.
- *
- * @param token The token of the device/subscription to be deprovisioned.
- * @param message The Message to send to result of the operation to.
- */
- public void deprovisionSatelliteService(@NonNull String token, @NonNull Message message) {
- if (mSatelliteService != null) {
- try {
- mSatelliteService.deprovisionSatelliteService(token, new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- plogd("deprovisionSatelliteService: " + error);
- Binder.withCleanCallingIdentity(() ->
- sendMessageWithResult(message, null, error));
- }
- });
- } catch (RemoteException e) {
- ploge("deprovisionSatelliteService: RemoteException " + e);
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
- }
- } else {
- ploge("deprovisionSatelliteService: Satellite service is unavailable.");
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
- }
- }
-
- /**
- * Request to get whether this device is provisioned with a satellite provider.
- *
- * @param message The Message to send to result of the operation to.
- */
- public void requestIsSatelliteProvisioned(@NonNull Message message) {
- if (mSatelliteService != null) {
- try {
- mSatelliteService.requestIsSatelliteProvisioned(new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- plogd("requestIsSatelliteProvisioned: " + error);
- Binder.withCleanCallingIdentity(() ->
- sendMessageWithResult(message, null, error));
- }
- }, new IBooleanConsumer.Stub() {
- @Override
- public void accept(boolean result) {
- // Convert for compatibility with SatelliteResponse
- // TODO: This should just report result instead.
- int[] provisioned = new int[] {result ? 1 : 0};
- plogd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned));
- Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
- message, provisioned, SatelliteManager.SATELLITE_RESULT_SUCCESS));
- }
- });
- } catch (RemoteException e) {
- ploge("requestIsSatelliteProvisioned: RemoteException " + e);
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
- }
- } else {
- ploge("requestIsSatelliteProvisioned: Satellite service is unavailable.");
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
- }
- }
-
- /**
* Poll the pending datagrams to be received over satellite.
* The satellite service should check if there are any pending datagrams to be received over
* satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
@@ -1410,6 +1298,34 @@
}
/**
+ * Provision UUID with a satellite provider.
+ */
+ public void updateSatelliteSubscription(@NonNull String iccId, @NonNull Message message) {
+ if (mSatelliteService != null) {
+ try {
+ mSatelliteService.updateSatelliteSubscription(iccId,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ int error = SatelliteServiceUtils.fromSatelliteError(result);
+ plogd("updateSatelliteSubscription: " + error);
+ Binder.withCleanCallingIdentity(() ->
+ sendMessageWithResult(message, null, error));
+ }
+ });
+ } catch (RemoteException e) {
+ ploge("updateSatelliteSubscription: RemoteException " + e);
+ sendMessageWithResult(message, null,
+ SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
+ }
+ } else {
+ ploge("updateSatelliteSubscription: Satellite service is unavailable.");
+ sendMessageWithResult(message, null,
+ SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
+ }
+ }
+
+ /**
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 0e938c1..50732fa 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -45,19 +45,17 @@
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.telecom.Connection;
-import android.telephony.AccessNetworkConstants;
import android.telephony.DropBoxManagerLoggerBackend;
-import android.telephony.NetworkRegistrationInfo;
import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.RegistrationManager;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
@@ -70,6 +68,9 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SmsApplication;
+import com.android.internal.telephony.TelephonyCountryDetector;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.SatelliteStats;
import java.util.List;
@@ -97,7 +98,11 @@
@NonNull private final Context mContext;
@NonNull
private final SatelliteController mSatelliteController;
+ @NonNull
+ private final TelephonyCountryDetector mCountryDetector;
private ImsManager mImsManager;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
private Connection mEmergencyConnection = null;
private final ISatelliteProvisionStateCallback mISatelliteProvisionStateCallback;
@@ -119,6 +124,8 @@
@Nullable private PersistentLogger mPersistentLogger = null;
+ private boolean mIsTestEmergencyNumber = false;
+
/**
* Create an instance of SatelliteSOSMessageRecommender.
*
@@ -151,6 +158,8 @@
}
mContext = context;
mSatelliteController = satelliteController;
+ mFeatureFlags = mSatelliteController.getFeatureFlags();
+ mCountryDetector = TelephonyCountryDetector.getInstance(context, mFeatureFlags);
mImsManager = imsManager;
mOemEnabledTimeoutMillis =
getOemEnabledEmergencyCallWaitForConnectionTimeoutMillis(context);
@@ -160,6 +169,13 @@
plogd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscriberProvisionStatus) {
+ plogd("onSatelliteSubscriptionProvisionStateChanged: "
+ + satelliteSubscriberProvisionStatus);
+ }
};
}
@@ -199,11 +215,13 @@
* @param connection The connection created by TelephonyConnectionService for the emergency
* call.
*/
- public void onEmergencyCallStarted(@NonNull Connection connection) {
+ public void onEmergencyCallStarted(@NonNull Connection connection,
+ boolean isTestEmergencyNumber) {
if (!isSatelliteSupported()) {
plogd("onEmergencyCallStarted: satellite is not supported");
return;
}
+ mIsTestEmergencyNumber = isTestEmergencyNumber;
if (hasMessages(EVENT_EMERGENCY_CALL_STARTED)) {
logd("onEmergencyCallStarted: Ignoring due to ongoing event:");
@@ -245,6 +263,7 @@
}
private void handleEmergencyCallStartedEvent(@NonNull Connection connection) {
+ plogd("handleEmergencyCallStartedEvent: connection=" + connection);
mSatelliteController.setLastEmergencyCallTime();
if (sendEventDisplayEmergencyMessageForcefully(connection)) {
@@ -266,7 +285,7 @@
private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
if (!provisioned) {
- cleanUpResources();
+ cleanUpResources(false);
}
}
@@ -299,29 +318,31 @@
updateSatelliteViaCarrierAvailability();
boolean isDialerNotified = false;
- if (!isCellularAvailable()
+ boolean isCellularAvailable = SatelliteServiceUtils.isCellularAvailable();
+ if (!isCellularAvailable
&& isSatelliteAllowed()
- && (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
+ && (isSatelliteViaOemAvailable()
+ || isSatelliteConnectedViaCarrierWithinHysteresisTime())
&& shouldTrackCall(mEmergencyConnection.getState())) {
plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
- Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
+ Bundle extras = createExtraBundleForEventDisplayEmergencyMessage(
+ mIsTestEmergencyNumber);
mEmergencyConnection.sendConnectionEvent(
TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
isDialerNotified = true;
}
plogd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
- + ", isCellularAvailable=" + isCellularAvailable()
+ + ", isCellularAvailable=" + isCellularAvailable
+ ", isSatelliteAllowed=" + isSatelliteAllowed()
+ ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
- reportEsosRecommenderDecision(isDialerNotified);
- cleanUpResources();
+ cleanUpResources(isDialerNotified);
}
}
private boolean isSatelliteAllowed() {
synchronized (mLock) {
- if (isSatelliteViaCarrierAvailable()) return true;
+ if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) return true;
return mIsSatelliteAllowedForCurrentLocation;
}
}
@@ -343,7 +364,7 @@
return satelliteProvisioned != null ? satelliteProvisioned : false;
}
- private boolean isSatelliteViaCarrierAvailable() {
+ private boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() {
return mIsSatelliteConnectedViaCarrierWithinHysteresisTime.get();
}
@@ -366,13 +387,12 @@
* we're not tracking. There must be some unexpected things happened in
* TelephonyConnectionService. Thus, we need to clean up the resources.
*/
- cleanUpResources();
+ cleanUpResources(false);
return;
}
if (!shouldTrackCall(state)) {
- reportEsosRecommenderDecision(false);
- cleanUpResources();
+ cleanUpResources(false);
} else {
// Location service will enter emergency mode only when connection state changes to
// STATE_DIALING
@@ -383,7 +403,8 @@
}
}
- private void reportEsosRecommenderDecision(boolean isDialerNotified) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void reportESosRecommenderDecision(boolean isDialerNotified) {
SatelliteStats.getInstance().onSatelliteSosMessageRecommender(
new SatelliteStats.SatelliteSosMessageRecommenderParams.Builder()
.setDisplaySosMessageSent(isDialerNotified)
@@ -393,10 +414,13 @@
.setIsMultiSim(isMultiSim())
.setRecommendingHandoverType(getEmergencyCallToSatelliteHandoverType())
.setIsSatelliteAllowedInCurrentLocation(isSatelliteAllowed())
- .build());
+ .setIsWifiConnected(mCountryDetector.isWifiNetworkConnected())
+ .setCarrierId(mSatelliteController.getSatelliteCarrierId()).build());
}
- private void cleanUpResources() {
+ private void cleanUpResources(boolean isDialerNotified) {
+ plogd("cleanUpResources");
+ reportESosRecommenderDecision(isDialerNotified);
synchronized (mLock) {
stopTimer();
if (mEmergencyConnection != null) {
@@ -407,12 +431,13 @@
mIsTimerTimedOut = false;
mCheckingAccessRestrictionInProgress = false;
mIsSatelliteAllowedForCurrentLocation = false;
+ mIsTestEmergencyNumber = false;
}
}
private void registerForInterestedStateChangedEvents() {
mSatelliteController.registerForSatelliteProvisionStateChanged(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, mISatelliteProvisionStateCallback);
+ mISatelliteProvisionStateCallback);
for (Phone phone : PhoneFactory.getPhones()) {
phone.registerForServiceStateChanged(
this, EVENT_SERVICE_STATE_CHANGED, null);
@@ -432,7 +457,7 @@
private void unregisterForInterestedStateChangedEvents() {
mSatelliteController.unregisterForSatelliteProvisionStateChanged(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, mISatelliteProvisionStateCallback);
+ mISatelliteProvisionStateCallback);
for (Phone phone : PhoneFactory.getPhones()) {
phone.unregisterForServiceStateChanged(this);
}
@@ -450,51 +475,6 @@
}
}
- private boolean isCellularAvailable() {
- for (Phone phone : PhoneFactory.getPhones()) {
- ServiceState serviceState = phone.getServiceState();
- if (serviceState != null) {
- int state = serviceState.getState();
- if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
- || serviceState.isEmergencyOnly())
- && !isSatellitePlmn(phone.getSubId(), serviceState)) {
- logv("isCellularAvailable true");
- return true;
- }
- }
- }
- logv("isCellularAvailable false");
- return false;
- }
-
- private boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
- List<String> satellitePlmnList =
- mSatelliteController.getSatellitePlmnsForCarrier(subId);
- if (satellitePlmnList.isEmpty()) {
- logv("isSatellitePlmn: satellitePlmnList is empty");
- return false;
- }
-
- for (NetworkRegistrationInfo nri :
- serviceState.getNetworkRegistrationInfoListForTransportType(
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
- String registeredPlmn = nri.getRegisteredPlmn();
- String mccmnc = nri.getCellIdentity().getMccString()
- + nri.getCellIdentity().getMncString();
- for (String satellitePlmn : satellitePlmnList) {
- if (TextUtils.equals(satellitePlmn, registeredPlmn)
- || TextUtils.equals(satellitePlmn, mccmnc)) {
- logv("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
- + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
- return true;
- }
- }
- }
-
- logv("isSatellitePlmn: return false");
- return false;
- }
-
/**
* @return {@link ServiceState#STATE_IN_SERVICE} if any subscription is in this state; else
* {@link ServiceState#STATE_EMERGENCY_ONLY} if any subscription is in this state; else
@@ -526,10 +506,11 @@
}
private synchronized void handleStateChangedEventForHysteresisTimer() {
- if (!isCellularAvailable() && mEmergencyConnection != null) {
+ if (!SatelliteServiceUtils.isCellularAvailable() && mEmergencyConnection != null) {
startTimer();
} else {
- logv("handleStateChangedEventForHysteresisTimer stopTimer");
+ plogd("handleStateChangedEventForHysteresisTimer stopTimer, mEmergencyConnection="
+ + mEmergencyConnection);
stopTimer();
}
}
@@ -542,7 +523,7 @@
sendMessageDelayed(obtainMessage(EVENT_TIME_OUT), mTimeoutMillis);
mCountOfTimerStarted++;
mIsTimerTimedOut = false;
- logd("startTimer mCountOfTimerStarted=" + mCountOfTimerStarted);
+ plogd("startTimer mCountOfTimerStarted=" + mCountOfTimerStarted);
}
}
@@ -561,7 +542,7 @@
}
private void selectEmergencyCallWaitForConnectionTimeoutDuration() {
- if (mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) {
+ if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
mTimeoutMillis =
mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis();
} else {
@@ -610,11 +591,13 @@
@Nullable
private static String getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(
- @NonNull Context context) {
+ @NonNull Context context, boolean isTestEmergencyNumber) {
String action;
try {
- action = context.getResources().getString(
- R.string.config_satellite_emergency_handover_intent_action);
+ int actionIntent = isTestEmergencyNumber
+ ? R.string.config_satellite_test_with_esp_replies_intent_action
+ : R.string.config_satellite_emergency_handover_intent_action;
+ action = context.getResources().getString(actionIntent);
} catch (Resources.NotFoundException ex) {
loge("getSatelliteEmergencyHandoverIntentFilterActionFromOverlayConfig: ex=" + ex);
action = null;
@@ -660,15 +643,17 @@
return callback;
}
- @NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage() {
+ @NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage(
+ boolean isTestEmergencyNumber) {
int handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
Pair<String, String> oemSatelliteMessagingApp =
getOemEnabledSatelliteHandoverAppFromOverlayConfig(mContext);
String packageName = oemSatelliteMessagingApp.first;
String className = oemSatelliteMessagingApp.second;
- String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext);
+ String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext,
+ isTestEmergencyNumber);
- if (isSatelliteViaCarrierAvailable()
+ if (isSatelliteConnectedViaCarrierWithinHysteresisTime()
|| isEmergencyCallToSatelliteHandoverTypeT911Enforced()) {
ComponentName defaultSmsAppComponent = getDefaultSmsApp();
handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
@@ -735,7 +720,8 @@
@NonNull Connection connection) {
plogd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
mEmergencyConnection = connection;
- Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
+ Bundle extras = createExtraBundleForEventDisplayEmergencyMessage(
+ /* isTestEmergencyNumber= */ true);
connection.sendConnectionEvent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
mEmergencyConnection = null;
}
@@ -749,8 +735,14 @@
return telephonyManager.isMultiSimEnabled();
}
- private int getEmergencyCallToSatelliteHandoverType() {
- if (isSatelliteViaCarrierAvailable()) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public int getEmergencyCallToSatelliteHandoverType() {
+ if (Flags.carrierRoamingNbIotNtn() && isSatelliteViaOemAvailable()
+ && isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+ int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
+ return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
+ satelliteSubId);
+ } else if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
} else {
return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index d33fd73..3936a7e 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -16,6 +16,9 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.ServiceState.STATE_EMERGENCY_ONLY;
+import static android.telephony.ServiceState.STATE_IN_SERVICE;
+
import static java.util.stream.Collectors.joining;
import android.annotation.NonNull;
@@ -24,8 +27,13 @@
import android.os.AsyncResult;
import android.os.Binder;
import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
+import android.telephony.CellIdentity;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.AntennaPosition;
import android.telephony.satellite.NtnSignalStrength;
@@ -33,9 +41,12 @@
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SatelliteSubscriptionInfo;
import android.telephony.satellite.stub.NTRadioTechnology;
import android.telephony.satellite.stub.SatelliteModemState;
import android.telephony.satellite.stub.SatelliteResult;
+import android.text.TextUtils;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
@@ -57,6 +68,21 @@
private static final String TAG = "SatelliteServiceUtils";
/**
+ * Converts a carrier roaming NTN (Non-Terrestrial Network) connect type constant
+ * from {@link CarrierConfigManager} to string.
+ * @param type The carrier roaming NTN connect type constant.
+ * @return A string representation of the connect type, or "Unknown(type)" if not recognized.
+ */
+ public static String carrierRoamingNtnConnectTypeToString(
+ @CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE int type) {
+ return switch (type) {
+ case CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC -> "AUTOMATIC";
+ case CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL -> "MANUAL";
+ default -> "Unknown(" + type + ")";
+ };
+ }
+
+ /**
* Convert radio technology from service definition to framework definition.
* @param radioTechnology The NTRadioTechnology from the satellite service.
* @return The converted NTRadioTechnology for the framework.
@@ -148,9 +174,9 @@
return SatelliteManager.SATELLITE_MODEM_STATE_OFF;
case SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE:
return SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
- case SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED:
+ case SatelliteModemState.SATELLITE_MODEM_STATE_OUT_OF_SERVICE:
return SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
- case SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED:
+ case SatelliteModemState.SATELLITE_MODEM_STATE_IN_SERVICE:
return SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
default:
loge("Received invalid modem state: " + modemState);
@@ -234,6 +260,41 @@
}
/**
+ * Convert SatelliteSubscriptionInfo from framework definition to service definition.
+ * @param info The SatelliteSubscriptionInfo from the framework.
+ * @return The converted SatelliteSubscriptionInfo for the satellite service.
+ */
+ @NonNull public static android.telephony.satellite.stub
+ .SatelliteSubscriptionInfo toSatelliteSubscriptionInfo(
+ @NonNull SatelliteSubscriptionInfo info
+ ) {
+ android.telephony.satellite.stub.SatelliteSubscriptionInfo converted =
+ new android.telephony.satellite.stub.SatelliteSubscriptionInfo();
+ converted.iccId = info.getIccId();
+ converted.niddApn = info.getNiddApn();
+ return converted;
+ }
+
+ /**
+ * Convert SatelliteModemEnableRequestAttributes from framework definition to service definition
+ * @param attributes The SatelliteModemEnableRequestAttributes from the framework.
+ * @return The converted SatelliteModemEnableRequestAttributes for the satellite service.
+ */
+ @NonNull public static android.telephony.satellite.stub
+ .SatelliteModemEnableRequestAttributes toSatelliteModemEnableRequestAttributes(
+ @NonNull SatelliteModemEnableRequestAttributes attributes
+ ) {
+ android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes converted =
+ new android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes();
+ converted.isEnabled = attributes.isEnabled();
+ converted.isDemoMode = attributes.isDemoMode();
+ converted.isEmergencyMode = attributes.isEmergencyMode();
+ converted.satelliteSubscriptionInfo = toSatelliteSubscriptionInfo(
+ attributes.getSatelliteSubscriptionInfo());
+ return converted;
+ }
+
+ /**
* Get the {@link SatelliteManager.SatelliteResult} from the provided result.
*
* @param ar AsyncResult used to determine the error code.
@@ -282,6 +343,26 @@
}
/**
+ * Get the subscription ID which supports OEM based NTN satellite service.
+ *
+ * @return ID of the subscription that supports OEM-based satellite if any,
+ * return {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} otherwise.
+ */
+ public static int getNtnOnlySubscriptionId(@NonNull Context context) {
+ List<SubscriptionInfo> infoList =
+ SubscriptionManagerService.getInstance().getAllSubInfoList(
+ context.getOpPackageName(), null);
+
+ int subId = infoList.stream()
+ .filter(info -> info.isOnlyNonTerrestrialNetwork())
+ .mapToInt(SubscriptionInfo::getSubscriptionId)
+ .findFirst()
+ .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ logd("getNtnOnlySubscriptionId: subId=" + subId);
+ return subId;
+ }
+
+ /**
* Expected format of the input dictionary bundle is:
* <ul>
* <li>Key: PLMN string.</li>
@@ -327,8 +408,14 @@
@NonNull
public static List<String> mergeStrLists(List<String> strList1, List<String> strList2) {
Set<String> mergedStrSet = new HashSet<>();
- mergedStrSet.addAll(strList1);
- mergedStrSet.addAll(strList2);
+ if (strList1 != null) {
+ mergedStrSet.addAll(strList1);
+ }
+
+ if (strList2 != null) {
+ mergedStrSet.addAll(strList2);
+ }
+
return mergedStrSet.stream().toList();
}
@@ -385,6 +472,76 @@
return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
}
+ /** Return {@code true} if device has cellular coverage, else return {@code false}. */
+ public static boolean isCellularAvailable() {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState != null) {
+ int state = serviceState.getState();
+ if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
+ || serviceState.isEmergencyOnly())
+ && !isSatellitePlmn(phone.getSubId(), serviceState)) {
+ logd("isCellularAvailable true");
+ return true;
+ }
+ }
+ }
+ logd("isCellularAvailable false");
+ return false;
+ }
+
+ /** Check whether device is connected to satellite PLMN */
+ public static boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
+ List<String> satellitePlmnList =
+ SatelliteController.getInstance().getSatellitePlmnsForCarrier(subId);
+ if (satellitePlmnList.isEmpty()) {
+ logd("isSatellitePlmn: satellitePlmnList is empty");
+ return false;
+ }
+
+ for (NetworkRegistrationInfo nri :
+ serviceState.getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
+ String registeredPlmn = nri.getRegisteredPlmn();
+ if (TextUtils.isEmpty(registeredPlmn)) {
+ logd("isSatellitePlmn: registeredPlmn is empty");
+ continue;
+ }
+
+ String mccmnc = getMccMnc(nri);
+ for (String satellitePlmn : satellitePlmnList) {
+ if (TextUtils.equals(satellitePlmn, registeredPlmn)
+ || TextUtils.equals(satellitePlmn, mccmnc)) {
+ logd("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
+ + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
+ return true;
+ }
+ }
+ }
+
+ logd("isSatellitePlmn: return false");
+ return false;
+ }
+
+ /** Get mccmnc string from NetworkRegistrationInfo. */
+ @Nullable
+ public static String getMccMnc(@NonNull NetworkRegistrationInfo nri) {
+ CellIdentity cellIdentity = nri.getCellIdentity();
+ if (cellIdentity == null) {
+ logd("getMccMnc: cellIdentity is null");
+ return null;
+ }
+
+ String mcc = cellIdentity.getMccString();
+ String mnc = cellIdentity.getMncString();
+ if (mcc == null || mnc == null) {
+ logd("getMccMnc: mcc or mnc is null. mcc=" + mcc + " mnc=" + mnc);
+ return null;
+ }
+
+ return mcc + mnc;
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
@@ -392,4 +549,8 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private static void logv(@NonNull String log) {
+ Rlog.v(TAG, log);
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index dde10a0..4138df3 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -16,6 +16,11 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE;
@@ -25,6 +30,13 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_LISTENING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -37,11 +49,12 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.PersistentLogger;
-import android.telephony.Rlog;
+import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.ISatelliteGateway;
@@ -52,10 +65,16 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.DeviceStateMonitor;
import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.android.telephony.Rlog;
import java.util.ArrayList;
import java.util.List;
@@ -106,10 +125,19 @@
protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 6;
private static final int EVENT_SATELLITE_ENABLEMENT_STARTED = 7;
private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8;
-
+ private static final int EVENT_SCREEN_STATE_CHANGED = 9;
+ protected static final int EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT = 10;
+ protected static final int EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT = 11;
+ private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12;
+ private static final int EVENT_SERVICE_STATE_CHANGED = 13;
+ protected static final int EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT = 14;
private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
private static final int REBIND_MULTIPLIER = 2;
+ private static final int DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC = 30;
+ private static final int DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC = 180;
+ private static final int DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC = 600;
+
@NonNull private final ExponentialBackoff mExponentialBackoff;
@NonNull private final Object mLock = new Object();
@Nullable
@@ -118,6 +146,7 @@
@Nullable private SatelliteGatewayServiceConnection mSatelliteGatewayServiceConnection;
private boolean mIsBound;
private boolean mIsBinding;
+ private boolean mIsRegisteredScreenStateChanged = false;
@NonNull private static SatelliteSessionController sInstance;
@@ -137,16 +166,25 @@
private long mSatelliteStayAtListeningFromSendingMillis;
private long mSatelliteStayAtListeningFromReceivingMillis;
private long mSatelliteNbIotInactivityTimeoutMillis;
+ private boolean mIgnoreCellularServiceState = false;
private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners;
@SatelliteManager.SatelliteModemState private int mCurrentState;
+ @SatelliteManager.SatelliteModemState private int mPreviousState;
final boolean mIsSatelliteSupported;
private boolean mIsDemoMode = false;
+ // Interested in screen off, so use default value true
+ boolean mIsScreenOn = true;
+ private boolean mIsDeviceAlignedWithSatellite = false;
+
@GuardedBy("mLock")
@NonNull private boolean mIsDisableCellularModemInProgress = false;
@NonNull private final SatelliteController mSatelliteController;
@NonNull private final DatagramController mDatagramController;
@Nullable private PersistentLogger mPersistentLogger = null;
+ @Nullable private DeviceStateMonitor mDeviceStateMonitor;
+ @NonNull private SessionMetricsStats mSessionMetricsStats;
+ @NonNull private FeatureFlags mFeatureFlags;
/**
* @return The singleton instance of SatelliteSessionController.
@@ -173,12 +211,28 @@
@NonNull FeatureFlags featureFlags,
boolean isSatelliteSupported) {
if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
+ ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> existingListeners = null;
+ boolean existIgnoreCellularServiceState = false;
+ if (sInstance != null) {
+ existingListeners = sInstance.mListeners;
+ existIgnoreCellularServiceState = sInstance.mIgnoreCellularServiceState;
+ sInstance.cleanUpResource();
+ }
+
sInstance = new SatelliteSessionController(
context,
looper,
featureFlags,
isSatelliteSupported,
SatelliteModemInterface.getInstance());
+ if (existingListeners != null) {
+ Log.d(TAG, "make() existingListeners: " + existingListeners.size());
+ sInstance.mListeners.putAll(existingListeners);
+ }
+ if (existIgnoreCellularServiceState) {
+ Log.d(TAG, "make() existIgnoreCellularServiceState is true");
+ sInstance.mIgnoreCellularServiceState = true;
+ }
}
return sInstance;
}
@@ -205,6 +259,7 @@
}
mContext = context;
+ mFeatureFlags = featureFlags;
mSatelliteModemInterface = satelliteModemInterface;
mSatelliteController = SatelliteController.getInstance();
mDatagramController = DatagramController.getInstance();
@@ -215,7 +270,8 @@
getSatelliteNbIotInactivityTimeoutMillis();
mListeners = new ConcurrentHashMap<>();
mIsSendingTriggeredDuringTransferringState = new AtomicBoolean(false);
- mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
+ mPreviousState = SATELLITE_MODEM_STATE_UNKNOWN;
+ mCurrentState = SATELLITE_MODEM_STATE_UNKNOWN;
mIsSatelliteSupported = isSatelliteSupported;
mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY,
REBIND_MULTIPLIER, looper, () -> {
@@ -234,6 +290,27 @@
bindService();
});
+ Phone satellitePhone = mSatelliteController.getSatellitePhone();
+ if (satellitePhone == null) {
+ satellitePhone = SatelliteServiceUtils.getPhone();
+ }
+ mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor();
+ mSessionMetricsStats = SessionMetricsStats.getInstance();
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ // Register to received Cellular service state
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone == null) continue;
+
+ phone.registerForServiceStateChanged(
+ getHandler(), EVENT_SERVICE_STATE_CHANGED, null);
+ if (DBG) {
+ plogd("SatelliteSessionController: registerForServiceStateChanged phoneId "
+ + phone.getPhoneId());
+ }
+ }
+ }
+
addState(mUnavailableState);
addState(mPowerOffState);
addState(mEnablingState);
@@ -257,9 +334,10 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onDatagramTransferStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int sendState,
- @SatelliteManager.SatelliteDatagramTransferState int receiveState) {
+ @SatelliteManager.SatelliteDatagramTransferState int receiveState,
+ @SatelliteManager.DatagramType int datagramType) {
sendMessage(EVENT_DATAGRAM_TRANSFER_STATE_CHANGED,
- new DatagramTransferState(sendState, receiveState));
+ new DatagramTransferState(sendState, receiveState, datagramType));
if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING) {
mIsSendingTriggeredDuringTransferringState.set(true);
}
@@ -290,10 +368,12 @@
/**
* {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
* that the satellite enablement has just failed.
+ *
+ * @param enabled {@code true} if satellite is enabled, {@code false} satellite is disabled.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void onSatelliteEnablementFailed() {
- sendMessage(EVENT_SATELLITE_ENABLEMENT_FAILED);
+ public void onSatelliteEnablementFailed(boolean enabled) {
+ sendMessage(EVENT_SATELLITE_ENABLEMENT_FAILED, enabled);
}
/**
@@ -308,6 +388,35 @@
}
/**
+ * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
+ * that the satellite emergency mode has changed.
+ *
+ * @param isEmergencyMode The satellite emergency mode.
+ */
+ public void onEmergencyModeChanged(boolean isEmergencyMode) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("onEmergencyModeChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ plogd("onEmergencyModeChanged " + isEmergencyMode);
+
+ List<ISatelliteModemStateCallback> toBeRemoved = new ArrayList<>();
+ mListeners.values().forEach(listener -> {
+ try {
+ listener.onEmergencyModeChanged(isEmergencyMode);
+ } catch (RemoteException e) {
+ plogd("onEmergencyModeChanged RemoteException: " + e);
+ toBeRemoved.add(listener);
+ }
+ });
+
+ toBeRemoved.forEach(listener -> {
+ mListeners.remove(listener.asBinder());
+ });
+ }
+
+ /**
* Registers for modem state changed from satellite modem.
*
* @param callback The callback to handle the satellite modem state changed event.
@@ -316,6 +425,9 @@
@NonNull ISatelliteModemStateCallback callback) {
try {
callback.onSatelliteModemStateChanged(mCurrentState);
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ callback.onEmergencyModeChanged(mSatelliteController.getRequestIsEmergency());
+ }
mListeners.put(callback.asBinder(), callback);
} catch (RemoteException ex) {
ploge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex);
@@ -366,6 +478,23 @@
}
/**
+ * This API can be used by only CTS to control ingoring cellular service state event.
+ *
+ * @param enabled Whether to enable boolean config.
+ * @return {@code true} if the value is set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteIgnoreCellularServiceState(boolean enabled) {
+ plogd("setSatelliteIgnoreCellularServiceState : "
+ + "old = " + mIgnoreCellularServiceState + " new : " + enabled);
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return false;
+ }
+
+ mIgnoreCellularServiceState = enabled;
+ return true;
+ }
+
+ /**
* This API can be used by only CTS to update satellite gateway service package name.
*
* @param servicePackageName The package name of the satellite gateway service.
@@ -413,6 +542,31 @@
}
/**
+ * Notify whether the device is aligned with the satellite
+ *
+ * @param isAligned {@code true} Device is aligned with the satellite,
+ * {@code false} otherwise.
+ */
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("setDeviceAlignedWithSatellite: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ mIsDeviceAlignedWithSatellite = isAligned;
+
+ if (mIsDeviceAlignedWithSatellite) {
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
+ } else {
+ if (mCurrentState == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
+ }
+ }
+ }
+
+ /**
* Get whether state machine is in enabling state.
*
* @return {@code true} if state machine is in enabling state and {@code false} otherwise.
@@ -422,6 +576,51 @@
return getCurrentState() == mEnablingState;
}
+ /**
+ * Get whether state machine is in disabling state.
+ *
+ * @return {@code true} if state machine is in disabling state and {@code false} otherwise.
+ */
+ public boolean isInDisablingState() {
+ if (DBG) plogd("isInDisablingState: getCurrentState=" + getCurrentState());
+ return getCurrentState() == mDisablingState;
+ }
+
+ /**
+ * Release all resource.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void cleanUpResource() {
+ plogd("cleanUpResource");
+ mIsDeviceAlignedWithSatellite = false;
+ unregisterForScreenStateChanged();
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ // Register to received Cellular service state
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone == null) continue;
+
+ phone.unregisterForServiceStateChanged(getHandler());
+ if (DBG) {
+ plogd("cleanUpResource: unregisterForServiceStateChanged phoneId "
+ + phone.getPhoneId());
+ }
+ }
+ }
+
+ quitNow();
+ }
+
+ /**
+ * Uses this function to notify that cellular service state has changed
+ *
+ * @param serviceState The state of the cellular service.
+ */
+ @VisibleForTesting
+ public void onCellularServiceStateChanged(ServiceState serviceState) {
+ sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null));
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -429,11 +628,14 @@
private static class DatagramTransferState {
@SatelliteManager.SatelliteDatagramTransferState public int sendState;
@SatelliteManager.SatelliteDatagramTransferState public int receiveState;
+ @SatelliteManager.DatagramType public int datagramType;
DatagramTransferState(@SatelliteManager.SatelliteDatagramTransferState int sendState,
- @SatelliteManager.SatelliteDatagramTransferState int receiveState) {
+ @SatelliteManager.SatelliteDatagramTransferState int receiveState,
+ @SatelliteManager.DatagramType int datagramType) {
this.sendState = sendState;
this.receiveState = receiveState;
+ this.datagramType = datagramType;
}
}
@@ -441,6 +643,7 @@
@Override
public void enter() {
if (DBG) plogd("Entering UnavailableState");
+ mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE);
}
@@ -457,6 +660,9 @@
public void enter() {
if (DBG) plogd("Entering PowerOffState");
+ mSatelliteController.moveSatelliteToOffStateAndCleanUpResources(
+ SATELLITE_RESULT_REQUEST_ABORTED);
+ mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
mIsSendingTriggeredDuringTransferringState.set(false);
synchronized (mLock) {
@@ -466,6 +672,8 @@
stopNbIotInactivityTimer();
DemoSimulator.getInstance().onSatelliteModeOff();
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+
+ unregisterForScreenStateChanged();
}
@Override
@@ -501,8 +709,9 @@
public void enter() {
if (DBG) plogd("Entering EnablingState");
- mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
+ mPreviousState = mCurrentState;
+ mCurrentState = SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
+ notifyStateChangedEvent(SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
}
@Override
@@ -518,10 +727,17 @@
handleSatelliteEnabledStateChanged((boolean) msg.obj);
break;
case EVENT_SATELLITE_ENABLEMENT_FAILED:
- transitionTo(mPowerOffState);
+ if ((boolean) msg.obj) {
+ transitionTo(mPowerOffState);
+ } else {
+ ploge("Unexpected failed disable event in EnablingState");
+ }
break;
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
- deferMessage(msg);
+ handleSatelliteModemStateChanged(msg);
+ break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
break;
}
// Ignore all unexpected events.
@@ -536,6 +752,8 @@
transitionTo(mIdleState);
}
DemoSimulator.getInstance().onSatelliteModeOn();
+
+ registerForScreenStateChanged();
} else {
/*
* During the state transition from ENABLING to NOT_CONNECTED, modem might be
@@ -547,6 +765,15 @@
transitionTo(mPowerOffState);
}
}
+
+ private void handleSatelliteModemStateChanged(@NonNull Message msg) {
+ int state = msg.arg1;
+ if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
+ } else {
+ deferMessage(msg);
+ }
+ }
}
private class DisablingState extends State {
@@ -554,8 +781,11 @@
public void enter() {
if (DBG) plogd("Entering DisablingState");
+ mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE);
+
+ unregisterForScreenStateChanged();
}
@Override
@@ -570,6 +800,32 @@
case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
handleSatelliteEnabledStateChanged((boolean) msg.obj);
break;
+ case EVENT_SATELLITE_ENABLEMENT_FAILED:
+ boolean enablingSatellite = (boolean) msg.obj;
+ if (enablingSatellite) {
+ /* Framework received a disable request when the enable request was in
+ * progress. We need to set the previous state to OFF since the enable has
+ * failed so that when disable fail, we can move to OFF state properly.
+ */
+ mPreviousState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
+ plogd("Enable request has failed. Set mPreviousState to OFF");
+ break;
+ }
+ if (mPreviousState == SATELLITE_MODEM_STATE_CONNECTED
+ || mPreviousState == SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING
+ || mPreviousState == SATELLITE_MODEM_STATE_LISTENING) {
+ transitionTo(mConnectedState);
+ } else if (mPreviousState == SATELLITE_MODEM_STATE_ENABLING_SATELLITE) {
+ transitionTo(mEnablingState);
+ } else if (mPreviousState == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
+ } else {
+ transitionTo(mNotConnectedState);
+ }
+ break;
+ case EVENT_SATELLITE_MODEM_STATE_CHANGED:
+ handleEventSatelliteModemStateChanged(msg);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -577,22 +833,42 @@
private void handleSatelliteEnabledStateChanged(boolean on) {
if (on) {
- plogw("Unexpected power on event while disabling satellite");
+ /* Framework received a disable request when the enable request was in progress.
+ * We need to set the previous state to NOT_CONNECTED since the enable has
+ * succeeded so that when disable fail, we can move to NOT_CONNECTED state properly.
+ */
+ mPreviousState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
+ plogd("Enable request has succeeded. Set mPreviousState to NOT_CONNECTED");
} else {
transitionTo(mPowerOffState);
}
}
+
+ private void handleEventSatelliteModemStateChanged(@NonNull Message msg) {
+ int state = msg.arg1;
+ if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ mPreviousState = state;
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ plogd("Modem OFF state will be processed after getting the confirmation of the"
+ + " disable request");
+ deferMessage(msg);
+ }
+ }
}
private class IdleState extends State {
@Override
public void enter() {
if (DBG) plogd("Entering IdleState");
+ mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
mIsSendingTriggeredDuringTransferringState.set(false);
stopNbIotInactivityTimer();
+
//Enable Cellular Modem scanning
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, null);
+ Message onCompleted =
+ obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
+ mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
}
@@ -613,6 +889,36 @@
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ handleEventScreenStateChanged((AsyncResult) msg.obj);
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ handleEventScreenOffInactivityTimerTimedOut();
+ break;
+ case EVENT_SATELLITE_MODEM_STATE_CHANGED:
+ handleSatelliteModemStateChanged(msg);
+ break;
+ case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
+ if (!mIgnoreCellularServiceState) {
+ handleEventEnableCellularModemWhileSatelliteModeIsOnDone();
+ } else {
+ plogd("IdleState: processing: ignore "
+ + "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE");
+ }
+ break;
+ case EVENT_SERVICE_STATE_CHANGED:
+ if (!mIgnoreCellularServiceState) {
+ AsyncResult ar = (msg.obj != null) ? (AsyncResult) msg.obj : null;
+ if (ar == null || ar.result == null) {
+ plogd("IdleState: processing: can't access ServiceState");
+ } else {
+ ServiceState newServiceState = (ServiceState) ar.result;
+ handleEventServiceStateChanged(newServiceState);
+ }
+ } else {
+ plogd("IdleState: processing: ignore EVENT_SERVICE_STATE_CHANGED");
+ }
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -640,6 +946,61 @@
}
}
+ private void handleEventEnableCellularModemWhileSatelliteModeIsOnDone() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
+ + "carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ ServiceState serviceState = mSatelliteController.getSatellitePhone().getServiceState();
+ if (serviceState == null) {
+ plogd("handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
+ + "can't access ServiceState");
+ return;
+ }
+ handleEventServiceStateChanged(serviceState);
+ }
+
+ private void handleEventServiceStateChanged(ServiceState serviceState) {
+ boolean isInServiceOrEmergency =
+ serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
+ || serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE
+ || serviceState.isEmergencyOnly();
+ if (!isInServiceOrEmergency) {
+ plogd("handleEventServiceStateChanged: is not IN_SERVICE or EMERGENCY_ONLY");
+ return;
+ }
+
+ // In emergency
+ boolean isEmergency = mSatelliteController.getRequestIsEmergency();
+ if (isEmergency) {
+ boolean isEmergencyCommunicationEstablished = (mDatagramController == null)
+ ? false : mDatagramController.isEmergencyCommunicationEstablished();
+ boolean isTurnOffAllowed =
+ mSatelliteController.turnOffSatelliteSessionForEmergencyCall(getSubId());
+ if (isEmergencyCommunicationEstablished || !isTurnOffAllowed) {
+ logd("handleEventServiceStateChanged: "
+ + "can't disable emergency satellite session");
+ return;
+ }
+ }
+
+ mSatelliteController.requestSatelliteEnabled(
+ false /*enableSatellite*/,
+ false /*enableDemoMode*/,
+ isEmergency /*isEmergency*/,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("requestSatelliteEnabled result=" + result);
+ if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ mSessionMetricsStats.addCountOfAutoExitDueToTnNetwork();
+ }
+ }
+ });
+ }
+
private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
@NonNull AsyncResult result) {
synchronized (mLock) {
@@ -656,6 +1017,13 @@
}
}
+ private void handleSatelliteModemStateChanged(@NonNull Message msg) {
+ int state = msg.arg1;
+ if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
+ }
+ }
+
private void disableCellularModemWhileSatelliteModeIsOn() {
synchronized (mLock) {
if (mIsDisableCellularModemInProgress) {
@@ -686,8 +1054,9 @@
public void enter() {
if (DBG) plogd("Entering TransferringState");
stopNbIotInactivityTimer();
- mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ mPreviousState = mCurrentState;
+ mCurrentState = SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
+ notifyStateChangedEvent(SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
}
@Override
@@ -706,6 +1075,12 @@
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ handleEventScreenStateChanged((AsyncResult) msg.obj);
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ handleEventScreenOffInactivityTimerTimedOut();
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -736,6 +1111,8 @@
@SatelliteManager.SatelliteModemState int state) {
if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
transitionTo(mNotConnectedState);
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
}
}
}
@@ -745,11 +1122,12 @@
public void enter() {
if (DBG) plogd("Entering ListeningState");
- mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_LISTENING;
+ mPreviousState = mCurrentState;
+ mCurrentState = SATELLITE_MODEM_STATE_LISTENING;
long timeoutMillis = updateListeningMode(true);
sendMessageDelayed(EVENT_LISTENING_TIMER_TIMEOUT, timeoutMillis);
mIsSendingTriggeredDuringTransferringState.set(false);
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_LISTENING);
+ notifyStateChangedEvent(SATELLITE_MODEM_STATE_LISTENING);
}
@Override
@@ -776,6 +1154,15 @@
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ handleEventScreenStateChanged((AsyncResult) msg.obj);
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ handleEventScreenOffInactivityTimerTimedOut();
+ break;
+ case EVENT_SATELLITE_MODEM_STATE_CHANGED:
+ handleEventSatelliteModemStateChange(msg);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -801,6 +1188,13 @@
transitionTo(mTransferringState);
}
}
+
+ private void handleEventSatelliteModemStateChange(@NonNull Message msg) {
+ int state = msg.arg1;
+ if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
+ }
+ }
}
private class NotConnectedState extends State {
@@ -808,14 +1202,20 @@
public void enter() {
if (DBG) plogd("Entering NotConnectedState");
+ mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
startNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
}
@Override
public void exit() {
if (DBG) plogd("Exiting NotConnectedState");
+
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
}
@Override
@@ -829,6 +1229,22 @@
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
handleEventSatelliteModemStateChanged(msg.arg1);
break;
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("NotConnectedState: processing: P2P_SMS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isEsosInActivityTimerStarted()) {
+ plogd("NotConnectedState: processing: ESOS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
transitionTo(mIdleState);
break;
@@ -838,6 +1254,12 @@
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ handleEventScreenStateChanged((AsyncResult) msg.obj);
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ handleEventScreenOffInactivityTimerTimedOut();
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -845,8 +1267,10 @@
private void handleEventSatelliteModemStateChanged(
@SatelliteManager.SatelliteModemState int state) {
- if (state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) {
+ if (state == SATELLITE_MODEM_STATE_CONNECTED) {
transitionTo(mConnectedState);
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
}
}
@@ -857,13 +1281,29 @@
|| datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT) {
stopNbIotInactivityTimer();
+
+ if (mSatelliteController.getRequestIsEmergency()) {
+ stopEsosInactivityTimer();
+ }
+ stopP2pSmsInactivityTimer();
} else if (datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
&& datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
startNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
} else if (isSending(datagramTransferState.sendState)
|| isReceiving(datagramTransferState.receiveState)) {
- restartNbIotInactivityTimer();
+ stopNbIotInactivityTimer();
+
+ int datagramType = datagramTransferState.datagramType;
+ if (datagramType == DATAGRAM_TYPE_SOS_MESSAGE) {
+ stopEsosInactivityTimer();
+ } else if (datagramType == DATAGRAM_TYPE_SMS) {
+ stopP2pSmsInactivityTimer();
+ } else {
+ plogd("datagram type is not SOS_Message and SMS " + datagramType);
+ }
}
}
}
@@ -873,14 +1313,20 @@
public void enter() {
if (DBG) plogd("Entering ConnectedState");
- mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mPreviousState = mCurrentState;
+ mCurrentState = SATELLITE_MODEM_STATE_CONNECTED;
+ notifyStateChangedEvent(SATELLITE_MODEM_STATE_CONNECTED);
startNbIotInactivityTimer();
+ evaluateStartingEsosInactivityTimer();
+ evaluateStartingP2pSmsInactivityTimer();
}
@Override
public void exit() {
if (DBG) plogd("Exiting ConnectedState");
+
+ stopEsosInactivityTimer();
+ stopP2pSmsInactivityTimer();
}
@Override
@@ -903,6 +1349,28 @@
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ handleEventScreenStateChanged((AsyncResult) msg.obj);
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ handleEventScreenOffInactivityTimerTimedOut();
+ break;
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("ConnectedState: processing: P2P_SMS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ if (isEsosInActivityTimerStarted()) {
+ plogd("ConnectedState: processing: ESOS inactivity timer running "
+ + "can not move to IDLE");
+ } else {
+ transitionTo(mIdleState);
+ }
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -912,6 +1380,8 @@
@SatelliteManager.SatelliteModemState int state) {
if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED) {
transitionTo(mNotConnectedState);
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ transitionTo(mPowerOffState);
}
}
@@ -955,6 +1425,24 @@
case EVENT_SATELLITE_ENABLEMENT_FAILED:
whatString = "EVENT_SATELLITE_ENABLEMENT_FAILED";
break;
+ case EVENT_SCREEN_STATE_CHANGED:
+ whatString = "EVENT_SCREEN_STATE_CHANGED";
+ break;
+ case EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT:
+ whatString = "EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT";
+ break;
+ case EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT:
+ whatString = "EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT";
+ break;
+ case EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT:
+ whatString = "EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT";
+ break;
+ case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
+ whatString = "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE";
+ break;
+ case EVENT_SERVICE_STATE_CHANGED:
+ whatString = "EVENT_SERVICE_STATE_CHANGED";
+ break;
default:
whatString = "UNKNOWN EVENT " + what;
}
@@ -969,6 +1457,10 @@
}
}
+ private int getSubId() {
+ return mSatelliteController.getSelectedSatelliteSubId();
+ }
+
private void notifyStateChangedEvent(@SatelliteManager.SatelliteModemState int state) {
mDatagramController.onSatelliteModemStateChanged(state);
@@ -1074,6 +1566,7 @@
mSatelliteGatewayServiceConnection = null;
}
}
+
private class SatelliteGatewayServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -1114,6 +1607,226 @@
}
}
+ private void registerForScreenStateChanged() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "registerForScreenStateChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (!mSatelliteController.isInCarrierRoamingNbIotNtn()) {
+ logd("registerScreenOnOffChanged: device is not in CarrierRoamingNbIotNtn");
+ return;
+ }
+
+ if (mSatelliteController.getRequestIsEmergency()) {
+ logd("registerScreenOnOffChanged: not register, device is in Emergency mode");
+ // screen on/off timer is available in not emergency mode
+ return;
+ }
+
+ if (!mIsRegisteredScreenStateChanged && mDeviceStateMonitor != null) {
+ mDeviceStateMonitor.registerForScreenStateChanged(
+ getHandler(), EVENT_SCREEN_STATE_CHANGED, null);
+
+ mIsRegisteredScreenStateChanged = true;
+ plogd("registerForScreenStateChanged: registered");
+ } else {
+ plogw("registerForScreenStateChanged: skip register, mIsRegisteredScreenStateChanged="
+ + mIsRegisteredScreenStateChanged + ","
+ + " mDeviceStateMonitor=" + (mDeviceStateMonitor != null));
+ }
+ }
+
+ private void unregisterForScreenStateChanged() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "unregisterForScreenStateChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (mIsRegisteredScreenStateChanged && mDeviceStateMonitor != null) {
+ mDeviceStateMonitor.unregisterForScreenStateChanged(getHandler());
+ removeMessages(EVENT_SCREEN_STATE_CHANGED);
+ removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+
+ removeDeferredMessages(EVENT_SCREEN_STATE_CHANGED);
+ removeDeferredMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+
+ mIsRegisteredScreenStateChanged = false;
+ plogd("unregisterForScreenStateChanged: unregistered");
+ }
+ }
+
+ private void handleEventScreenStateChanged(AsyncResult asyncResult) {
+ if (asyncResult == null) {
+ ploge("handleEventScreenStateChanged: asyncResult is null");
+ return;
+ }
+
+ boolean screenOn = (boolean) asyncResult.result;
+ if (mIsScreenOn == screenOn) {
+ if (DBG) plogd("handleEventScreenStateChanged: screen state is not changed");
+ return;
+ }
+ mIsScreenOn = screenOn;
+
+ if (!screenOn) {
+ // Screen off, start timer
+ int timeoutMillis = getScreenOffInactivityTimeoutDurationSec() * 1000;
+ sendMessageDelayed(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT, timeoutMillis);
+
+ plogd("handleEventScreenStateChanged: start timer " + timeoutMillis);
+ } else {
+ // Screen on, stop timer
+ removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+
+ plogd("handleEventScreenStateChanged: stop timer");
+ }
+ }
+
+ private int getScreenOffInactivityTimeoutDurationSec() {
+ PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
+
+ return config.getInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ }
+
+ private int getEsosInactivityTimeoutDurationSec() {
+ PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
+
+ return config.getInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ DEFAULT_ESOS_INACTIVITY_TIMEOUT_SEC);
+ }
+
+ private void evaluateStartingEsosInactivityTimer() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (isEsosInActivityTimerStarted()) {
+ plogd("isEsosInActivityTimerStarted: "
+ + "ESOS inactivity timer already started");
+ return;
+ }
+
+ int subId = getSubId();
+ if (!mSatelliteController.isSatelliteEsosSupported(subId)) {
+ plogd("evaluateStartingEsosInactivityTimer: ESOS is not supported");
+ return;
+ }
+
+ if (!mSatelliteController.getRequestIsEmergency()) {
+ plogd("evaluateStartingEsosInactivityTimer: request is not emergency");
+ return;
+ }
+
+ if (mIsDeviceAlignedWithSatellite) {
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start ESOS inactivity timer due to device aligned satellite");
+ return;
+ }
+
+ int timeOutMillis = getEsosInactivityTimeoutDurationSec() * 1000;
+ DatagramController datagramController = DatagramController.getInstance();
+ if (datagramController.isSendingInIdleState()
+ && datagramController.isPollingInIdleState()) {
+ sendMessageDelayed(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
+ plogd("evaluateStartingEsosInactivityTimer: start ESOS inactivity timer "
+ + timeOutMillis);
+ } else {
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start ESOS inactivity timer");
+ }
+ }
+
+ private void stopEsosInactivityTimer() {
+ if (isEsosInActivityTimerStarted()) {
+ removeMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT);
+ plogd("stopEsosInactivityTimer: ESOS inactivity timer stopped");
+ }
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isEsosInActivityTimerStarted() {
+ return hasMessages(EVENT_ESOS_INACTIVITY_TIMER_TIMED_OUT);
+ }
+
+ private int getP2pSmsInactivityTimeoutDurationSec() {
+ PersistableBundle config = mSatelliteController.getPersistableBundle(getSubId());
+
+ return config.getInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ DEFAULT_P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ }
+
+ private void evaluateStartingP2pSmsInactivityTimer() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ + "carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (isP2pSmsInActivityTimerStarted()) {
+ plogd("isEsosInActivityTimerStarted: "
+ + "P2P_SMS inactivity timer already started");
+ return;
+ }
+
+ int subId = getSubId();
+ if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) {
+ plogd("evaluateStartingEsosInactivityTimer: P2P_SMS is not supported");
+ return;
+ }
+
+ if (mIsDeviceAlignedWithSatellite) {
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start P2P_SMS inactivity timer due to device aligned satellite");
+ return;
+ }
+
+ int timeOutMillis = getP2pSmsInactivityTimeoutDurationSec() * 1000;
+ DatagramController datagramController = DatagramController.getInstance();
+ if (datagramController.isSendingInIdleState()
+ && datagramController.isPollingInIdleState()) {
+ sendMessageDelayed(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
+ plogd("evaluateStartingEsosInactivityTimer: start P2P_SMS inactivity timer "
+ + timeOutMillis);
+ } else {
+ plogd("evaluateStartingEsosInactivityTimer: "
+ + "can't start P2P_SMS inactivity timer");
+ }
+ }
+
+ private void stopP2pSmsInactivityTimer() {
+ if (isP2pSmsInActivityTimerStarted()) {
+ removeMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT);
+ plogd("stopP2pSmsInactivityTimer: P2P_SMS inactivity timer stopped");
+ }
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isP2pSmsInActivityTimerStarted() {
+ return hasMessages(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT);
+ }
+
+ private void handleEventScreenOffInactivityTimerTimedOut() {
+ plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite");
+
+ mSatelliteController.requestSatelliteEnabled(
+ false /*enableSatellite*/,
+ false /*enableDemoMode*/,
+ mSatelliteController.getRequestIsEmergency() /*isEmergency*/,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("requestSatelliteEnabled result=" + result);
+ if (result == SATELLITE_RESULT_SUCCESS) {
+ mSessionMetricsStats.addCountOfAutoExitDueToScreenOff();
+ }
+ }
+ });
+ }
+
private boolean isMockModemAllowed() {
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
@@ -1152,6 +1865,12 @@
}
private void startNbIotInactivityTimer() {
+ if (!isSatelliteEnabledForNtnOnlySubscription()) {
+ plogd("startNbIotInactivityTimer: Can't start timer "
+ + "because satellite was not enabled for OEM based NB IOT");
+ return;
+ }
+
if (isNbIotInactivityTimerStarted()) {
plogd("NB IOT inactivity timer is already started");
return;
@@ -1174,6 +1893,18 @@
return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
}
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean isSatelliteEnabledForNtnOnlySubscription() {
+ if (SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext)
+ != getSubId()) {
+ plogd("isSatelliteEnabledForOemBasedNbIot: highest priority satellite subscription "
+ + "is not NTN-only subscription");
+ return false;
+ }
+
+ return true;
+ }
+
private boolean isSatellitePersistentLoggingEnabled(
@NonNull Context context, @NonNull FeatureFlags featureFlags) {
if (featureFlags.satellitePersistentLogging()) {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java
index 13ba709..4333253 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java
@@ -15,9 +15,12 @@
*/
package com.android.internal.telephony.satellite.metrics;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static com.android.internal.telephony.satellite.SatelliteConstants.ACCESS_CONTROL_TYPE_UNKNOWN;
import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_UNKNOWN;
+import static com.android.internal.telephony.satellite.SatelliteConstants.TRIGGERING_EVENT_UNKNOWN;
import android.annotation.NonNull;
import android.telephony.satellite.SatelliteManager;
@@ -42,6 +45,8 @@
private @SatelliteManager.SatelliteResult int mResultCode;
private String[] mCountryCodes;
private @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+ private int mCarrierId;
+ private @SatelliteConstants.TriggeringEvent int mTriggeringEvent;
private AccessControllerMetricsStats() {
initializeAccessControllerMetricsParam();
}
@@ -61,7 +66,7 @@
return sInstance;
}
private void initializeAccessControllerMetricsParam() {
- mAccessControlType = SatelliteConstants.ACCESS_CONTROL_TYPE_UNKNOWN;
+ mAccessControlType = ACCESS_CONTROL_TYPE_UNKNOWN;
mLocationQueryTimeMillis = 0;
mOnDeviceLookupTimeMillis = 0;
mTotalCheckingTimeMillis = 0;
@@ -70,6 +75,8 @@
mResultCode = SATELLITE_RESULT_SUCCESS;
mCountryCodes = new String[0];
mConfigDataSource = CONFIG_DATA_SOURCE_UNKNOWN;
+ mCarrierId = UNKNOWN_CARRIER_ID;
+ mTriggeringEvent = TRIGGERING_EVENT_UNKNOWN;
}
/**
* Sets the Access Control Type for current satellite enablement.
@@ -161,6 +168,26 @@
logd("setConfigDataSource: config data source = " + mConfigDataSource);
return this;
}
+ /**
+ * Sets the carrier id for NTN satellite service.
+ * @param carrierId Carrier ID of currently available NTN Satellite Network.
+ */
+ public AccessControllerMetricsStats setCarrierId(int carrierId) {
+ mCarrierId = carrierId;
+ logd("setCarrierId: Carrier ID = " + mCarrierId);
+ return this;
+ }
+ /**
+ * Sets the triggering event for satellite access controller operation.
+ * @param triggeringEvent triggering event.
+ */
+ public AccessControllerMetricsStats setTriggeringEvent(
+ @SatelliteConstants.TriggeringEvent int triggeringEvent) {
+ mTriggeringEvent = triggeringEvent;
+ logd("setTriggeringEvent: triggering event = " + mTriggeringEvent);
+ return this;
+ }
+
/** Report the access controller metrics atoms to PersistAtomsStorage in telephony. */
public void reportAccessControllerMetrics() {
SatelliteStats.SatelliteAccessControllerParams accessControllerParams =
@@ -174,6 +201,8 @@
.setResult(mResultCode)
.setCountryCodes(mCountryCodes)
.setConfigDatasource(mConfigDataSource)
+ .setCarrierId(mCarrierId)
+ .setTriggeringEvent(mTriggeringEvent)
.build();
logd("reportAccessControllerMetrics: " + accessControllerParams.toString());
SatelliteStats.getInstance().onSatelliteAccessControllerMetrics(accessControllerParams);
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
index 9524b75..e97d234 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
@@ -80,6 +80,22 @@
.build());
}
+ /** Capture the NB-IoT NTN carrier ID */
+ public void reportCarrierId(int carrierId) {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCarrierId(carrierId)
+ .build());
+ }
+
+ /** Capture whether the device is satellite entitled or not */
+ public void reportIsDeviceEntitled(boolean isDeviceEntitled) {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setIsDeviceEntitled(isDeviceEntitled)
+ .build());
+ }
+
private static void logd(@NonNull String log) {
Log.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
index 7dff2e6..56c3431 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
@@ -141,14 +141,13 @@
builder.setCountOfDemoModeOutgoingDatagramSuccess(ADD_COUNT);
} else {
builder.setCountOfOutgoingDatagramSuccess(ADD_COUNT);
- }
-
- if (SatelliteServiceUtils.isSosMessage(datagramType)) {
- builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
- builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+ }
}
SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
@@ -166,14 +165,13 @@
builder.setCountOfDemoModeOutgoingDatagramFail(ADD_COUNT);
} else {
builder.setCountOfOutgoingDatagramFail(ADD_COUNT);
- }
-
- if (SatelliteServiceUtils.isSosMessage(datagramType)) {
- builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
- builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+ }
}
SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
@@ -371,6 +369,54 @@
}
}
+ /** Capture the latest provisioned state for satellite service */
+ @VisibleForTesting
+ public void setIsProvisioned(boolean isProvisioned) {
+ logd("setIsProvisioned:" + isProvisioned);
+ mSatelliteStats.onSatelliteControllerMetrics(
+ new SatelliteStats.SatelliteControllerParams.Builder()
+ .setIsProvisioned(isProvisioned)
+ .build());
+ }
+
+ /** Capture the NB-IoT NTN carrier ID */
+ @VisibleForTesting
+ public void setCarrierId(int carrierId) {
+ logd("setCarrierId:" + carrierId);
+ mSatelliteStats.onSatelliteControllerMetrics(
+ new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCarrierId(carrierId)
+ .build());
+ }
+
+ /**
+ * Report a counter when allowed state has changed.
+ */
+ public void reportAllowedStateChanged() {
+ logd("reportAllowedStateChanged:");
+ mSatelliteStats.onSatelliteControllerMetrics(
+ new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSatelliteAllowedStateChangedEvents(ADD_COUNT)
+ .build());
+ }
+
+ /**
+ * Report a counter when location query was successful or failed.
+ */
+ public void reportLocationQuerySuccessful(boolean result) {
+ SatelliteStats.SatelliteControllerParams.Builder builder;
+ if (result) {
+ builder = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSuccessfulLocationQueries(ADD_COUNT);
+ } else {
+ builder = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfFailedLocationQueries(ADD_COUNT);
+ }
+ SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
+ logd("reportLocationQuerySuccessful:" + controllerParam);
+ mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
+ }
+
/** Receives the battery status whether it is in charging or not, update interval is 60 sec. */
private final BroadcastReceiver mBatteryStatusReceiver = new BroadcastReceiver() {
private long mLastUpdatedTime = 0;
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
index 0647231..73be042 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.satellite.metrics;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+
import android.annotation.NonNull;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
@@ -37,6 +39,7 @@
private int mProvisioningStartTimeSec;
private boolean mIsProvisionRequest;
private boolean mIsCanceled;
+ private int mCarrierId;
private ProvisionMetricsStats() {
initializeProvisionParams();
@@ -80,6 +83,12 @@
return this;
}
+ /** Sets the Carrier of NTN satellite */
+ public ProvisionMetricsStats setCarrierId(int carrierId) {
+ mCarrierId = carrierId;
+ return this;
+ }
+
/** Report the provision metrics atoms to PersistAtomsStorage in telephony */
public void reportProvisionMetrics() {
SatelliteStats.SatelliteProvisionParams provisionParams =
@@ -89,9 +98,10 @@
(System.currentTimeMillis() / 1000) - mProvisioningStartTimeSec)
.setIsProvisionRequest(mIsProvisionRequest)
.setIsCanceled(mIsCanceled)
+ .setCarrierId(mCarrierId)
.build();
SatelliteStats.getInstance().onSatelliteProvisionMetrics(provisionParams);
- logd("reportProvisionMetrics: " + provisionParams.toString());
+ logd("reportProvisionMetrics: " + provisionParams);
initializeProvisionParams();
}
@@ -100,6 +110,7 @@
mProvisioningStartTimeSec = INVALID_TIME;
mIsProvisionRequest = false;
mIsCanceled = false;
+ mCarrierId = UNKNOWN_CARRIER_ID;
}
private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
index 65181c0..a234378 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.satellite.metrics;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
@@ -52,6 +53,10 @@
private int mCountOfIncomingDatagramFailed;
private boolean mIsDemoMode;
private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
+ private int mCarrierId;
+ private int mCountOfSatelliteNotificationDisplayed;
+ private int mCountOfAutoExitDueToScreenOff;
+ private int mCountOfAutoExitDueToTnNetwork;
private SessionMetricsStats() {
initializeSessionMetricsParam();
@@ -213,6 +218,35 @@
return this;
}
+ /** Sets the Carrier ID of this NTN session. */
+ public SessionMetricsStats setCarrierId(int carrierId) {
+ mCarrierId = carrierId;
+ logd("setCarrierId(" + carrierId + ")");
+ return this;
+ }
+
+ /** Increase the count of Satellite Notification Display. */
+ public SessionMetricsStats addCountOfSatelliteNotificationDisplayed() {
+ mCountOfSatelliteNotificationDisplayed++;
+ logd("addCountOfSatelliteNotificationDisplayed: current count="
+ + mCountOfSatelliteNotificationDisplayed);
+ return this;
+ }
+
+ /** Increase the count of auto exit from P2P satellite messaging due to screen off. */
+ public SessionMetricsStats addCountOfAutoExitDueToScreenOff() {
+ mCountOfAutoExitDueToScreenOff++;
+ logd("addCountOfAutoExitDueToScreenOff: current count=" + mCountOfAutoExitDueToScreenOff);
+ return this;
+ }
+
+ /** Increase the count of auto exit from P2P satellite messaging due to scan TN network. */
+ public SessionMetricsStats addCountOfAutoExitDueToTnNetwork() {
+ mCountOfAutoExitDueToTnNetwork++;
+ logd("addCountOfAutoExitDueToTnNetwork: current count=" + mCountOfAutoExitDueToTnNetwork);
+ return this;
+ }
+
/** Report the session metrics atoms to PersistAtomsStorage in telephony. */
public void reportSessionMetrics() {
SatelliteStats.SatelliteSessionParams sessionParams =
@@ -229,6 +263,11 @@
.setCountOfIncomingDatagramFailed(mCountOfIncomingDatagramFailed)
.setIsDemoMode(mIsDemoMode)
.setMaxNtnSignalStrengthLevel(mMaxNtnSignalStrengthLevel)
+ .setCarrierId(mCarrierId)
+ .setCountOfSatelliteNotificationDisplayed(
+ mCountOfSatelliteNotificationDisplayed)
+ .setCountOfAutoExitDueToScreenOff(mCountOfAutoExitDueToScreenOff)
+ .setCountOfAutoExitDueToTnNetwork(mCountOfAutoExitDueToTnNetwork)
.build();
logd("reportSessionMetrics: " + sessionParams.toString());
SatelliteStats.getInstance().onSatelliteSessionMetrics(sessionParams);
@@ -277,6 +316,10 @@
mCountOfIncomingDatagramFailed = 0;
mIsDemoMode = false;
mMaxNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE;
+ mCarrierId = UNKNOWN_CARRIER_ID;
+ mCountOfSatelliteNotificationDisplayed = 0;
+ mCountOfAutoExitDueToScreenOff = 0;
+ mCountOfAutoExitDueToTnNetwork = 0;
}
private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 7596754..9d62972 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -280,7 +280,7 @@
SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
SubscriptionInfoInternal::getSatelliteAttachEnabledForCarrier),
new AbstractMap.SimpleImmutableEntry<>(
- SimInfo.COLUMN_IS_NTN,
+ SimInfo.COLUMN_IS_ONLY_NTN,
SubscriptionInfoInternal::getOnlyNonTerrestrialNetwork),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SERVICE_CAPABILITIES,
@@ -293,7 +293,13 @@
SubscriptionInfoInternal::getSatelliteEntitlementStatus),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
- SubscriptionInfoInternal::getSatelliteEntitlementPlmns)
+ SubscriptionInfoInternal::getSatelliteEntitlementPlmns),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
+ SubscriptionInfoInternal::getSatelliteESOSSupported),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ SubscriptionInfoInternal::getIsSatelliteProvisionedForNonIpDatagram)
);
/**
@@ -423,7 +429,7 @@
SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
SubscriptionDatabaseManager::setSatelliteAttachEnabledForCarrier),
new AbstractMap.SimpleImmutableEntry<>(
- SimInfo.COLUMN_IS_NTN,
+ SimInfo.COLUMN_IS_ONLY_NTN,
SubscriptionDatabaseManager::setNtn),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SERVICE_CAPABILITIES,
@@ -433,7 +439,13 @@
SubscriptionDatabaseManager::setTransferStatus),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS,
- SubscriptionDatabaseManager::setSatelliteEntitlementStatus)
+ SubscriptionDatabaseManager::setSatelliteEntitlementStatus),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
+ SubscriptionDatabaseManager::setSatelliteESOSSupported),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ SubscriptionDatabaseManager::setIsSatelliteProvisionedForNonIpDatagram)
);
/**
@@ -2063,7 +2075,7 @@
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
return;
}
- writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_NTN, isNtn,
+ writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_ONLY_NTN, isNtn,
SubscriptionInfoInternal.Builder::setOnlyNonTerrestrialNetwork);
}
@@ -2109,9 +2121,6 @@
* @param capabilities Service capabilities bitmasks
*/
public void setServiceCapabilities(int subId, int capabilities) {
- if (!mFeatureFlags.dataOnlyCellularService()) {
- return;
- }
writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_SERVICE_CAPABILITIES,
capabilities, SubscriptionInfoInternal.Builder::setServiceCapabilities);
}
@@ -2162,6 +2171,41 @@
}
/**
+ * Set whether the carrier roaming to satellite is using ESOS for emergency messaging.
+ *
+ * @param subId Subscription id.
+ * @param isSatelliteESOSSupported whether the carrier roaming to satellite is using ESOS for
+ * emergency messaging.
+ * @throws IllegalArgumentException if the subscription does not exist.
+ */
+ public void setSatelliteESOSSupported(int subId, int isSatelliteESOSSupported) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+ writeDatabaseAndCacheHelper(subId,
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, isSatelliteESOSSupported,
+ SubscriptionInfoInternal.Builder::setSatelliteESOSSupported);
+ }
+
+ /**
+ * Set whether the subscription is provisioned for OEM-enabled or carrier roaming NB-IOT
+ * satellite service.
+ *
+ * @param subId Subscription ID.
+ * @param isSatelliteProvisionedForNonIpDatagram {@code 1} if it is provisioned for OEM-enabled
+ * or carrier roaming NB-IOT satellite service. {@code 0} otherwise.
+ *
+ * @throws IllegalArgumentException if the subscription does not exist.
+ */
+ public void setIsSatelliteProvisionedForNonIpDatagram(int subId,
+ int isSatelliteProvisionedForNonIpDatagram) {
+ writeDatabaseAndCacheHelper(subId,
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ isSatelliteProvisionedForNonIpDatagram,
+ SubscriptionInfoInternal.Builder::setIsSatelliteProvisionedForNonIpDatagram);
+ }
+
+ /**
* Reload the database from content provider to the cache. This must be a synchronous operation
* to prevent cache/database out-of-sync. Callers should be cautious to call this method because
* it might take longer time to complete.
@@ -2399,15 +2443,22 @@
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS)))
.setSatelliteEntitlementPlmns(cursor.getString(
cursor.getColumnIndexOrThrow(
- SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS)));
+ SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS)))
+ .setIsSatelliteProvisionedForNonIpDatagram(cursor.getInt(
+ cursor.getColumnIndexOrThrow(
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM)));
if (mFeatureFlags.oemEnabledSatelliteFlag()) {
builder.setOnlyNonTerrestrialNetwork(cursor.getInt(cursor.getColumnIndexOrThrow(
- SimInfo.COLUMN_IS_NTN)));
+ SimInfo.COLUMN_IS_ONLY_NTN)));
}
if (mFeatureFlags.supportPsimToEsimConversion()) {
builder.setTransferStatus(cursor.getInt(cursor.getColumnIndexOrThrow(
SimInfo.COLUMN_TRANSFER_STATUS)));
}
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ builder.setSatelliteESOSSupported(cursor.getInt(
+ cursor.getColumnIndexOrThrow(SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED)));
+ }
return builder.build();
}
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index c6dee7c..92e112d 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -492,6 +492,19 @@
@NonNull private final String mSatelliteEntitlementPlmns;
/**
+ * Whether the carrier roaming to satellite is using ESOS for emergency messaging.
+ * By default, its disabled. It is intended to use integer to fit the database format.
+ */
+ private final int mIsSatelliteESOSSupported;
+
+ /**
+ * Whether this subscription is provisioned for OEM-enabled or carrier roaming NB-IOT satellite
+ * service or not.
+ * By default, its disabled. It is intended to use integer to fit the database format.
+ */
+ private final int mIsSatelliteProvisionedForNonIpDatagram;
+
+ /**
* Constructor from builder.
*
* @param builder Builder of {@link SubscriptionInfoInternal}.
@@ -570,6 +583,9 @@
this.mTransferStatus = builder.mTransferStatus;
this.mIsSatelliteEntitlementStatus = builder.mIsSatelliteEntitlementStatus;
this.mSatelliteEntitlementPlmns = builder.mSatelliteEntitlementPlmns;
+ this.mIsSatelliteESOSSupported = builder.mIsSatelliteESOSSupported;
+ this.mIsSatelliteProvisionedForNonIpDatagram =
+ builder.mIsSatelliteProvisionedForNonIpDatagram;
}
/**
@@ -1266,6 +1282,23 @@
return mSatelliteEntitlementPlmns;
}
+ /**
+ * @return {@code 1} if the carrier roaming to satellite is using ESOS for emergency messaging.
+ */
+ public int getSatelliteESOSSupported() {
+ return mIsSatelliteESOSSupported;
+ }
+
+ /**
+ * Return whether the subscription is provisioned for oem satellite service or not.
+ *
+ * @return {@code 1} if the subscription is provisioned for oem stellite service. {@code 0}
+ * otherwise.
+ */
+ public int getIsSatelliteProvisionedForNonIpDatagram() {
+ return mIsSatelliteProvisionedForNonIpDatagram;
+ }
+
/** @return converted {@link SubscriptionInfo}. */
@NonNull
public SubscriptionInfo toSubscriptionInfo() {
@@ -1305,6 +1338,7 @@
.setServiceCapabilities(
SubscriptionManager.getServiceCapabilitiesSet(mServiceCapabilities))
.setTransferStatus(mTransferStatus)
+ .setSatelliteESOSSupported(mIsSatelliteESOSSupported == 1)
.build();
}
@@ -1368,6 +1402,9 @@
+ " transferStatus=" + mTransferStatus
+ " satelliteEntitlementStatus=" + mIsSatelliteEntitlementStatus
+ " satelliteEntitlementPlmns=" + mSatelliteEntitlementPlmns
+ + " isSatelliteESOSSupported=" + mIsSatelliteESOSSupported
+ + " isSatelliteProvisionedForNonIpDatagram="
+ + mIsSatelliteProvisionedForNonIpDatagram
+ "]";
}
@@ -1430,7 +1467,10 @@
&& mServiceCapabilities == that.mServiceCapabilities
&& mTransferStatus == that.mTransferStatus
&& mIsSatelliteEntitlementStatus == that.mIsSatelliteEntitlementStatus
- && mSatelliteEntitlementPlmns == that.mSatelliteEntitlementPlmns;
+ && mSatelliteEntitlementPlmns.equals(that.mSatelliteEntitlementPlmns)
+ && mIsSatelliteESOSSupported == that.mIsSatelliteESOSSupported
+ && mIsSatelliteProvisionedForNonIpDatagram
+ == that.mIsSatelliteProvisionedForNonIpDatagram;
}
@Override
@@ -1463,7 +1503,8 @@
mIsSatelliteEnabled, mCardId, mIsGroupDisabled,
mIsSatelliteAttachEnabledForCarrier, mIsOnlyNonTerrestrialNetwork,
mServiceCapabilities, mTransferStatus, mIsSatelliteEntitlementStatus,
- mSatelliteEntitlementPlmns);
+ mSatelliteEntitlementPlmns, mIsSatelliteESOSSupported,
+ mIsSatelliteProvisionedForNonIpDatagram);
result = 31 * result + Arrays.hashCode(mNativeAccessRules);
result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
result = 31 * result + Arrays.hashCode(mRcsConfig);
@@ -1872,6 +1913,16 @@
private String mSatelliteEntitlementPlmns = "";
/**
+ * Whether the carrier roaming to satellite is using ESOS for emergency messaging.
+ */
+ private int mIsSatelliteESOSSupported = 0;
+
+ /**
+ * Whether this subscription is provisioned for oem satellite service or not.
+ */
+ private int mIsSatelliteProvisionedForNonIpDatagram = 0;
+
+ /**
* Default constructor.
*/
public Builder() {
@@ -1953,6 +2004,8 @@
mTransferStatus = info.mTransferStatus;
mIsSatelliteEntitlementStatus = info.mIsSatelliteEntitlementStatus;
mSatelliteEntitlementPlmns = info.mSatelliteEntitlementPlmns;
+ mIsSatelliteESOSSupported = info.mIsSatelliteESOSSupported;
+ mIsSatelliteProvisionedForNonIpDatagram = info.mIsSatelliteProvisionedForNonIpDatagram;
}
/**
@@ -2923,6 +2976,33 @@
}
/**
+ * Set whether the carrier roaming to satellite is using ESOS for emergency messaging.
+ *
+ * @param isSatelliteESOSSupported {@code 1} if the carrier roaming to satellite is using
+ * ESOS for emergency messaging.
+ * @return The builder
+ */
+ @NonNull
+ public Builder setSatelliteESOSSupported(int isSatelliteESOSSupported) {
+ mIsSatelliteESOSSupported = isSatelliteESOSSupported;
+ return this;
+ }
+
+ /**
+ * Set whether the subscription is provisioned for oem satellite service or not.
+ *
+ * @param isSatelliteProvisionedForNonIpDatagram {@code 1} if the subscription is for NTN,
+ * {@code 0} otherwise.
+ * @return The builder.
+ */
+ @NonNull
+ public Builder setIsSatelliteProvisionedForNonIpDatagram(
+ int isSatelliteProvisionedForNonIpDatagram) {
+ mIsSatelliteProvisionedForNonIpDatagram = isSatelliteProvisionedForNonIpDatagram;
+ return this;
+ }
+
+ /**
* Build the {@link SubscriptionInfoInternal}.
*
* @return The {@link SubscriptionInfoInternal} instance.
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 2125f45..a0a050c 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -27,6 +27,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.compat.CompatChanges;
@@ -193,9 +194,11 @@
SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED,
SimInfo.COLUMN_SATELLITE_ENABLED,
SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
- SimInfo.COLUMN_IS_NTN,
+ SimInfo.COLUMN_IS_ONLY_NTN,
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS,
- SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS
+ SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM
);
/**
@@ -456,6 +459,13 @@
* @param subId The subscription id.
*/
public void onUiccApplicationsEnabledChanged(int subId) {}
+
+ /**
+ * Called when {@link #getDefaultDataSubId()} changed.
+ *
+ * @param subId The subscription id.
+ */
+ public void onDefaultDataSubscriptionChanged(int subId) {}
}
/**
@@ -591,6 +601,13 @@
// Broadcast sub Id on service initialized.
broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,
getDefaultDataSubId());
+ if (mFeatureFlags.ddsCallback()) {
+ mSubscriptionManagerServiceCallbacks.forEach(
+ callback -> callback.invokeFromExecutor(
+ () -> callback.onDefaultDataSubscriptionChanged(
+ getDefaultDataSubId())));
+ }
+
broadcastSubId(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED,
getDefaultVoiceSubId());
broadcastSubId(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED,
@@ -704,7 +721,7 @@
return false;
}
} else {
- if (!mSubscriptionManager.canManageSubscription(subInfo.toSubscriptionInfo(),
+ if (!canManageSubscription(subInfo.toSubscriptionInfo(),
callingPackage)) {
loge("checkCarrierPrivilegeOnSubList: cannot manage sub " + subId);
return false;
@@ -911,6 +928,8 @@
* @param subId The subscription id.
*/
public void setCountryIso(int subId, @NonNull String iso) {
+ logl("setCountryIso: subId=" + subId + ", iso=" + iso);
+
// This can throw IllegalArgumentException if the subscription does not exist.
try {
mSubscriptionDatabaseManager.setCountryIso(subId, iso);
@@ -927,6 +946,8 @@
* @param carrierName The carrier name.
*/
public void setCarrierName(int subId, @NonNull String carrierName) {
+ logl("setCarrierName: subId=" + subId + ", carrierName=" + carrierName);
+
// This can throw IllegalArgumentException if the subscription does not exist.
try {
mSubscriptionDatabaseManager.setCarrierName(subId, carrierName);
@@ -998,6 +1019,9 @@
* @param numberFromIms The phone number retrieved from IMS.
*/
public void setNumberFromIms(int subId, @NonNull String numberFromIms) {
+ logl("setNumberFromIms: subId=" + subId + ", number="
+ + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, numberFromIms));
+
// This can throw IllegalArgumentException if the subscription does not exist.
try {
mSubscriptionDatabaseManager.setNumberFromIms(subId, numberFromIms);
@@ -1427,8 +1451,8 @@
SatelliteController satelliteController = SatelliteController.getInstance();
boolean isSatelliteEnabledOrBeingEnabled = false;
if (satelliteController != null) {
- isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
- || satelliteController.isSatelliteBeingEnabled();
+ isSatelliteEnabledOrBeingEnabled =
+ satelliteController.isSatelliteEnabledOrBeingEnabled();
}
if (!isSatelliteEnabledOrBeingEnabled) {
@@ -1540,6 +1564,9 @@
MccTable.updateMccMncConfiguration(mContext, mccMnc);
}
setMccMnc(subId, mccMnc);
+ if (isSatelliteSpn(subInfo.getDisplayName()) || isSatellitePlmn(mccMnc)) {
+ setNtn(subId, true);
+ }
} else {
loge("updateSubscription: mcc/mnc is empty");
}
@@ -1812,37 +1839,35 @@
+ " newSetting=" + SubscriptionManager.usageSettingToString(newUsageSetting));
}
- if (mFeatureFlags.dataOnlyCellularService()) {
- final int[] servicesFromCarrierConfig =
- config.getIntArray(
- CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
- int serviceBitmasks = 0;
- boolean allServicesAreValid = true;
- // Check if all services from carrier config are valid before setting to db
- if (servicesFromCarrierConfig == null) {
- allServicesAreValid = false;
- } else {
- for (int service : servicesFromCarrierConfig) {
- if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
- || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
- allServicesAreValid = false;
- break;
- } else {
- serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
- }
+ final int[] servicesFromCarrierConfig =
+ config.getIntArray(
+ CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
+ int serviceBitmasks = 0;
+ boolean allServicesAreValid = true;
+ // Check if all services from carrier config are valid before setting to db
+ if (servicesFromCarrierConfig == null) {
+ allServicesAreValid = false;
+ } else {
+ for (int service : servicesFromCarrierConfig) {
+ if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE
+ || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) {
+ allServicesAreValid = false;
+ break;
+ } else {
+ serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service);
}
}
- // In case we get invalid service override, fall back to default value.
- // DO NOT throw exception which will crash phone process.
- if (!allServicesAreValid) {
- serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
- }
+ }
+ // In case we get invalid service override, fall back to default value.
+ // DO NOT throw exception which will crash phone process.
+ if (!allServicesAreValid) {
+ serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks();
+ }
- if (serviceBitmasks != subInfo.getServiceCapabilities()) {
- log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
- + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
- mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
- }
+ if (serviceBitmasks != subInfo.getServiceCapabilities()) {
+ log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from "
+ + subInfo.getServiceCapabilities() + " to " + serviceBitmasks);
+ mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks);
}
}
@@ -1889,7 +1914,10 @@
+ "carrier privilege");
}
- enforceTelephonyFeatureWithException(callingPackage, "getAllSubInfoList");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(callingPackage, "getAllSubInfoList");
+ }
return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
// callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
@@ -1933,7 +1961,10 @@
+ "carrier privilege");
}
- enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
+ }
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
.getSubscriptionInfoInternal(subId);
@@ -2062,7 +2093,10 @@
return Collections.emptyList();
}
- enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
+ }
if (isForAllProfiles) {
enforcePermissionAccessAllUserProfiles();
@@ -2154,7 +2188,11 @@
enforcePermissions("getAvailableSubscriptionInfoList",
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
- enforceTelephonyFeatureWithException(callingPackage, "getAvailableSubscriptionInfoList");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(callingPackage,
+ "getAvailableSubscriptionInfoList");
+ }
return getAvailableSubscriptionsInternalStream()
.sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex)
@@ -2229,7 +2267,7 @@
return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle())
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(subInfo -> subInfo.isEmbedded()
- && mSubscriptionManager.canManageSubscription(subInfo, callingPackage))
+ && canManageSubscription(subInfo, callingPackage))
.sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex)
.thenComparing(SubscriptionInfo::getSubscriptionId))
.collect(Collectors.toList());
@@ -2738,7 +2776,10 @@
return Collections.emptyList();
}
- enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
+ }
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
// callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
@@ -2952,7 +2993,7 @@
return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.filter(info -> groupUuid.equals(info.getGroupUuid())
- && (mSubscriptionManager.canManageSubscription(info, callingPackage)
+ && (canManageSubscription(info, callingPackage)
|| TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
mContext, info.getSubscriptionId(), callingPackage,
callingFeatureId, "getSubscriptionsInGroup")))
@@ -3149,6 +3190,11 @@
broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,
subId);
+ if (mFeatureFlags.ddsCallback()) {
+ mSubscriptionManagerServiceCallbacks.forEach(
+ callback -> callback.invokeFromExecutor(
+ () -> callback.onDefaultDataSubscriptionChanged(subId)));
+ }
updateDefaultSubId();
}
@@ -3311,7 +3357,10 @@
public int[] getActiveSubIdList(boolean visibleOnly) {
enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
- enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
+ if (!mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_force_phone_globals_creation)) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
+ }
// UserHandle.ALL because this API is exposed as system API.
return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL);
@@ -3875,10 +3924,20 @@
switch(source) {
case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
final Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
- if (phone != null) {
- return TextUtils.emptyIfNull(phone.getLine1Number());
- } else {
+ if (mFeatureFlags.uiccPhoneNumberFix()) {
+ if (phone != null) {
+ String number = phone.getLine1Number();
+ if (!TextUtils.isEmpty(number)) {
+ return number;
+ }
+ }
return subInfo.getNumber();
+ } else {
+ if (phone != null) {
+ return TextUtils.emptyIfNull(phone.getLine1Number());
+ } else {
+ return subInfo.getNumber();
+ }
}
case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
return subInfo.getNumberFromCarrier();
@@ -3986,6 +4045,9 @@
@RequiresPermission("carrier privileges")
public void setPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String number,
@NonNull String callingPackage, @Nullable String callingFeatureId) {
+ logl("setPhoneNumber: subId=" + subId + ", number="
+ + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, number)
+ + ", calling package=" + callingPackage);
if (!TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, subId)) {
throw new SecurityException("setPhoneNumber for CARRIER needs carrier privilege.");
}
@@ -4494,10 +4556,14 @@
*/
@NonNull
private String getCallingPackage() {
- if (Binder.getCallingUid() == Process.PHONE_UID) {
+ if (UserHandle.isSameApp(Binder.getCallingUid(), Process.PHONE_UID)) {
// Too many packages running with phone uid. Just return one here.
return "com.android.phone";
}
+ if (mFeatureFlags.hsumPackageManager()) {
+ return Arrays.toString(mContext.createContextAsUser(Binder.getCallingUserHandle(), 0)
+ .getPackageManager().getPackagesForUid(Binder.getCallingUid()));
+ }
return Arrays.toString(mContext.getPackageManager().getPackagesForUid(
Binder.getCallingUid()));
}
@@ -4591,6 +4657,75 @@
}
/**
+ * Set the satellite ESOS supported value in the subscription database.
+ *
+ * @param subId subscription id.
+ * @param isSatelliteESOSSupported {@code true} satellite ESOS supported true.
+ */
+ public void setSatelliteESOSSupported(int subId, @NonNull boolean isSatelliteESOSSupported) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+ try {
+ mSubscriptionDatabaseManager.setSatelliteESOSSupported(subId,
+ isSatelliteESOSSupported ? 1 : 0);
+ } catch (IllegalArgumentException e) {
+ loge("setSatelliteESOSSupported: invalid subId=" + subId);
+ }
+ }
+
+ /**
+ * Set whether the subscription is provisioned for OEM-enabled or carrier roaming NB-IOT
+ * satellite service or not.
+ *
+ * @param subId subscription id.
+ * @param isSatelliteProvisionedForNonIpDatagram {@code true} if subId is provisioned.
+ * {@code false} otherwise.
+ */
+ public void setIsSatelliteProvisionedForNonIpDatagram(int subId,
+ boolean isSatelliteProvisionedForNonIpDatagram) {
+ try {
+ mSubscriptionDatabaseManager.setIsSatelliteProvisionedForNonIpDatagram(
+ subId, (isSatelliteProvisionedForNonIpDatagram ? 1 : 0));
+ } catch (IllegalArgumentException e) {
+ loge("setIsSatelliteProvisionedForNonIpDatagram: invalid subId=" + subId);
+ }
+ }
+
+ /**
+ * Get the satellite ESOS supported value in the subscription database.
+ *
+ * @param subId subscription id.
+ * @return the satellite ESOS supported true or false.
+ */
+ public boolean getSatelliteESOSSupported(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return false;
+ }
+ SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+ subId);
+ if (subInfo == null) {
+ return false;
+ }
+
+ return subInfo.getSatelliteESOSSupported() == 1;
+ }
+
+ /**
+ * Get whether the subscription is provisioned for OEM-enabled or carrier roaming NB-IOT
+ * satellite service or not.
+ *
+ * @param subId subscription id.
+ * @return {@code true} if it is provisioned for oem satellite service. {@code false} otherwise.
+ */
+ public boolean isSatelliteProvisionedForNonIpDatagram(int subId) {
+ SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+ subId);
+
+ return subInfo.getIsSatelliteProvisionedForNonIpDatagram() == 1;
+ }
+
+ /**
* checks whether esim bootstrap is activated for any of the available active subscription info
* list.
*
@@ -4633,9 +4768,16 @@
*/
@Nullable
private String getCurrentPackageName() {
+ if (mFeatureFlags.hsumPackageManager()) {
+ PackageManager pm = mContext.createContextAsUser(Binder.getCallingUserHandle(), 0)
+ .getPackageManager();
+ if (pm == null) return null;
+ String[] callingPackageNames = pm.getPackagesForUid(Binder.getCallingUid());
+ return (callingPackageNames == null) ? null : callingPackageNames[0];
+ }
if (mPackageManager == null) return null;
- String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
- return (callingUids == null) ? null : callingUids[0];
+ String[] callingPackageNames = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingPackageNames == null) ? null : callingPackageNames[0];
}
/**
@@ -4760,6 +4902,15 @@
return cardNumber;
}
+ private boolean canManageSubscription(SubscriptionInfo subInfo, String packageName) {
+ if (Flags.hsumPackageManager() && UserManager.isHeadlessSystemUserMode()) {
+ return mSubscriptionManager.canManageSubscriptionAsUser(subInfo, packageName,
+ UserHandle.of(ActivityManager.getCurrentUser()));
+ } else {
+ return mSubscriptionManager.canManageSubscription(subInfo, packageName);
+ }
+ }
+
/**
* Log debug messages.
*
diff --git a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
index 5f8ccb4..a3f34c4 100644
--- a/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
+++ b/src/java/com/android/internal/telephony/uicc/IccFileHandler.java
@@ -16,14 +16,18 @@
package com.android.internal.telephony.uicc;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
+
import android.compat.annotation.UnsupportedAppUsage;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CommandsInterface;
+import com.android.telephony.Rlog;
import java.util.ArrayList;
@@ -31,7 +35,9 @@
* {@hide}
*/
public abstract class IccFileHandler extends Handler implements IccConstants {
- private static final boolean VDBG = false;
+ protected static final String LOG_TAG = "IccFileHandler";
+ private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
+ Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
//from TS 11.11 9.1 or elsewhere
static protected final int COMMAND_READ_BINARY = 0xb0;
diff --git a/src/java/com/android/internal/telephony/uicc/IccRecords.java b/src/java/com/android/internal/telephony/uicc/IccRecords.java
index ae93b09..cccbf19 100644
--- a/src/java/com/android/internal/telephony/uicc/IccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IccRecords.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.uicc;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -34,6 +36,7 @@
import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.gsm.SimTlv;
@@ -59,7 +62,6 @@
public abstract class IccRecords extends Handler implements IccConstants {
private static final String LOG_TAG = "IccRecords";
protected static final boolean DBG = true;
- private static final boolean FORCE_VERBOSE_STATE_LOGGING = false; /* stopship if true */
protected static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
@@ -1299,10 +1301,18 @@
return null;
}
+ if (rsp.exception instanceof CommandException commandException) {
+ switch (commandException.getCommandError()) {
+ case REQUEST_NOT_SUPPORTED:
+ throw new UnsupportedOperationException(commandException);
+ default:
+ // handle other exceptions in the rsp.exception conditional below
+ }
+ }
if (rsp.exception != null) {
loge("getIccSimChallengeResponse exception: " + rsp.exception);
//TODO: propagate better exceptions up to the user now that we have them available
- //in the call stack.
+ //in the call stack (see CommandException switch above).
return null;
}
diff --git a/src/java/com/android/internal/telephony/uicc/InstallCarrierAppTrampolineActivity.java b/src/java/com/android/internal/telephony/uicc/InstallCarrierAppTrampolineActivity.java
index 2c29266..a07c2ec 100644
--- a/src/java/com/android/internal/telephony/uicc/InstallCarrierAppTrampolineActivity.java
+++ b/src/java/com/android/internal/telephony/uicc/InstallCarrierAppTrampolineActivity.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -107,7 +108,8 @@
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == INSTALL_CARRIER_APP_DIALOG_REQUEST) {
if (resultCode == DOWNLOAD_RESULT) {
- startActivity(InstallCarrierAppUtils.getPlayStoreIntent(mPackageName));
+ startActivityAsUser(InstallCarrierAppUtils.getPlayStoreIntent(mPackageName),
+ UserHandle.CURRENT);
}
finishNoAnimation();
}
diff --git a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
index 9591a498..b705cbc 100644
--- a/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/IsimUiccRecords.java
@@ -16,17 +16,23 @@
package com.android.internal.telephony.uicc;
+import android.annotation.NonNull;
+
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
+
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncResult;
import android.os.Build;
import android.os.Message;
+import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.SimTlv;
import com.android.telephony.Rlog;
@@ -43,7 +49,6 @@
protected static final String LOG_TAG = "IsimUiccRecords";
private static final boolean DBG = true;
- private static final boolean FORCE_VERBOSE_STATE_LOGGING = false; /* stopship if true */
private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
private static final boolean DUMP_RECORDS = false; // Note: PII is logged when this is true
@@ -64,6 +69,9 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private String auth_rsp;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
private static final int TAG_ISIM_VALUE = 0x80; // From 3GPP TS 31.103
@Override
@@ -78,9 +86,10 @@
+ " mSmss TPMR=" + getSmssTpmrValue()) : "");
}
- public IsimUiccRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
+ public IsimUiccRecords(@NonNull UiccCardApplication app, @NonNull Context c,
+ @NonNull CommandsInterface ci, @NonNull FeatureFlags flags) {
super(app, c, ci);
-
+ mFeatureFlags = flags;
mRecordsRequested = false; // No load request is made till SIM ready
//todo: currently locked state for ISIM is not handled well and may cause app state to not
//be broadcast
@@ -387,7 +396,11 @@
Intent intent = new Intent(INTENT_ISIM_REFRESH);
log("send ISim REFRESH: " + INTENT_ISIM_REFRESH);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mParentApp.getPhoneId());
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
}
/**
diff --git a/src/java/com/android/internal/telephony/uicc/PinStorage.java b/src/java/com/android/internal/telephony/uicc/PinStorage.java
index e4a0cfa..e26050e 100644
--- a/src/java/com/android/internal/telephony/uicc/PinStorage.java
+++ b/src/java/com/android/internal/telephony/uicc/PinStorage.java
@@ -36,6 +36,7 @@
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS;
import static com.android.internal.telephony.uicc.IccCardStatus.PinState.PINSTATE_ENABLED_NOT_VERIFIED;
import static com.android.internal.telephony.uicc.IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
import android.annotation.Nullable;
import android.app.KeyguardManager;
@@ -56,6 +57,7 @@
import android.telephony.TelephonyManager.SimState;
import android.util.Base64;
import android.util.IndentingPrintWriter;
+import android.util.Log;
import android.util.SparseArray;
import com.android.internal.R;
@@ -88,7 +90,8 @@
*/
public class PinStorage extends Handler {
private static final String TAG = "PinStorage";
- private static final boolean VDBG = false; // STOPSHIP if true
+ private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
+ Rlog.isLoggable(TAG, Log.VERBOSE);
/**
* Time duration in milliseconds to allow automatic PIN verification after reboot. All unused
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index a97b00b..4b0e63c 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -19,6 +19,8 @@
import static android.telephony.SmsManager.STATUS_ON_ICC_READ;
import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
+
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
@@ -48,6 +50,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* {@hide}
@@ -56,8 +59,7 @@
protected static final String LOG_TAG = "SIMRecords";
private static final boolean CRASH_RIL = false;
- private static final boolean FORCE_VERBOSE_STATE_LOGGING = false; /* stopship if true */
- private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
+ private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
// ***** Instance Variables
@@ -1278,15 +1280,22 @@
case EVENT_GET_FPLMN_SIZE_DONE:
ar = (AsyncResult) msg.obj;
+ int key = msg.arg2;
+
+ Message response;
+ Pair<Message, Object> transaction = null;
+ if (ar.exception != null && ar.userObj != null) {
+ response = (Message) ar.userObj;
+ } else {
+ transaction = retrievePendingTransaction(key);
+ response = Objects.requireNonNull(transaction.first);
+ }
+
if (ar.exception != null) {
- Message response = (Message) ar.userObj;
AsyncResult.forMessage(response).exception = ar.exception;
response.sendToTarget();
break;
}
- int key = msg.arg2;
- Pair<Message, Object> transaction = retrievePendingTransaction(key);
- Message response = transaction.first;
List<String> fplmns = (List<String>) transaction.second;
int dataLength = (int) ar.result;
if (dataLength < 0 || dataLength % FPLMN_BYTE_SIZE != 0) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
index fe19e99..3bda29f 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccCardApplication.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.uicc;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.AsyncResult;
@@ -29,6 +30,7 @@
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
@@ -105,11 +107,14 @@
private RegistrantList mPinLockedRegistrants = new RegistrantList();
private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
- public UiccCardApplication(UiccProfile uiccProfile,
- IccCardApplicationStatus as,
- Context c,
- CommandsInterface ci) {
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
+ public UiccCardApplication(@NonNull UiccProfile uiccProfile,
+ @NonNull IccCardApplicationStatus as, @NonNull Context c, @NonNull CommandsInterface ci,
+ @NonNull FeatureFlags flags) {
if (DBG) log("Creating UiccApp: " + as);
+ mFeatureFlags = flags;
mUiccProfile = uiccProfile;
mAppState = as.app_state;
mAppType = as.app_type;
@@ -208,7 +213,7 @@
} else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){
return new RuimRecords(this, c, ci);
} else if (type == AppType.APPTYPE_ISIM) {
- return new IsimUiccRecords(this, c, ci);
+ return new IsimUiccRecords(this, c, ci, mFeatureFlags);
} else {
// Unknown app type (maybe detection is still in progress)
return null;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 84e84d9..dd71c44 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -19,6 +19,8 @@
import static android.telephony.TelephonyManager.UNINITIALIZED_CARD_ID;
import static android.telephony.TelephonyManager.UNSUPPORTED_CARD_ID;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
+
import static java.util.Arrays.copyOf;
import android.Manifest;
@@ -35,6 +37,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.RegistrantList;
+import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.sysprop.TelephonyProperties;
import android.telephony.AnomalyReporter;
@@ -64,6 +67,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RadioConfig;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.euicc.EuiccCard;
@@ -129,9 +133,10 @@
* See also {@link com.android.internal.telephony.IccCard}
*/
public class UiccController extends Handler {
- private static final boolean DBG = true;
- private static final boolean VDBG = false; //STOPSHIP if true
private static final String LOG_TAG = "UiccController";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
+ Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
public static final int INVALID_SLOT_ID = -1;
@@ -245,22 +250,26 @@
// LocalLog buffer to hold important SIM related events for debugging
private static LocalLog sLocalLog = new LocalLog(TelephonyUtils.IS_DEBUGGABLE ? 256 : 64);
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
/**
* API to make UiccController singleton if not already created.
*/
- public static UiccController make(Context c) {
+ public static UiccController make(@NonNull Context c, @NonNull FeatureFlags flags) {
synchronized (mLock) {
if (mInstance != null) {
throw new RuntimeException("UiccController.make() should only be called once");
}
- mInstance = new UiccController(c);
+ mInstance = new UiccController(c, flags);
return mInstance;
}
}
- private UiccController(Context c) {
+ private UiccController(@NonNull Context c, @NonNull FeatureFlags flags) {
if (DBG) log("Creating UiccController");
mContext = c;
+ mFeatureFlags = flags;
mCis = PhoneFactory.getCommandsInterfaces();
int numPhysicalSlots = c.getResources().getInteger(
com.android.internal.R.integer.config_num_physical_slots);
@@ -292,7 +301,7 @@
mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i);
}
- mLauncher = new UiccStateChangedLauncher(c, this);
+ mLauncher = new UiccStateChangedLauncher(c, this, mFeatureFlags);
mCardStrings = loadCardStrings();
mDefaultEuiccCardId = UNINITIALIZED_CARD_ID;
@@ -780,9 +789,10 @@
intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state);
intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
+ SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId);
Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason "
- + reason + " for phone: " + phoneId);
+ + reason + " for phone: " + phoneId + " sub: " + subId);
IntentBroadcaster.getInstance().broadcastStickyIntent(mContext, intent, phoneId);
}
@@ -798,7 +808,8 @@
Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, state);
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
+ SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId);
// TODO(b/130664115) we manually populate this intent with the slotId. In the future we
// should do a review of whether to make this public
UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
@@ -811,8 +822,13 @@
}
Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_CARD_STATE_CHANGED "
+ TelephonyManager.simStateToString(state) + " for phone: " + phoneId
- + " slot: " + slotId + " port: " + portIndex);
- mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ + " slot: " + slotId + " port: " + portIndex + " sub: " + subId);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ } else {
+ mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
TelephonyMetrics.getInstance().updateSimState(phoneId, state);
}
}
@@ -838,7 +854,8 @@
Intent intent = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, state);
- SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
+ SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId);
// TODO(b/130664115) we populate this intent with the actual slotId. In the future we
// should do a review of whether to make this public
UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
@@ -849,9 +866,14 @@
}
Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_APPLICATION_STATE_CHANGED "
+ TelephonyManager.simStateToString(state)
- + " for phone: " + phoneId + " slot: " + slotId + "port: "
- + slot.getPortIndexFromPhoneId(phoneId));
- mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ + " for phone: " + phoneId + " slot: " + slotId + " port: "
+ + slot.getPortIndexFromPhoneId(phoneId) + " sub: " + subId);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ } else {
+ mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
TelephonyMetrics.getInstance().updateSimState(phoneId, state);
}
}
@@ -1453,8 +1475,13 @@
options.setBackgroundActivityStartsAllowed(true);
Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- options.toBundle());
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+ android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, options.toBundle());
+ } else {
+ mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ options.toBundle());
+ }
}
private boolean hasActivePort(IccSimPortInfo[] simPortInfos) {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPort.java b/src/java/com/android/internal/telephony/uicc/UiccPort.java
index 9e341ef..905db70 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPort.java
@@ -31,7 +31,6 @@
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.FeatureFlagsImpl;
-import com.android.internal.telephony.flags.Flags;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
@@ -442,15 +441,13 @@
* channel that may have been assigned to other client.
*/
private void cleanupOpenLogicalChannelRecordsIfNeeded() {
- if (Flags.cleanupOpenLogicalChannelRecordOnDispose()) {
- synchronized (mOpenChannelRecords) {
- for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
- if (DBG) log("Clean up " + record);
- record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
- record.mRequest.binder = null;
- }
- mOpenChannelRecords.clear();
+ synchronized (mOpenChannelRecords) {
+ for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
+ if (DBG) log("Clean up " + record);
+ record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
+ record.mRequest.binder = null;
}
+ mOpenChannelRecords.clear();
}
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index a22f075..2551cb8 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -19,6 +19,7 @@
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT;
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE;
import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS;
+import static com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,6 +41,7 @@
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
+import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -53,6 +55,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CarrierAppUtils;
@@ -67,6 +70,7 @@
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.cat.CatService;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
@@ -101,11 +105,13 @@
public class UiccProfile extends IccCard {
protected static final String LOG_TAG = "UiccProfile";
protected static final boolean DBG = true;
- private static final boolean VDBG = false; //STOPSHIP if true
+ private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING ||
+ Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
- private final @NonNull FeatureFlags mFlags;
+ @NonNull
+ private final FeatureFlags mFlags;
// The lock object is created by UiccSlot that owns the UiccCard that owns this UiccProfile.
// This is to share the lock between UiccSlot, UiccCard and UiccProfile for now.
private final Object mLock;
@@ -1139,7 +1145,7 @@
//Create newly added Applications
if (i < ics.mApplications.length) {
mUiccApplications[i] = new UiccCardApplication(this,
- ics.mApplications[i], mContext, mCi);
+ ics.mApplications[i], mContext, mCi, mFlags);
}
} else if (i >= ics.mApplications.length) {
//Delete removed applications
@@ -1155,7 +1161,9 @@
// Reload the carrier privilege rules if necessary.
log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + ics.mCardState);
- if (mCarrierPrivilegeRules == null && ics.mCardState == CardState.CARDSTATE_PRESENT) {
+ if (mCarrierPrivilegeRules == null && ics.mCardState == CardState.CARDSTATE_PRESENT && (
+ !Flags.uiccAppCountCheckToCreateChannel()
+ || mLastReportedNumOfUiccApplications > 0)) {
mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this,
mHandler.obtainMessage(EVENT_CARRIER_PRIVILEGES_LOADED));
} else if (mCarrierPrivilegeRules != null
@@ -1349,7 +1357,7 @@
private void promptInstallCarrierApp(String pkgName) {
Intent showDialogIntent = InstallCarrierAppTrampolineActivity.get(mContext, pkgName);
showDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(showDialogIntent);
+ mContext.startActivityAsUser(showDialogIntent, UserHandle.CURRENT);
}
private void onCarrierPrivilegesLoadedMessage() {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccStateChangedLauncher.java b/src/java/com/android/internal/telephony/uicc/UiccStateChangedLauncher.java
index 3ef421a..ff48fd1 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccStateChangedLauncher.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccStateChangedLauncher.java
@@ -16,15 +16,18 @@
package com.android.internal.telephony.uicc;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.uicc.IccCardStatus.CardState;
/**
@@ -46,7 +49,12 @@
private UiccController mUiccController;
private boolean[] mIsRestricted = null;
- public UiccStateChangedLauncher(Context context, UiccController controller) {
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+
+ public UiccStateChangedLauncher(Context context, UiccController controller,
+ @NonNull FeatureFlags flags) {
+ mFeatureFlags = flags;
sDeviceProvisioningPackage = context.getResources().getString(
R.string.config_deviceProvisioningPackage);
if (sDeviceProvisioningPackage != null && !sDeviceProvisioningPackage.isEmpty()) {
@@ -92,7 +100,11 @@
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.setPackage(sDeviceProvisioningPackage);
try {
- mContext.sendBroadcast(intent);
+ if (mFeatureFlags.hsumBroadcast()) {
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(intent);
+ }
} catch (Exception e) {
Log.e(TAG, e.toString());
}
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index f42d5a2..1d9dc68 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -18,14 +18,16 @@
import android.annotation.Nullable;
import android.content.Context;
-import android.content.SharedPreferences;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.telephony.IccOpenLogicalChannelResponse;
import android.util.Base64;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.euicc.EuiccSession;
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.euicc.async.AsyncResultCallback;
import com.android.internal.telephony.uicc.euicc.async.AsyncResultHelper;
@@ -34,14 +36,20 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
-import java.util.NoSuchElementException;
/**
* This class sends a list of APDU commands to an AID on a UICC. A logical channel will be opened
* before sending and closed after all APDU commands are sent. The complete response of the last
* APDU command will be returned. If any APDU command returns an error status (other than
* {@link #STATUS_NO_ERROR}) or causing an exception, an {@link ApduException} will be returned
- * immediately without sending the rest of commands. This class is thread-safe.
+ * immediately without sending the rest of commands.
+ *
+ * <p>If {@link EuiccSession} indicates ongoing session(s), the behavior changes: 1) before
+ * sending, check if a channel is opened already. If yes, reuse the channel and send APDU commands
+ * directly. If no, open a channel before sending. 2) The channel is closed when EuiccSession
+ * class ends all sessions, independent of APDU sending.
+ *
+ * <p>This class is thread-safe.
*
* @hide
*/
@@ -55,10 +63,11 @@
// Status code of APDU response
private static final int STATUS_NO_ERROR = 0x9000;
private static final int SW1_NO_ERROR = 0x91;
+ private static final int STATUS_CHANNEL_CLOSED = 0x6881; // b/359336875
private static final int WAIT_TIME_MS = 2000;
private static final String CHANNEL_ID_PRE = "esim-channel";
- private static final String ISD_R_AID = "A0000005591010FFFFFFFF8900000100";
+ static final String ISD_R_AID = "A0000005591010FFFFFFFF8900000100";
private static final String CHANNEL_RESPONSE_ID_PRE = "esim-res-id";
private static void logv(String msg) {
@@ -69,6 +78,10 @@
Rlog.d(LOG_TAG, msg);
}
+ private static void loge(String msg) {
+ Rlog.e(LOG_TAG, msg);
+ }
+
private final String mAid;
private final boolean mSupportExtendedApdu;
private final OpenLogicalChannelInvocation mOpenChannel;
@@ -77,10 +90,16 @@
private final Context mContext;
private final String mChannelKey;
private final String mChannelResponseKey;
+ // closeAnyOpenChannel() needs a handler for its async callbacks.
+ private final Handler mHandler;
- // Lock for accessing mChannelOpened. We only allow to open a single logical channel at any
- // time for an AID.
- private final Object mChannelLock = new Object();
+ // Lock for accessing mChannelInUse. We only allow to open a single logical
+ // channel at any time for an AID and to invoke one command at any time.
+ // Only the thread (and its async callbacks) that sets mChannelInUse
+ // can open/close/send, and update mChannelOpened.
+ private final Object mChannelInUseLock = new Object();
+ @GuardedBy("mChannelInUseLock")
+ private boolean mChannelInUse;
private boolean mChannelOpened;
/**
@@ -88,6 +107,9 @@
*/
public ApduSender(Context context, int phoneId, CommandsInterface ci, String aid,
boolean supportExtendedApdu) {
+ if (!aid.equals(ISD_R_AID) && !"user".equals(Build.TYPE)) {
+ throw new IllegalArgumentException("Only ISD-R AID is supported.");
+ }
mAid = aid;
mContext = context;
mSupportExtendedApdu = supportExtendedApdu;
@@ -96,7 +118,8 @@
mTransmitApdu = new TransmitApduLogicalChannelInvocation(ci);
mChannelKey = CHANNEL_ID_PRE + "_" + phoneId;
mChannelResponseKey = CHANNEL_RESPONSE_ID_PRE + "_" + phoneId;
- closeExistingChannelIfExists();
+ mHandler = new Handler();
+ mChannelInUse = false;
}
/**
@@ -115,86 +138,125 @@
RequestProvider requestProvider,
ApduSenderResultCallback resultCallback,
Handler handler) {
- synchronized (mChannelLock) {
- if (mChannelOpened) {
- if (!Looper.getMainLooper().equals(Looper.myLooper())) {
- logd("Logical channel has already been opened. Wait.");
- try {
- mChannelLock.wait(WAIT_TIME_MS);
- } catch (InterruptedException e) {
- // nothing to do
- }
- if (mChannelOpened) {
- AsyncResultHelper.throwException(
- new ApduException("The logical channel is still in use."),
- resultCallback, handler);
- return;
- }
- } else {
- AsyncResultHelper.throwException(
- new ApduException("The logical channel is in use."),
- resultCallback, handler);
- return;
- }
- }
- mChannelOpened = true;
+ if (!acquireChannelLock()) {
+ AsyncResultHelper.throwException(
+ new ApduException("The logical channel is still in use."),
+ resultCallback,
+ handler);
+ return;
}
- mOpenChannel.invoke(mAid, new AsyncResultCallback<IccOpenLogicalChannelResponse>() {
- @Override
- public void onResult(IccOpenLogicalChannelResponse openChannelResponse) {
- int channel = openChannelResponse.getChannel();
- int status = openChannelResponse.getStatus();
- byte[] selectResponse = openChannelResponse.getSelectResponse();
- if (mAid.equals(ISD_R_AID)
- && status == IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT) {
- channel = PreferenceManager.getDefaultSharedPreferences(mContext)
- .getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
- if (channel != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
- logv("Try to use already opened channel: " + channel);
- status = IccOpenLogicalChannelResponse.STATUS_NO_ERROR;
- String storedResponse = PreferenceManager
- .getDefaultSharedPreferences(mContext)
- .getString(mChannelResponseKey, "");
- selectResponse = Base64.decode(storedResponse, Base64.DEFAULT);
- }
- }
- if (channel == IccOpenLogicalChannelResponse.INVALID_CHANNEL
- || status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR) {
- synchronized (mChannelLock) {
- mChannelOpened = false;
- mChannelLock.notify();
- }
- resultCallback.onException(
- new ApduException("Failed to open logical channel opened for AID: "
- + mAid + ", with status: " + status));
- return;
- }
-
- RequestBuilder builder = new RequestBuilder(channel, mSupportExtendedApdu);
- Throwable requestException = null;
- if (mAid.equals(ISD_R_AID)) {
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().putInt(mChannelKey, channel).apply();
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().putString(mChannelResponseKey,
- Base64.encodeToString(selectResponse, Base64.DEFAULT)).apply();
- }
- try {
- requestProvider.buildRequest(selectResponse, builder);
- } catch (Throwable e) {
- requestException = e;
- }
- if (builder.getCommands().isEmpty() || requestException != null) {
- // Just close the channel if we don't have commands to send or an error
- // was encountered.
- closeAndReturn(channel, null /* response */, requestException, resultCallback,
- handler);
- return;
- }
- sendCommand(builder.getCommands(), 0 /* index */, resultCallback, handler);
+ boolean euiccSession = EuiccSession.get().hasSession();
+ // Case 1, channel was already opened AND EuiccSession is ongoing.
+ // sendCommand directly. Do not immediately close channel after sendCommand.
+ // Case 2, channel was already opened AND EuiccSession is not ongoing. This means
+ // EuiccSession#endSession is already called but closeAnyOpenChannel() is not
+ // yet executed because of waiting to acquire lock hold by this thread.
+ // sendCommand directly. Close channel immediately anyways after sendCommand.
+ // Case 3, channel is not open AND EuiccSession is ongoing. Open channel
+ // before sendCommand. Do not immediately close channel after sendCommand.
+ // Case 4, channel is not open AND EuiccSession is not ongoing. Open channel
+ // before sendCommand. Close channel immediately after sendCommand.
+ if (mChannelOpened) { // Case 1 or 2
+ if (euiccSession) {
+ EuiccSession.get().noteChannelOpen(this);
}
- }, handler);
+ RequestBuilder builder = getRequestBuilderWithOpenedChannel(requestProvider,
+ !euiccSession /* closeChannelImmediately */, resultCallback, handler);
+ if (builder == null) {
+ return;
+ }
+ sendCommand(builder.getCommands(), 0 /* index */,
+ !euiccSession /* closeChannelImmediately */, resultCallback, handler);
+ } else { // Case 3 or 4
+ if (euiccSession) {
+ EuiccSession.get().noteChannelOpen(this);
+ }
+ openChannel(requestProvider,
+ !euiccSession /* closeChannelImmediately */, resultCallback, handler);
+ }
+ }
+
+ private RequestBuilder getRequestBuilderWithOpenedChannel(
+ RequestProvider requestProvider,
+ boolean closeChannelImmediately,
+ ApduSenderResultCallback resultCallback,
+ Handler handler) {
+ Throwable requestException = null;
+ int channel =
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
+ String storedResponse =
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .getString(mChannelResponseKey, "");
+ byte[] selectResponse = Base64.decode(storedResponse, Base64.DEFAULT);
+ RequestBuilder builder = new RequestBuilder(channel, mSupportExtendedApdu);
+ try {
+ requestProvider.buildRequest(selectResponse, builder);
+ } catch (Throwable e) {
+ requestException = e;
+ }
+ if (builder.getCommands().isEmpty() || requestException != null) {
+ logd("Release as commands are empty or exception occurred");
+ returnRespnseOrException(channel, closeChannelImmediately,
+ null /* response */, requestException, resultCallback, handler);
+ return null;
+ }
+ return builder;
+ }
+
+ private void openChannel(
+ RequestProvider requestProvider,
+ boolean closeChannelImmediately,
+ ApduSenderResultCallback resultCallback,
+ Handler handler) {
+ mOpenChannel.invoke(mAid, new AsyncResultCallback<IccOpenLogicalChannelResponse>() {
+ @Override
+ public void onResult(IccOpenLogicalChannelResponse openChannelResponse) {
+ int channel = openChannelResponse.getChannel();
+ int status = openChannelResponse.getStatus();
+ byte[] selectResponse = openChannelResponse.getSelectResponse();
+ if (status == IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT) {
+ channel = PreferenceManager.getDefaultSharedPreferences(mContext)
+ .getInt(mChannelKey,
+ IccOpenLogicalChannelResponse.INVALID_CHANNEL);
+ if (channel != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
+ logv("Try to use already opened channel: " + channel);
+ status = IccOpenLogicalChannelResponse.STATUS_NO_ERROR;
+ String storedResponse = PreferenceManager
+ .getDefaultSharedPreferences(mContext)
+ .getString(mChannelResponseKey, "");
+ selectResponse = Base64.decode(storedResponse, Base64.DEFAULT);
+ }
+ }
+
+ if (channel == IccOpenLogicalChannelResponse.INVALID_CHANNEL
+ || status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR) {
+ mChannelOpened = false;
+ resultCallback.onException(
+ new ApduException("Failed to open logical channel for AID: "
+ + mAid + ", with status: " + status));
+ return;
+ }
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit()
+ .putInt(mChannelKey, channel)
+ .putString(mChannelResponseKey,
+ Base64.encodeToString(selectResponse, Base64.DEFAULT)).apply();
+ mChannelOpened = true;
+
+ RequestBuilder builder =
+ getRequestBuilderWithOpenedChannel(requestProvider,
+ closeChannelImmediately, resultCallback, handler);
+ if (builder == null) {
+ return;
+ }
+
+ sendCommand(builder.getCommands(), 0 /* index */,
+ closeChannelImmediately, resultCallback, handler);
+ }
+ },
+ handler);
}
/**
@@ -207,6 +269,7 @@
private void sendCommand(
List<ApduCommand> commands,
int index,
+ boolean closeChannelImmediately,
ApduSenderResultCallback resultCallback,
Handler handler) {
ApduCommand command = commands.get(index);
@@ -221,9 +284,21 @@
public void onResult(IccIoResult fullResponse) {
logv("Full APDU response: " + fullResponse);
int status = (fullResponse.sw1 << 8) | fullResponse.sw2;
- if (status != STATUS_NO_ERROR && fullResponse.sw1 != SW1_NO_ERROR) {
- closeAndReturn(command.channel, null /* response */,
- new ApduException(status), resultCallback, handler);
+ if (status != STATUS_NO_ERROR
+ && fullResponse.sw1 != SW1_NO_ERROR) {
+ if (status == STATUS_CHANNEL_CLOSED) {
+ // Channel is closed by EUICC e.g. REFRESH.
+ tearDownPreferences();
+ mChannelOpened = false;
+ // TODO: add retry
+ }
+ returnRespnseOrException(
+ command.channel,
+ closeChannelImmediately,
+ null /* response */,
+ new ApduException(status),
+ resultCallback,
+ handler);
return;
}
@@ -233,11 +308,17 @@
fullResponse);
if (continueSendCommand) {
// Sends the next command
- sendCommand(commands, index + 1, resultCallback, handler);
+ sendCommand(commands, index + 1,
+ closeChannelImmediately, resultCallback, handler);
} else {
// Returns the result of the last command
- closeAndReturn(command.channel, fullResponse.payload,
- null /* exception */, resultCallback, handler);
+ returnRespnseOrException(
+ command.channel,
+ closeChannelImmediately,
+ fullResponse.payload,
+ null /* exception */,
+ resultCallback,
+ handler);
}
}
}, handler);
@@ -286,6 +367,41 @@
}, handler);
}
+ private void tearDownPreferences() {
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit()
+ .remove(mChannelKey)
+ .remove(mChannelResponseKey)
+ .apply();
+ }
+
+ /**
+ * Fires the {@code resultCallback} to return a response or exception. Also
+ * closes the open logical channel if {@code closeChannelImmediately} is {@code true}.
+ */
+ private void returnRespnseOrException(
+ int channel,
+ boolean closeChannelImmediately,
+ @Nullable byte[] response,
+ @Nullable Throwable exception,
+ ApduSenderResultCallback resultCallback,
+ Handler handler) {
+ if (closeChannelImmediately) {
+ closeAndReturn(
+ channel,
+ response,
+ exception,
+ resultCallback,
+ handler);
+ } else {
+ releaseChannelLockAndReturn(
+ response,
+ exception,
+ resultCallback,
+ handler);
+ }
+ }
+
/**
* Closes the opened logical channel.
*
@@ -303,16 +419,9 @@
mCloseChannel.invoke(channel, new AsyncResultCallback<Boolean>() {
@Override
public void onResult(Boolean aBoolean) {
- synchronized (mChannelLock) {
- if (mAid.equals(ISD_R_AID)) {
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().remove(mChannelKey).apply();
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().remove(mChannelResponseKey).apply();
- }
- mChannelOpened = false;
- mChannelLock.notify();
- }
+ tearDownPreferences();
+ mChannelOpened = false;
+ releaseChannelLock();
if (exception == null) {
resultCallback.onResult(response);
@@ -324,37 +433,97 @@
}
/**
- * Cleanup the existing opened channel which was remainined opened earlier due
- * to failure or crash.
+ * Cleanup the existing opened channel which remained opened earlier due
+ * to:
+ *
+ * <p> 1) onging EuiccSession. This will be called by {@link EuiccSession#endSession()}
+ * from non-main-thread. Or,
+ *
+ * <p> 2) telephony crash. This will be called by constructor from main-thread.
*/
- private void closeExistingChannelIfExists() {
- if (mCloseChannel != null) {
- int channelId = PreferenceManager.getDefaultSharedPreferences(mContext)
+ public void closeAnyOpenChannel() {
+ if (!acquireChannelLock()) {
+ // This cannot happen for case 2) when called by constructor
+ loge("[closeAnyOpenChannel] failed to acquire channel lock");
+ return;
+ }
+ int channelId = PreferenceManager.getDefaultSharedPreferences(mContext)
.getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
- if (channelId != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
- logv("Trying to clean up the opened channel : " + channelId);
- synchronized (mChannelLock) {
- mChannelOpened = true;
- mChannelLock.notify();
+ if (channelId == IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
+ releaseChannelLock();
+ return;
+ }
+ logv("[closeAnyOpenChannel] closing the open channel : " + channelId);
+ mCloseChannel.invoke(channelId, new AsyncResultCallback<Boolean>() {
+ @Override
+ public void onResult(Boolean isSuccess) {
+ if (isSuccess) {
+ logv("[closeAnyOpenChannel] Channel closed successfully: " + channelId);
+ tearDownPreferences();
}
- mCloseChannel.invoke(channelId, new AsyncResultCallback<Boolean>() {
- @Override
- public void onResult(Boolean isSuccess) {
- if (isSuccess) {
- logv("Channel closed successfully: " + channelId);
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().remove(mChannelResponseKey).apply();
- PreferenceManager.getDefaultSharedPreferences(mContext)
- .edit().remove(mChannelKey).apply();
- }
-
- synchronized (mChannelLock) {
- mChannelOpened = false;
- mChannelLock.notify();
- }
- }
- }, new Handler());
+ // Even if CloseChannel failed, pretend that the channel is closed.
+ // So next send() will try open the channel again. If the channel is
+ // indeed still open, we use the channelId saved in sharedPref.
+ mChannelOpened = false;
+ releaseChannelLock();
}
+ }, mHandler);
+ }
+
+ // releases channel and callback
+ private void releaseChannelLockAndReturn(
+ @Nullable byte[] response,
+ @Nullable Throwable exception,
+ ApduSenderResultCallback resultCallback,
+ Handler handler) {
+ handler.post(
+ () -> {
+ releaseChannelLock();
+ if (exception == null) {
+ resultCallback.onResult(response);
+ } else {
+ resultCallback.onException(exception);
+ }
+ });
+ }
+
+ private void releaseChannelLock() {
+ synchronized (mChannelInUseLock) {
+ logd("Channel lock released.");
+ mChannelInUse = false;
+ mChannelInUseLock.notify();
+ }
+ }
+
+ /**
+ * Acquires channel lock and returns {@code true} if successful.
+ *
+ * <p>It fails and returns {@code false} when:
+ * <ul>
+ * <li>Called from main thread, and mChannelInUse=true, fails immediately.
+ * <li>Called from non main thread, and mChannelInUse=true after 2 seconds waiting, fails.
+ * </ul>
+ */
+ private boolean acquireChannelLock() {
+ synchronized (mChannelInUseLock) {
+ if (mChannelInUse) {
+ if (!Looper.getMainLooper().equals(Looper.myLooper())) {
+ logd("Logical channel is in use. Wait.");
+ try {
+ mChannelInUseLock.wait(WAIT_TIME_MS);
+ } catch (InterruptedException e) {
+ // nothing to do
+ }
+ if (mChannelInUse) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ mChannelInUse = true;
+ logd("Channel lock acquired.");
+ return true;
}
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
index e06e4fe..cb37d88 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
@@ -23,7 +23,6 @@
import android.os.Bundle;
import android.os.CarrierAssociatedAppEntry;
import android.os.UserHandle;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
@@ -35,12 +34,9 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.telephony.flags.Flags;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -63,9 +59,6 @@
private static final int USER_ID = 12345;
private static final String CALLING_PACKAGE = "phone";
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
// Mocked classes
private Context mContext;
private PackageManager mPackageManager;
@@ -86,7 +79,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_PREINSTALLED_CARRIER_APP_AT_MOST_ONCE);
System.setProperty("dexmaker.dexcache",
InstrumentationRegistry.getTargetContext().getCacheDir().getPath());
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierDisplayNameResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierDisplayNameResolverTest.java
index 2ccfe0c..17fb829 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierDisplayNameResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierDisplayNameResolverTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -271,4 +272,14 @@
assertThat(data.shouldShowPlmn()).isTrue();
assertThat(data.getPlmn()).isEqualTo(HOME_PLMN_NUMERIC);
}
+
+ @Test
+ public void testCarrierDisplayNameData_enforceNonNullDataSpn() {
+ try {
+ CarrierDisplayNameData cdnd = new CarrierDisplayNameData.Builder()
+ .setSpn("testSpn").build();
+ fail("Expected IAE");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
index 06b63a2..1c58ef2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
@@ -52,6 +52,7 @@
import android.net.Uri;
import android.os.PersistableBundle;
import android.os.Process;
+import android.os.UserHandle;
import android.service.carrier.CarrierService;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
@@ -187,9 +188,15 @@
pkg.packageName = pkgCertInfo.pkgName;
pkg.signatures = new Signature[] {new Signature(pkgCertInfo.cert)};
- when(mPackageManager.getPackageInfo(
- eq(pkgCertInfo.pkgName), eq(PM_FLAGS)))
- .thenReturn(pkg);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.getPackageInfoAsUser(
+ eq(pkgCertInfo.pkgName), eq(PM_FLAGS), anyInt()))
+ .thenReturn(pkg);
+ } else {
+ when(mPackageManager.getPackageInfo(
+ eq(pkgCertInfo.pkgName), eq(PM_FLAGS)))
+ .thenReturn(pkg);
+ }
when(mPackageManager.getPackageUidAsUser(
eq(pkgCertInfo.pkgName), eq(pkgCertInfo.userInfo.id)))
.thenReturn(pkgCertInfo.uid);
@@ -214,7 +221,8 @@
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
CarrierPrivilegesTracker cpt =
- new CarrierPrivilegesTracker(mTestableLooper.getLooper(), mPhone, mContext);
+ new CarrierPrivilegesTracker(
+ mTestableLooper.getLooper(), mPhone, mContext, mFeatureFlags);
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0);
@@ -579,8 +587,14 @@
ResolveInfo pkg1ResolveInfo = new ResolveInfoBuilder().setActivity(PACKAGE_1).build();
ResolveInfo pkg2ResolveInfo = new ResolveInfoBuilder().setActivity(PACKAGE_2).build();
- when(mPackageManager.queryBroadcastReceivers(any(), anyInt())).thenReturn(
- List.of(pkg1ResolveInfo, pkg2ResolveInfo));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.queryBroadcastReceiversAsUser(any(), anyInt(),
+ anyInt())).thenReturn(
+ List.of(pkg1ResolveInfo, pkg2ResolveInfo));
+ } else {
+ when(mPackageManager.queryBroadcastReceivers(any(), anyInt())).thenReturn(
+ List.of(pkg1ResolveInfo, pkg2ResolveInfo));
+ }
// SIM is READY
sendSimCardStateChangedIntent(PHONE_ID, SIM_STATE_READY);
@@ -712,8 +726,13 @@
// Update PACKAGE_1 to have no signatures
PackageInfo pkg = new PackageInfo();
pkg.packageName = PACKAGE_1;
- when(mPackageManager.getPackageInfo(eq(PACKAGE_1), eq(PM_FLAGS)))
- .thenReturn(pkg);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.getPackageInfoAsUser(eq(PACKAGE_1), eq(PM_FLAGS), anyInt()))
+ .thenReturn(pkg);
+ } else {
+ when(mPackageManager.getPackageInfo(eq(PACKAGE_1), eq(PM_FLAGS)))
+ .thenReturn(pkg);
+ }
sendPackageChangedIntent(Intent.ACTION_PACKAGE_ADDED, PACKAGE_1);
mTestableLooper.processAllMessages();
@@ -784,19 +803,35 @@
setupInstalledPackages(
new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1),
new PackageCertInfo(PACKAGE_2, CERT_2, USER_1, UID_2));
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
- when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ } else {
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ }
ResolveInfo resolveInfoPkg1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
- doReturn(List.of(resolveInfoPkg1))
- .when(mPackageManager)
- .queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(resolveInfoPkg1))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ doReturn(List.of(resolveInfoPkg1))
+ .when(mPackageManager)
+ .queryIntentServices(any(), anyInt());
+ }
mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
// Package_1 is disabled
when(mPackageManager.getApplicationEnabledSetting(eq(PACKAGE_1))).thenReturn(
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
- doReturn(List.of()).when(
- mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of()).when(
+ mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ doReturn(List.of()).when(
+ mPackageManager).queryIntentServices(any(), anyInt());
+ }
sendPackageChangedIntent(Intent.ACTION_PACKAGE_CHANGED, PACKAGE_1);
mTestableLooper.processAllMessages();
@@ -807,8 +842,13 @@
// Package_1 is re-enabled
when(mPackageManager.getApplicationEnabledSetting(eq(PACKAGE_1))).thenReturn(
PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
- doReturn(List.of(resolveInfoPkg1)).when(
- mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(resolveInfoPkg1)).when(
+ mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ doReturn(List.of(resolveInfoPkg1)).when(
+ mPackageManager).queryIntentServices(any(), anyInt());
+ }
sendPackageChangedIntent(Intent.ACTION_PACKAGE_CHANGED, PACKAGE_1);
mTestableLooper.processAllMessages();
@@ -888,24 +928,45 @@
ResolveInfo privilegeBroadcast = new ResolveInfoBuilder().setActivity(PACKAGE_1).build();
ResolveInfo noPrivilegeBroadcast = new ResolveInfoBuilder().setActivity(PACKAGE_2).build();
- when(mPackageManager.queryBroadcastReceivers(any(), anyInt())).thenReturn(
- List.of(privilegeBroadcast, noPrivilegeBroadcast));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.queryBroadcastReceiversAsUser(any(), anyInt(),
+ anyInt())).thenReturn(
+ List.of(privilegeBroadcast, noPrivilegeBroadcast));
+ } else {
+ when(mPackageManager.queryBroadcastReceivers(any(), anyInt())).thenReturn(
+ List.of(privilegeBroadcast, noPrivilegeBroadcast));
+ }
ResolveInfo privilegeActivity = new ResolveInfoBuilder().setActivity(PACKAGE_3).build();
ResolveInfo noPrivilegeActivity = new ResolveInfoBuilder().setActivity(PACKAGE_4).build();
- when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(
- List.of(privilegeActivity, noPrivilegeActivity));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ List.of(privilegeActivity, noPrivilegeActivity));
+ } else {
+ when(mPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(
+ List.of(privilegeActivity, noPrivilegeActivity));
+ }
ResolveInfo privilegeService = new ResolveInfoBuilder().setService(PACKAGE_5).build();
ResolveInfo noPrivilegeService = new ResolveInfoBuilder().setService(PACKAGE_6).build();
// Use doReturn instead of when/thenReturn which has NPE with unknown reason
- doReturn(List.of(privilegeService, noPrivilegeService)).when(
- mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(privilegeService, noPrivilegeService)).when(
+ mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ doReturn(List.of(privilegeService, noPrivilegeService)).when(
+ mPackageManager).queryIntentServices(any(), anyInt());
+ }
ResolveInfo privilegeProvider = new ResolveInfoBuilder().setProvider(PACKAGE_7).build();
ResolveInfo noPrivilegeProvider = new ResolveInfoBuilder().setProvider(PACKAGE_8).build();
- when(mPackageManager.queryIntentContentProviders(any(), anyInt())).thenReturn(
- List.of(privilegeProvider, noPrivilegeProvider));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ when(mPackageManager.queryIntentContentProvidersAsUser(any(), anyInt(), anyInt()))
+ .thenReturn(List.of(privilegeProvider, noPrivilegeProvider));
+ } else {
+ when(mPackageManager.queryIntentContentProviders(any(), anyInt())).thenReturn(
+ List.of(privilegeProvider, noPrivilegeProvider));
+ }
mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
Intent intent = new Intent(CarrierService.CARRIER_SERVICE_INTERFACE);
@@ -934,11 +995,19 @@
ResolveInfo privilegeService = new ResolveInfoBuilder().setService(PACKAGE_1).build();
ResolveInfo noPrivilegeService = new ResolveInfoBuilder().setService(PACKAGE_2).build();
// Use doReturn instead of when/thenReturn which has NPE with unknown reason
- doReturn(List.of(privilegeService, noPrivilegeService)).when(
- mPackageManager).queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
- when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
- when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(privilegeService, noPrivilegeService)).when(
+ mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ } else {
+ doReturn(List.of(privilegeService, noPrivilegeService)).when(
+ mPackageManager).queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ }
// Get CS package name for the first time
mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
@@ -947,7 +1016,11 @@
mTestableLooper.processAllMessages();
// Package manager should be queried from
- verify(mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ verify(mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ verify(mPackageManager).queryIntentServices(any(), anyInt());
+ }
assertEquals(PACKAGE_1, carrierServicePackageName);
assertEquals(UID_1, carrierServiceUid);
@@ -958,7 +1031,11 @@
mTestableLooper.processAllMessages();
// It should return the same result, but didn't query package manager
- verify(mPackageManager, never()).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ verify(mPackageManager, never()).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ verify(mPackageManager, never()).queryIntentServices(any(), anyInt());
+ }
assertEquals(PACKAGE_1, carrierServicePackageName);
assertEquals(UID_1, carrierServiceUid);
}
@@ -978,12 +1055,21 @@
ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build();
// Use doReturn instead of when/thenReturn which has NPE with unknown reason
- doReturn(List.of(service1, service2))
- .when(mPackageManager)
- .queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
- when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
- when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(service1, service2))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ } else {
+ doReturn(List.of(service1, service2))
+ .when(mPackageManager)
+ .queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ }
// Verify that neither carrier service (no privileges, or carrier-config based privileges)
// are accepted.
@@ -992,7 +1078,11 @@
int carrierServiceUid = mCarrierPrivilegesTracker.getCarrierServicePackageUid();
mTestableLooper.processAllMessages();
- verify(mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ verify(mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ verify(mPackageManager).queryIntentServices(any(), anyInt());
+ }
assertNull(carrierServicePackageName);
assertEquals(Process.INVALID_UID, carrierServiceUid);
}
@@ -1008,11 +1098,19 @@
new PackageCertInfo(PACKAGE_3, CERT_1, USER_1, UID_1));
// No CarrierService declared at all
// Use doReturn instead of when/thenReturn which has NPE with unknown reason
- doReturn(List.of()).when(
- mPackageManager).queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
- when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
- when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of()).when(
+ mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ } else {
+ doReturn(List.of()).when(
+ mPackageManager).queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_3), anyInt())).thenReturn(UID_1);
+ }
mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
String carrierServicePackageName = mCarrierPrivilegesTracker.getCarrierServicePackageName();
@@ -1021,7 +1119,11 @@
assertNull(carrierServicePackageName);
assertEquals(Process.INVALID_UID, carrierServiceUid);
- verify(mPackageManager).queryIntentServices(any(), anyInt());
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ verify(mPackageManager).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ } else {
+ verify(mPackageManager).queryIntentServices(any(), anyInt());
+ }
}
@Test
@@ -1030,10 +1132,17 @@
setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1));
ResolveInfo carrierService = new ResolveInfoBuilder().setService(PACKAGE_1).build();
- doReturn(List.of(carrierService))
- .when(mPackageManager)
- .queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(carrierService))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ } else {
+ doReturn(List.of(carrierService))
+ .when(mPackageManager)
+ .queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ }
// Set override, and verify the carrier service package was not set due to a lack of a
// matching cert.
@@ -1056,11 +1165,19 @@
ResolveInfo service1 = new ResolveInfoBuilder().setService(PACKAGE_1).build();
ResolveInfo service2 = new ResolveInfoBuilder().setService(PACKAGE_2).build();
- doReturn(List.of(service1, service2))
- .when(mPackageManager)
- .queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
- when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(service1, service2))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ } else {
+ doReturn(List.of(service1, service2))
+ .when(mPackageManager)
+ .queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ when(mPackageManager.getPackageUid(eq(PACKAGE_2), anyInt())).thenReturn(UID_2);
+ }
mCarrierPrivilegesTracker = createCarrierPrivilegesTracker();
@@ -1093,10 +1210,17 @@
setupInstalledPackages(new PackageCertInfo(PACKAGE_1, CERT_1, USER_1, UID_1));
ResolveInfo carrierService = new ResolveInfoBuilder().setService(PACKAGE_1).build();
- doReturn(List.of(carrierService))
- .when(mPackageManager)
- .queryIntentServices(any(), anyInt());
- when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ doReturn(List.of(carrierService))
+ .when(mPackageManager)
+ .queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ } else {
+ doReturn(List.of(carrierService))
+ .when(mPackageManager)
+ .queryIntentServices(any(), anyInt());
+ when(mPackageManager.getPackageUid(eq(PACKAGE_1), anyInt())).thenReturn(UID_1);
+ }
// Set override, and expect that an invalid package name would not be selected as the
// carrier config service.
@@ -1114,21 +1238,40 @@
}
private void sendSimCardStateChangedIntent(int phoneId, int simState) {
- mContext.sendBroadcast(
- new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)
- .putExtra(EXTRA_SIM_STATE, simState)
- .putExtra(PhoneConstants.PHONE_KEY, phoneId));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ mContext.sendBroadcastAsUser(
+ new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)
+ .putExtra(EXTRA_SIM_STATE, simState)
+ .putExtra(PhoneConstants.PHONE_KEY, phoneId), UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(
+ new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED)
+ .putExtra(EXTRA_SIM_STATE, simState)
+ .putExtra(PhoneConstants.PHONE_KEY, phoneId));
+ }
}
private void sendSimApplicationStateChangedIntent(int phoneId, int simState) {
- mContext.sendBroadcast(
- new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)
- .putExtra(EXTRA_SIM_STATE, simState)
- .putExtra(PhoneConstants.PHONE_KEY, phoneId));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ mContext.sendBroadcastAsUser(
+ new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)
+ .putExtra(EXTRA_SIM_STATE, simState)
+ .putExtra(PhoneConstants.PHONE_KEY, phoneId), UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(
+ new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED)
+ .putExtra(EXTRA_SIM_STATE, simState)
+ .putExtra(PhoneConstants.PHONE_KEY, phoneId));
+ }
}
private void sendPackageChangedIntent(String action, String pkgName) {
- mContext.sendBroadcast(new Intent(action, new Uri.Builder().path(pkgName).build()));
+ if (mFeatureFlags.supportCarrierServicesForHsum()) {
+ mContext.sendBroadcastAsUser(
+ new Intent(action, new Uri.Builder().path(pkgName).build()), UserHandle.ALL);
+ } else {
+ mContext.sendBroadcast(new Intent(action, new Uri.Builder().path(pkgName).build()));
+ }
}
/** Returns the SHA-1 hash (as a hex String) for the given hex String. */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
index a3fcd4e..753f85c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
@@ -98,7 +98,7 @@
super.setUp(getClass().getSimpleName());
((MockContentResolver) mContext.getContentResolver()).addProvider(
CarrierId.AUTHORITY, new CarrierIdContentProvider());
- mCarrierResolver = new CarrierResolver(mPhone);
+ mCarrierResolver = new CarrierResolver(mPhone, mFeatureFlags);
mCarrierResolver.sendEmptyMessage(ICC_CHANGED_EVENT);
processAllMessages();
logd("CarrierResolverTest -Setup!");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 4612ad9..9788320 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -241,6 +241,14 @@
}
@Override
+ public boolean bindServiceAsUser(
+ Intent serviceIntent,
+ ServiceConnection connection,
+ int flags, UserHandle user) {
+ return bindService(serviceIntent, connection, flags);
+ }
+
+ @Override
public void unbindService(
ServiceConnection connection) {
IInterface service = mServiceByServiceConnection.remove(connection);
@@ -541,6 +549,12 @@
}
@Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, Bundle options) {
+ sendBroadcast(intent);
+ }
+
+ @Override
public void sendBroadcastMultiplePermissions(Intent intent,
String[] includePermissions, String[] excludePermissions) {
sendBroadcast(intent);
@@ -681,6 +695,9 @@
@Override
public void startActivity(Intent intent) {}
+
+ @Override
+ public void startActivityAsUser(Intent intent, UserHandle user) {}
}
private final Multimap<String, ComponentName> mComponentNamesByAction =
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 8209f92..da4bf50 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -23,7 +23,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.telephony.CellIdentityGsm;
import android.telephony.CellInfo;
@@ -101,23 +100,7 @@
}
@Test @SmallTest
- public void testNotifyDataActivity() throws Exception {
- when(mFeatureFlags.notifyDataActivityChangedWithSlot()).thenReturn(false);
- //mock data activity state
- doReturn(TelephonyManager.DATA_ACTIVITY_NONE).when(mPhone).getDataActivityState();
- mDefaultPhoneNotifierUT.notifyDataActivity(mPhone);
- verify(mTelephonyRegistryManager).notifyDataActivityChanged(eq(0),
- eq(TelephonyManager.DATA_ACTIVITY_NONE));
-
- doReturn(1).when(mPhone).getSubId();
- doReturn(TelephonyManager.DATA_ACTIVITY_IN).when(mPhone).getDataActivityState();
- mDefaultPhoneNotifierUT.notifyDataActivity(mPhone);
- verify(mTelephonyRegistryManager).notifyDataActivityChanged(eq(1),
- eq(TelephonyManager.DATA_ACTIVITY_IN));
- }
- @Test @SmallTest
public void testNotifyDataActivityWithSlot() throws Exception {
- when(mFeatureFlags.notifyDataActivityChangedWithSlot()).thenReturn(true);
//mock data activity state
doReturn(TelephonyManager.DATA_ACTIVITY_NONE).when(mPhone).getDataActivityState();
doReturn(PHONE_ID).when(mPhone).getPhoneId();
@@ -395,10 +378,64 @@
@Test
@SmallTest
+ public void testNotifyCallbackModeStarted() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ long durationMillis = 1000;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeStarted(mPhone, type, durationMillis);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeStarted(eq(phoneId), eq(subId),
+ eq(type), eq(durationMillis));
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyCallbackModeRestarted() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ long durationMillis = 1000;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeRestarted(mPhone, type, durationMillis);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeRestarted(eq(phoneId), eq(subId),
+ eq(type), eq(durationMillis));
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyCallbackModeStopped() {
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ int type = 1;
+ int reason = 0;
+
+ mDefaultPhoneNotifierUT.notifyCallbackModeStopped(mPhone, type, reason);
+
+ verify(mTelephonyRegistryManager).notifyCallbackModeStopped(eq(phoneId), eq(subId),
+ eq(type), eq(reason));
+ }
+
+ @Test
+ @SmallTest
public void testCarrierRoamingNtnModeChanged() {
int subId = mPhone.getSubId();
mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnModeChanged(mPhone, true);
verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnModeChanged(
eq(subId), eq(true));
}
+
+ @Test
+ @SmallTest
+ public void testCarrierRoamingNtnEligibleStateChanged() {
+ int subId = mPhone.getSubId();
+ mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnEligibleStateChanged(mPhone, true);
+ verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnEligibleStateChanged(
+ eq(subId), eq(true));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index a13a92c..c923f69 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -131,11 +131,14 @@
+ Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT 0,"
+ Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER
+ " INTEGER DEFAULT 1, "
- + Telephony.SimInfo.COLUMN_IS_NTN + " INTEGER DEFAULT 0,"
+ + Telephony.SimInfo.COLUMN_IS_ONLY_NTN + " INTEGER DEFAULT 0,"
+ Telephony.SimInfo.COLUMN_SERVICE_CAPABILITIES + " INTEGER DEFAULT 7,"
+ Telephony.SimInfo.COLUMN_TRANSFER_STATUS + " INTEGER DEFAULT 0,"
+ Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS + " INTEGER DEFAULT 0,"
- + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS + " TEXT"
+ + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS + " TEXT,"
+ + Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED + " INTEGER DEFAULT 0,"
+ + Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM
+ + " INTEGER DEFAULT 0"
+ ");";
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FdnUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/FdnUtilsTest.java
index 9da19bc..996fa2d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FdnUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FdnUtilsTest.java
@@ -181,4 +181,13 @@
assertTrue(FdnUtils.isFDN("1234560000@ims.mnc.org", "US", fdnList));
}
+
+ @Test
+ public void dialStrInNationalFormat_returnsTrue() {
+ ArrayList<AdnRecord> fdnList = initializeFdnList();
+ AdnRecord adnRecord = new AdnRecord(null, "0469887529");
+ fdnList.add(8, adnRecord);
+
+ assertTrue(FdnUtils.isFDN("0469887529", "US", fdnList));
+ }
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
index bad32e9..8898a0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
@@ -41,6 +41,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.IBootstrapAuthenticationCallback;
import android.telephony.TelephonyManager;
import android.telephony.gba.GbaAuthRequest;
@@ -51,8 +52,6 @@
import android.testing.TestableLooper;
import android.util.Log;
-import androidx.test.filters.SmallTest;
-
import com.android.internal.telephony.metrics.RcsStats;
import org.junit.After;
@@ -66,7 +65,7 @@
*/
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public final class GbaManagerTest {
+public final class GbaManagerTest extends TelephonyTest {
private static final String LOG_TAG = "GbaManagerTest";
private static final ComponentName TEST_DEFAULT_SERVICE_NAME = new ComponentName(
@@ -91,6 +90,7 @@
@Before
public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
log("setUp");
mMockContext = mock(Context.class);
mMockBinder = mock(IBinder.class);
@@ -100,7 +100,8 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
+ .thenReturn(true);
when(mMockGbaServiceBinder.asBinder()).thenReturn(mMockBinder);
mTestGbaManager = new GbaManager(mMockContext, TEST_SUB_ID, null, 0, mMockRcsStats);
mHandler = mTestGbaManager.getHandler();
@@ -109,137 +110,129 @@
} catch (Exception e) {
fail("Unable to create looper from handler.");
}
+ monitorTestableLooper(mLooper);
}
@After
public void tearDown() throws Exception {
log("tearDown");
mTestGbaManager.destroy();
- mTestGbaManager = null;
- mHandler = null;
- mLooper.destroy();
- mLooper = null;
+ super.tearDown();
}
@Test
- @SmallTest
public void testFailOnRequest() throws Exception {
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
verify(mMockCallback).onAuthenticationFailure(anyInt(), anyInt());
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testBindServiceOnRequest() throws Exception {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
- mLooper.processAllMessages();
+ processAllMessages();
verify(mMockGbaServiceBinder).authenticationRequest(any());
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testFailAndRetryOnRequest() throws RemoteException {
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(false);
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
+ .thenReturn(false);
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
for (int i = 0; i < GbaManager.MAX_RETRY; i++) {
- mLooper.processAllMessages();
- verify(mMockContext, times(i + 1)).bindService(any(), any(), anyInt());
- try {
- Thread.sleep(GbaManager.RETRY_TIME_MS + 500);
- } catch (InterruptedException e) {
- }
+ processAllMessages();
+ verify(mMockContext, times(i + 1)).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
+ moveTimeForward(GbaManager.REQUEST_TIMEOUT_MS);
}
assertTrue(!mTestGbaManager.isServiceConnected());
- mLooper.processAllMessages();
+ processAllMessages();
verify(mMockCallback).onAuthenticationFailure(anyInt(), anyInt());
}
@Test
- @SmallTest
public void testBindServiceWhenPackageNameChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
GbaAuthRequest request = createDefaultRequest();
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ServiceConnection conn = bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
- mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName(), 123);
assertEquals(TEST_SERVICE2_NAME.getPackageName(), mTestGbaManager.getServicePackage());
- mLooper.processAllMessages();
+ processAllMessages();
unbindService(conn);
bindAndConnectService(TEST_SERVICE2_NAME);
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testBindServiceWhenReleaseTimeChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
assertEquals(RELEASE_NEVER, mTestGbaManager.getReleaseTime());
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
assertTrue(mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testDontBindServiceWhenPackageNameChanged() {
- mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName(), 123);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testDontBindServiceWhenReleaseTimeChanged() {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
- mLooper.processAllMessages();
+ processAllMessages();
- verify(mMockContext, never()).bindService(any(), any(), anyInt());
+ verify(mMockContext, never()).bindServiceAsUser(any(), any(), anyInt(),
+ any(UserHandle.class));
assertTrue(!mTestGbaManager.isServiceConnected());
}
@Test
- @SmallTest
public void testMetricsGbaEvent() throws Exception {
- mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName());
+ mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
- mLooper.processAllMessages();
+ processAllMessages();
bindAndConnectService(TEST_DEFAULT_SERVICE_NAME);
GbaAuthRequest request = createDefaultRequest();
// Failure case
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ArgumentCaptor<GbaAuthRequest> captor = ArgumentCaptor.forClass(GbaAuthRequest.class);
verify(mMockGbaServiceBinder, times(1)).authenticationRequest(captor.capture());
@@ -254,7 +247,7 @@
// Success case
mTestGbaManager.bootstrapAuthenticationRequest(request);
- mLooper.processAllMessages();
+ processAllMessages();
ArgumentCaptor<GbaAuthRequest> captor2 = ArgumentCaptor.forClass(GbaAuthRequest.class);
verify(mMockGbaServiceBinder, times(2)).authenticationRequest(captor2.capture());
@@ -280,9 +273,10 @@
ArgumentCaptor.forClass(Intent.class);
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- verify(mMockContext, atLeastOnce()).bindService(intentCaptor.capture(),
+ verify(mMockContext, atLeastOnce()).bindServiceAsUser(intentCaptor.capture(),
serviceCaptor.capture(), eq(
- Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE));
+ Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+ any(UserHandle.class));
Intent testIntent = intentCaptor.getValue();
assertEquals(GbaService.SERVICE_INTERFACE, testIntent.getAction());
assertEquals(component.getPackageName(), testIntent.getPackage());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
index 45f8c12..e56ac90 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
@@ -21,10 +21,12 @@
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
+import android.telephony.emergency.EmergencyNumber;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -313,4 +315,52 @@
assertEquals(DisconnectCause.OUT_OF_SERVICE,
connection.disconnectCauseFromCode(CallFailCause.LOCAL_SERVICE_UNAVAILABLE));
}
+
+ @Test
+ public void testUpdateEmergencyRouting() {
+ Bundle extras = new Bundle();
+ extras.putBoolean(PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, true);
+
+ DialArgs dialArgs = new DialArgs.Builder()
+ .setIsEmergency(true)
+ .setIntentExtras(extras)
+ .build();
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ connection = new GsmCdmaConnection(mPhone, "911", mCT, null, dialArgs);
+ // Not updated when category is unset.
+ assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+ extras.putInt(PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED);
+
+ dialArgs = new DialArgs.Builder()
+ .setIsEmergency(true)
+ .setIntentExtras(extras)
+ .build();
+
+ connection = new GsmCdmaConnection(mPhone, "911", mCT, null, dialArgs);
+ // Not updated when category is EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED.
+ assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+ extras.putInt(PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+
+ dialArgs = new DialArgs.Builder()
+ .setIsEmergency(true)
+ .setIntentExtras(extras)
+ .build();
+
+ connection = new GsmCdmaConnection(mPhone, "911", mCT, null, dialArgs);
+
+ EmergencyNumber expectedNumber = new EmergencyNumber("911", "us", "30",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+ new ArrayList<String>(), EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
+ // Updated when category is not EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED.
+ assertNotEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+ assertEquals(expectedNumber, connection.getEmergencyNumberInfo());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index ba08f8b..7735c97 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -2018,6 +2018,42 @@
@Test
@SmallTest
+ public void testUsageSettingUpdate_ResetToDefault() {
+ setupUsageSettingResources();
+ mPhoneUT.mCi = mMockCi;
+
+ SubscriptionInfoInternal si = makeSubscriptionInfoInternal(
+ false, SubscriptionManager.USAGE_SETTING_DATA_CENTRIC);
+ doReturn(si).when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
+ mPhoneUT.updateUsageSetting();
+ processAllMessages();
+
+ verify(mMockCi).getUsageSetting(any());
+ mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_GET_USAGE_SETTING_DONE,
+ new AsyncResult(null,
+ new int[]{SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC}, null)));
+ processAllMessages();
+
+ // Grab the message to ensure it returns the preferred value for updating the cache
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockCi).setUsageSetting(
+ messageCaptor.capture(), eq(SubscriptionManager.USAGE_SETTING_DATA_CENTRIC));
+ AsyncResult.forMessage(messageCaptor.getValue());
+ messageCaptor.getValue().sendToTarget();
+ processAllMessages();
+
+ si = makeSubscriptionInfoInternal(false, SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC);
+ doReturn(si).when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
+ mPhoneUT.updateUsageSetting();
+ processAllMessages();
+
+ verify(mMockCi).setUsageSetting(any(), eq(SubscriptionManager.USAGE_SETTING_VOICE_CENTRIC));
+ }
+
+ @Test
+ @SmallTest
public void testUsageSettingUpdate_DefaultOpportunistic() {
setupUsageSettingResources();
mPhoneUT.mCi = mMockCi;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
index f64155c..6c84b08 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ImsSmsDispatcherTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Binder;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SmsMessage;
@@ -71,6 +72,7 @@
PersistableBundle mBundle = new PersistableBundle();
private static final int SUB_0 = 0;
private static final String TAG = "ImsSmsDispatcherTest";
+ private int mCallingUserId;
@Before
public void setUp() throws Exception {
@@ -94,6 +96,7 @@
mTrackerData = new HashMap<>(1);
when(mSmsTracker.getData()).thenReturn(mTrackerData);
verify(mSmsDispatchersController).setImsManager(mImsManager);
+ mCallingUserId = Binder.getCallingUserHandle().getIdentifier();
}
@After
@@ -333,8 +336,7 @@
doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mImsSmsDispatcher.sendText("+15555551212", null, "MessageRef test",
- null, null, null, null, false,
- -1, false, -1, false, 0);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0);
verify(mImsManager).sendSms(eq(token + 1), eq(messageRef), eq(SmsMessage.FORMAT_3GPP),
nullable(String.class), eq(false), (byte[]) any());
}
@@ -349,8 +351,7 @@
doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mImsSmsDispatcher.sendText("+15555551212", null, "MessageRef test",
- null, null, null, null, false,
- -1, false, -1, false, 0);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0);
verify(mImsManager).sendSms(eq(token + 1), eq(messageRef), eq(SmsMessage.FORMAT_3GPP),
nullable(String.class), eq(false), (byte[]) any());
@@ -384,8 +385,7 @@
doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mImsSmsDispatcher.sendText("+15555551212", null, "MessageRef test",
- null, null, null, null, false,
- -1, false, -1, false, 0);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0);
verify(mImsManager).sendSms(eq(token + 1), eq(messageRef), eq(SmsMessage.FORMAT_3GPP),
nullable(String.class), eq(false), (byte[]) any());
@@ -423,8 +423,7 @@
when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
mImsSmsDispatcher.sendText("+15555551212", null, "Retry test",
- null, null, null, null, false,
- -1, false, -1, false, 0);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0);
verify(mImsManager).sendSms(eq(token + 1), eq(messageRef), eq(SmsMessage.FORMAT_3GPP),
nullable(String.class), eq(false), (byte[]) any());
assertEquals(2, mImsSmsDispatcher.getMaxRetryCountOverIms());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index e08abd9..f92643a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1507,6 +1507,52 @@
}
@Test
+ public void testTransitionToNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ // use advanced band
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // empty PCC, switch to connected_rrc_idle,
+ // isNrAdvanced is still true(due to either advance band OR frequency)
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, physicalChannelConfigs, null));
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // Received an event update, verify should stay in idle because physical link didn't change,
+ // otherwise there is a loop between advance state and idle state.
+ mNetworkTypeController.sendMessage(0 /* EVENT_UPDATE */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
public void testSecondaryTimerAdvanceBand() throws Exception {
doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
@@ -1603,8 +1649,23 @@
mNetworkTypeController.getOverrideNetworkType());
assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // the timer has been reduced from 20 - 6s(advance band) to 5s(regular). Suppose passed 1s,
+ // a new PCC shouldn't affect the timer.
+ moveTimeForward(1 * 1000);
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, Collections.emptyList(), null));
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, List.of(
+ new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(3)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build()), null));
+ processAllMessages();
+
// Verify the timer has been reduced from 20 - 6s(advance band) to 5s(regular).
- moveTimeForward(5 * 1000);
+ moveTimeForward(4 * 1000);
processAllMessages();
assertEquals("connected_rrc_idle", getCurrentState().getName());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index 0e04aff..b09d90d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -203,26 +203,40 @@
for (int i : enabledLogicalSlots) { expectedSlots.add(i); }
assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
}
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupportBothInvalidSlotIds() throws Exception {
+ // Test case where both slot IDs are invalid (-1 and 5).
+ testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(-1, 5));
+ }
@Test
@SmallTest
- public void testUpdateSimultaneousCallingSupport_invalidResponse_shouldFail() throws Exception {
- doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
- init(2);
- mPcm.updateSimultaneousCallingSupport();
+ public void testUpdateSimultaneousCallingSupportOneInvalidSlotId() throws Exception {
+ // Test case where one slot ID is valid (1) and the other is invalid (2).
+ testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(1, 2));
+ }
- // Have the modem send invalid phone slots -1 and 5:
- List<Integer> invalidEnabledLogicalSlots = Arrays.asList(-1, 5);
- ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
- verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
- Message msg = captor.getValue();
- AsyncResult.forMessage(msg, invalidEnabledLogicalSlots, null);
- msg.sendToTarget();
- processAllMessages();
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupportInvalidExtraSlotId() throws Exception {
+ // Test case where the number of slot IDs exceeds the phone count (2) and one slot ID is
+ // invalid (2).
+ testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(0, 1, 2));
+ }
- // We would expect to DSDA to be disabled and mSlotsSupportingSimultaneousCellularCalls to
- // have been cleared:
- assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty());
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupportInvalidSingularSlotId() throws Exception {
+ // Test case where only a single, invalid slot ID (0) is provided.
+ testUpdateSimultaneousCallingSupportWithInvalidSlots(List.of(0));
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateSimultaneousCallingSupportInvalidEmptySlotIds() throws Exception {
+ // Test case where an empty list of slot IDs is provided.
+ testUpdateSimultaneousCallingSupportWithInvalidSlots(List.of());
}
/**
@@ -576,4 +590,28 @@
assertEquals(capability, mPcm.getStaticPhoneCapability());
}
+
+ private void testUpdateSimultaneousCallingSupportWithInvalidSlots(List<Integer> invalidSlots)
+ throws Exception {
+ doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
+ init(2);
+ mPcm.updateSimultaneousCallingSupport();
+
+ sendInvalidSlotsToModem(invalidSlots);
+ processAllMessages();
+
+ assertDsdaDisabledAndSlotsCleared();
+ }
+
+ private void sendInvalidSlotsToModem(List<Integer> invalidSlots) {
+ ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+ verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+ Message msg = captor.getValue();
+ AsyncResult.forMessage(msg, invalidSlots, null);
+ msg.sendToTarget();
+ }
+
+ private void assertDsdaDisabledAndSlotsCleared() {
+ assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index bf9ced3..7a30984 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -628,6 +628,7 @@
public void testFormatSingaporeInternational() {
// Disable feature flag.
mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
// International call from a US iso
assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US"));
@@ -636,6 +637,7 @@
assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));
// Enable feature flag
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
// Internal call from a US iso
@@ -644,6 +646,7 @@
// Lowercase country iso
assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));
mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
}
/**
@@ -655,14 +658,16 @@
public void testFormatSingaporeNational() {
// Disable feature flag.
mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
// Local call from a Singaporean number to a Singaporean number
- assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));
+ assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));
// Lowercase country iso.
- assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
+ assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
// Enable feature flag.
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
// Local call from a Singaporean number to a Singaporean number.
@@ -671,6 +676,44 @@
// Lowercase country iso.
assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ }
+
+ @SmallTest
+ @Test
+ public void testFormatTaiwanNational() {
+ // Disable feature flag.
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "TW"));
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "tw"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "TW"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "tw"));
+
+ // Enable feature flag.
+ mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ assertEquals("02 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "TW"));
+ assertEquals("02 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "tw"));
+ assertEquals("0988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "TW"));
+ assertEquals("0988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "tw"));
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ }
+
+ @SmallTest
+ @Test
+ public void testFormatTaiwanInternational() {
+ // Disable feature flag.
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "US"));
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "us"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "US"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "us"));
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "US"));
+ assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "us"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "US"));
+ assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "us"));
+ mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
}
@SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 88c5389..48c9f9c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -175,6 +175,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.SparseArray;
+import android.view.Display;
import androidx.test.filters.FlakyTest;
@@ -312,6 +313,7 @@
} catch (RuntimeException e) {
}
Context context = new ContextFixture().getTestDouble();
+ doReturn(Display.DEFAULT_DISPLAY).when(context).getDisplayId();
doReturn(true).when(mConnectionManager).isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
doReturn(mConnectionManager).when(context)
.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index e3da458..9bee1ac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.nullable;
@@ -594,7 +595,7 @@
sst.setRadioPowerForReason(false, false, false, false, reason);
assertTrue(sst.getRadioPowerOffReasons().contains(reason));
assertTrue(sst.getRadioPowerOffReasons().size() == 1);
- verify(mSatelliteController).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(false));
clearInvocations(mSatelliteController);
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
@@ -602,7 +603,7 @@
TelephonyManager.RADIO_POWER_REASON_USER);
assertTrue(sst.getRadioPowerOffReasons().contains(reason));
assertTrue(sst.getRadioPowerOffReasons().size() == 1);
- verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController, never()).onSetCellularRadioPowerStateRequested(anyBoolean());
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
@@ -610,7 +611,7 @@
// had been turned off for.
sst.setRadioPowerForReason(true, false, false, false, reason);
assertTrue(sst.getRadioPowerOffReasons().isEmpty());
- verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(true));
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
@@ -1928,6 +1929,8 @@
sst.setRadioPower(false);
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(false));
+ verify(mSatelliteController).onPowerOffCellularRadioFailed();
sst.requestShutdown();
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertFalse(mSimulatedCommands.getRadioState()
@@ -2980,7 +2983,7 @@
doReturn(ServiceState.STATE_IN_SERVICE).when(mSST).getCombinedRegState(ss);
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "Emergency call only"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3002,7 +3005,7 @@
sst.mSS = ss;
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3023,7 +3026,7 @@
sst.mSS = ss;
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is null
Bundle b = getExtrasFromLastSpnUpdateIntent();
@@ -3046,7 +3049,7 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Show both spn & plmn
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3082,12 +3085,13 @@
doReturn(mImsPhone).when(mPhone).getImsPhone();
doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM).when(mImsPhone)
.getImsRegistrationTech();
+ doReturn(true).when(mPhone).isImsRegistered();
String[] formats = {CROSS_SIM_CALLING_VOICE_FORMAT, "%s"};
Resources r = mContext.getResources();
doReturn(formats).when(r).getStringArray(anyInt());
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only spn should be shown
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3124,7 +3128,7 @@
doReturn(true).when(mPhone).isImsRegistered();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only spn should be shown
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3157,7 +3161,7 @@
doReturn(true).when(mPhone).isImsRegistered();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Only plmn should be shown
String plmn = mBundle.getStringArray(CarrierConfigManager.KEY_PNN_OVERRIDE_STRING_ARRAY)[0];
@@ -3183,7 +3187,7 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
// Show both spn & plmn
String spn = mBundle.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
@@ -3236,7 +3240,70 @@
doReturn(false).when(mPhone).isWifiCallingEnabled();
// update the spn
- sst.updateSpnDisplay();
+ sst.updateCarrierDisplayName();
+
+ // Plmn should be shown, and the string is "No service"
+ Bundle b = getExtrasFromLastSpnUpdateIntent();
+ assertThat(b.getString(TelephonyManager.EXTRA_PLMN))
+ .isEqualTo(CARRIER_NAME_DISPLAY_NO_SERVICE);
+ assertThat(b.getBoolean(TelephonyManager.EXTRA_SHOW_PLMN)).isTrue();
+ }
+
+ @Test
+ public void testUpdateSpnDisplayLegacy_CrossSimCallingDataOOS_displayOOS() {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
+ sendCarrierConfigUpdate(PHONE_ID);
+
+ // GSM phone
+ doReturn(true).when(mPhone).isPhoneTypeGsm();
+
+ // Reg tech is Cross Sim but both data and voice are OOS
+ doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
+ doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegistrationState();
+ doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mServiceState).getDataNetworkType();
+ doReturn(mImsPhone).when(mPhone).getImsPhone();
+ doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM).when(
+ mImsPhone).getImsRegistrationTech();
+ sst.mSS = mServiceState;
+
+ // wifi-calling is enabled
+ doReturn(true).when(mPhone).isWifiCallingEnabled();
+
+ // update the spn
+ sst.updateCarrierDisplayName();
+
+ // Plmn should be shown, and the string is "No service"
+ Bundle b = getExtrasFromLastSpnUpdateIntent();
+ assertThat(b.getString(TelephonyManager.EXTRA_PLMN))
+ .isEqualTo(CARRIER_NAME_DISPLAY_NO_SERVICE);
+ assertThat(b.getBoolean(TelephonyManager.EXTRA_SHOW_PLMN)).isTrue();
+ }
+
+ @Test
+ public void testUpdateSpnDisplayLegacy_CrossSimCallingVoiceOOS_displayOOS() {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
+ sendCarrierConfigUpdate(PHONE_ID);
+
+ // GSM phone
+ doReturn(true).when(mPhone).isPhoneTypeGsm();
+
+ // voice out of service but data in service (connected to Cross Sim IWLAN)
+ doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
+ doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getDataRegistrationState();
+ doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mServiceState).getDataNetworkType();
+ doReturn(mImsPhone).when(mPhone).getImsPhone();
+ doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM).when(
+ mImsPhone).getImsRegistrationTech();
+ doReturn(false).when(mPhone).isImsRegistered();
+ sst.mSS = mServiceState;
+
+ // wifi-calling is enabled
+ doReturn(true).when(mPhone).isWifiCallingEnabled();
+
+ // update the spn
+ sst.updateCarrierDisplayName();
// Plmn should be shown, and the string is "No service"
Bundle b = getExtrasFromLastSpnUpdateIntent();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
index 879b184..6fd45ea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
@@ -134,7 +134,6 @@
.getSubscriptionInfo(any(Integer.class));
doReturn(RIL.RADIO_HAL_VERSION_2_2).when(mMockRadioConfigProxy).getVersion();
doReturn(true).when(mFeatureFlags).simultaneousCallingIndications();
- doReturn(true).when(mFeatureFlags).dataOnlyCellularService();
mMockRegistryManager = mContext.getSystemService(TelephonyRegistryManager.class);
}
@@ -254,7 +253,7 @@
/**
* Test that simultaneous calling is not supported when IMS is not registered and cellular
- * simultaneous calling is only supported for one SIM subscription.
+ * simultaneous calling is not supported for any SIM subscriptions.
*/
@Test
@SmallTest
@@ -264,8 +263,8 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- // Have the modem inform telephony that only phone slot 0 supports DSDA:
- List<Integer> enabledLogicalSlots = List.of(0);
+ // Have the modem inform telephony that no phone slots currently support DSDA:
+ List<Integer> enabledLogicalSlots = List.of();
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
index 06dbd0b..710f1ec 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
@@ -31,6 +31,7 @@
import android.compat.testing.PlatformCompatChangeRule;
import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
@@ -67,6 +68,7 @@
private SmsController mSmsControllerUT;
private final String smscAddrStr = "+1206313004";
private String mCallingPackage;
+ private int mCallingUserId;
@Before
public void setUp() throws Exception {
@@ -74,6 +76,7 @@
mAdnRecordCache = Mockito.mock(AdnRecordCache.class);
mSmsControllerUT = new SmsController(mContext, mFeatureFlags);
mCallingPackage = mContext.getOpPackageName();
+ mCallingUserId = Binder.getCallingUserHandle().getIdentifier();
doReturn(true).when(mPackageManager).hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_MESSAGING);
@@ -196,9 +199,9 @@
doReturn(true).when(mSubscriptionManager)
.isSubscriptionAssociatedWithUser(eq(subId), any());
- mSmsControllerUT.sendVisualVoicemailSmsForSubscriber(mCallingPackage,null ,
- subId, null, 0, null, null);
- verify(mIccSmsInterfaceManager).sendTextWithSelfPermissions(any(),
+ mSmsControllerUT.sendVisualVoicemailSmsForSubscriber(mCallingPackage, mCallingUserId,
+ null , subId, null, 0, null, null);
+ verify(mIccSmsInterfaceManager).sendTextWithSelfPermissions(any(), eq(mCallingUserId),
any(), any(), any(), any(), any(), any(), eq(false), eq(true));
}
@@ -206,10 +209,11 @@
public void sendVisualVoicemailSmsForSubscriber_phoneIsInEcm() {
doReturn(true).when(mPhone).isInEcm();
- mSmsControllerUT.sendVisualVoicemailSmsForSubscriber(mCallingPackage,null ,
- 1, null, 0, null, null);
+ mSmsControllerUT.sendVisualVoicemailSmsForSubscriber(mCallingPackage, mCallingUserId,
+ null , 1, null, 0, null, null);
verify(mIccSmsInterfaceManager, never()).sendTextWithSelfPermissions(any(),
- any(), any(), any(), any(), any(), any(), eq(false), eq(true));
+ eq(mCallingUserId), any(), any(), any(), any(), any(), any(),
+ eq(false), eq(true));
doReturn(false).when(mPhone).isInEcm();
}
@@ -223,7 +227,8 @@
mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
null, "text", null, null, false, 0L, true, true);
verify(mIccSmsInterfaceManager, Mockito.times(1))
- .sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
+ .sendText(mCallingPackage, mCallingUserId,
+ "1234", null, "text", null, null, false, 0L, true);
}
@Test
@@ -239,7 +244,8 @@
mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
null, "text", null, null, false, 0L, true, true);
verify(mIccSmsInterfaceManager, Mockito.times(1))
- .sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
+ .sendText(mCallingPackage, mCallingUserId,
+ "1234", null, "text", null, null, false, 0L, true);
}
@Test
@@ -255,7 +261,8 @@
mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
null, "text", null, null, false, 0L, true, true);
verify(mIccSmsInterfaceManager, Mockito.times(0))
- .sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
+ .sendText(mCallingPackage, mCallingUserId,
+ "1234", null, "text", null, null, false, 0L, true);
}
@Test
@@ -320,6 +327,7 @@
mSmsControllerUT.sendTextForSubscriber(subId, mCallingPackage, null, "1234",
null, "text", null, null, false, 0L, true, true);
verify(mIccSmsInterfaceManager, Mockito.times(1))
- .sendText(mCallingPackage, "1234", null, "text", null, null, false, 0L, true);
+ .sendText(mCallingPackage, mCallingUserId,
+ "1234", null, "text", null, null, false, 0L, true);
}
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 414fb3b..8f0cbbb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -24,10 +25,12 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -64,6 +67,7 @@
import com.android.internal.telephony.domainselection.SmsDomainSelectionConnection;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.DatagramDispatcher;
import com.android.internal.telephony.uicc.IccUtils;
import org.junit.After;
@@ -94,35 +98,42 @@
return getDomainSelectionConnectionHolder(emergency);
}
- public void testSendData(String callingPackage, String destAddr, String scAddr,
- int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
- sendData(callingPackage, destAddr, scAddr,
+ public void testSendData(String callingPackage, int callingUser,
+ String destAddr, String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+ PendingIntent deliveryIntent, boolean isForVvm) {
+ sendData(callingPackage, callingUser, destAddr, scAddr,
destPort, data, sentIntent, deliveryIntent, isForVvm);
}
public void testSendMultipartText(String destAddr, String scAddr,
ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
ArrayList<PendingIntent> deliveryIntents, Uri messageUri, String callingPkg,
- boolean persistMessage, int priority, boolean expectMore, int validityPeriod,
- long messageId) {
+ int callingUser, boolean persistMessage, int priority, boolean expectMore,
+ int validityPeriod, long messageId) {
sendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents, messageUri,
- callingPkg, persistMessage, priority, expectMore, validityPeriod, messageId);
+ callingPkg, callingUser, persistMessage, priority, expectMore,
+ validityPeriod, messageId);
}
public void testNotifySmsSentToEmergencyStateTracker(String destAddr, long messageId,
boolean isOverIms, boolean isLastSmsPart) {
- notifySmsSentToEmergencyStateTracker(destAddr, messageId, isOverIms, isLastSmsPart);
+ notifySmsSent(getSmsTracker(destAddr, messageId), isOverIms,
+ isLastSmsPart, true/*success*/);
}
public void testNotifySmsSentFailedToEmergencyStateTracker(String destAddr,
long messageId, boolean isOverIms) {
- notifySmsSentFailedToEmergencyStateTracker(destAddr, messageId, isOverIms);
+ notifySmsSent(getSmsTracker(destAddr, messageId), isOverIms,
+ true/*isLastSmsPart*/, false/*success*/);
}
public void testNotifySmsReceivedViaImsToEmergencyStateTracker(String origAddr) {
notifySmsReceivedViaImsToEmergencyStateTracker(origAddr);
}
+
+ private SMSDispatcher.SmsTracker getSmsTracker(String destAddr, long messageId) {
+ return new SMSDispatcher.SmsTracker(destAddr, messageId);
+ }
}
/**
@@ -134,11 +145,11 @@
}
@Override
- public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
- super.sendData(callingPackage, destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent, isForVvm);
+ public void sendData(String callingPackage, int callingUser, String destAddr,
+ String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+ PendingIntent deliveryIntent, boolean isForVvm, long uniqueMessageId) {
+ super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
+ data, sentIntent, deliveryIntent, isForVvm, uniqueMessageId);
}
@Override
@@ -161,11 +172,11 @@
}
@Override
- public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
- boolean isForVvm) {
- super.sendData(callingPackage, destAddr, scAddr, destPort,
- data, sentIntent, deliveryIntent, isForVvm);
+ public void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ boolean isForVvm, long uniqueMessageId) {
+ super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
+ data, sentIntent, deliveryIntent, isForVvm, uniqueMessageId);
}
@Override
@@ -191,15 +202,21 @@
private TestSmsDispatchersController mSmsDispatchersController;
private boolean mInjectionCallbackTriggered = false;
private CompletableFuture<Integer> mDscFuture;
+ private DatagramDispatcher mMockDatagramDispatcher;
+ private int mCallingUserId;
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
mTracker = mock(SMSDispatcher.SmsTracker.class);
mFeatureFlags = mock(FeatureFlags.class);
+ mMockDatagramDispatcher = mock(DatagramDispatcher.class);
+ replaceInstance(DatagramDispatcher.class, "sInstance", null,
+ mMockDatagramDispatcher);
setupMockPackagePermissionChecks();
mSmsDispatchersController = new TestSmsDispatchersController(mPhone, mSmsStorageMonitor,
mSmsUsageMonitor, mTestableLooper.getLooper(), mFeatureFlags);
+ mCallingUserId = mContext.getUserId();
processAllMessages();
}
@@ -234,7 +251,7 @@
@Test @SmallTest
public void testReportSmsMemoryStatus() throws Exception {
int eventReportMemoryStatusDone = 3;
- SmsStorageMonitor smsStorageMonnitor = new SmsStorageMonitor(mPhone);
+ SmsStorageMonitor smsStorageMonnitor = new SmsStorageMonitor(mPhone, mFeatureFlags);
Message result = smsStorageMonnitor.obtainMessage(eventReportMemoryStatusDone);
ImsSmsDispatcher mImsSmsDispatcher = Mockito.mock(ImsSmsDispatcher.class);
mSmsDispatchersController.setImsSmsDispatcher(mImsSmsDispatcher);
@@ -247,7 +264,7 @@
@Test @SmallTest
public void testReportSmsMemoryStatusFailure() throws Exception {
int eventReportMemoryStatusDone = 3;
- SmsStorageMonitor smsStorageMonnitor = new SmsStorageMonitor(mPhone);
+ SmsStorageMonitor smsStorageMonnitor = new SmsStorageMonitor(mPhone, mFeatureFlags);
Message result = smsStorageMonnitor.obtainMessage(eventReportMemoryStatusDone);
mSmsDispatchersController.setImsSmsDispatcher(null);
mSmsDispatchersController.reportSmsMemoryStatus(result);
@@ -259,7 +276,7 @@
public void testSendImsGmsTest() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
mSmsDispatchersController.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier).sendImsGsmSms(eq("038122F2"),
eq("0100038111F100001CD3F69C989EC3C3F431BA2C9F0FDF6EBAFCCD6697E5D4F29C0E"), eq(0), eq(0),
any(Message.class));
@@ -269,7 +286,7 @@
public void testSendImsGmsTestWithOutDesAddr() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
mSmsDispatchersController.sendText(null, "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier, times(0)).sendImsGsmSms(anyString(), anyString(),
anyInt(), anyInt(), any(Message.class));
}
@@ -278,7 +295,7 @@
public void testSendImsCdmaTest() throws Exception {
switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
mSmsDispatchersController.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier).sendImsCdmaSms((byte[])any(), eq(0), eq(0),
any(Message.class));
}
@@ -353,7 +370,8 @@
mSmsDispatchersController.sendText("111", null /*scAddr*/, TAG,
null, null, null, "com.android.messaging",
- false, -1, false, -1, false, 0L);
+ mContext.getUserId(), false, -1, false,
+ -1, false, 0L);
byte[] smscbyte = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
"222");
String smsc = IccUtils.bytesToHexString(smscbyte);
@@ -462,7 +480,7 @@
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -479,8 +497,8 @@
verify(mEmergencySmsDsc).finishSelection();
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(mCallingUserId), eq(false),
+ eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -494,7 +512,7 @@
setUpEmergencyStateTracker(DisconnectCause.OUT_OF_SERVICE);
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
// Verify the domain selection requested regardless of the result of EmergencyStateTracker.
@@ -512,7 +530,7 @@
ArrayList<PendingIntent> sentIntents = new ArrayList<>();
ArrayList<PendingIntent> deliveryIntents = new ArrayList<>();
mSmsDispatchersController.testSendMultipartText("911", "2222", parts, sentIntents,
- deliveryIntents, null, "test-app", false, 0, false, 10, 1L);
+ deliveryIntents, null, "test-app", mCallingUserId, false, 0, false, 10, 1L);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -529,8 +547,9 @@
verify(mEmergencySmsDsc).finishSelection();
verify(mImsSmsDispatcher).sendMultipartText(eq("911"), eq("2222"), eq(parts),
- eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(false), eq(0),
- eq(false), eq(10), eq(1L));
+ eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"),
+ eq(mCallingUserId), eq(false), eq(0), eq(false),
+ eq(10), eq(1L), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -703,7 +722,7 @@
when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -728,8 +747,8 @@
assertEquals(0, holder.getPendingRequests().size());
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0), eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -743,7 +762,8 @@
when(mImsSmsDispatcher.isEmergencySmsSupport(anyString())).thenReturn(true);
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false,
+ 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -768,8 +788,8 @@
assertEquals(0, holder.getPendingRequests().size());
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -779,7 +799,7 @@
setUpSmsDispatchers();
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -790,7 +810,7 @@
assertEquals(1, holder.getPendingRequests().size());
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
verify(mSmsDsc).requestDomainSelection(any(), any());
@@ -802,9 +822,10 @@
processAllMessages();
verify(mSmsDsc).finishSelection();
- verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"), eq("text"),
- eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"),
+ eq("text"), eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0), eq(false), eq(10), eq(false), eq(1L),
+ eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -819,13 +840,13 @@
when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
// Expect that the domain selection is not executed and
// ImsSmsDispatcher handles this text directly.
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"),
- eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -835,7 +856,7 @@
setUpSmsDispatchers();
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -873,7 +894,7 @@
// Expect that new domain selection connection is created and domain selection is performed.
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
verify(mSmsDsc).finishSelection();
@@ -888,8 +909,8 @@
verify(newSmsDsc).finishSelection();
verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"), eq("text"),
- eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -904,7 +925,7 @@
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -944,7 +965,7 @@
// Expect that new domain selection connection is created and domain selection is performed.
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
verify(mEmergencySmsDsc).finishSelection();
@@ -959,8 +980,8 @@
verify(newEmergencySmsDsc).finishSelection();
verify(mImsSmsDispatcher, times(2)).sendText(eq("911"), eq("2222"), eq("text"),
- eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
- eq(false), eq(1L), eq(false));
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false),
+ eq(10), eq(false), eq(1L), eq(false), anyLong());
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -991,7 +1012,7 @@
// Expect that creating a domain selection connection is failed and
// fallback to the legacy implementation.
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -1002,8 +1023,8 @@
assertEquals(0, holder.getPendingRequests().size());
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0),
+ eq(false), eq(10), eq(false), eq(1L), eq(false), anyLong());
}
@Test
@@ -1033,7 +1054,7 @@
// Expect that creating a domain selection connection is failed and
// fallback to the legacy implementation.
mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -1045,8 +1066,8 @@
assertEquals(0, holder.getPendingRequests().size());
verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(mCallingUserId), eq(false), eq(0), eq(false),
+ eq(10), eq(false), eq(1L), eq(false), anyLong());
}
private void switchImsSmsFormat(int phoneType) {
@@ -1063,6 +1084,42 @@
assertTrue(mSmsDispatchersController.setImsManager(imsManager));
}
+ @Test
+ public void testSendSmsToDatagramDispatcher() {
+ when(mSatelliteController.isInCarrierRoamingNbIotNtn(any(Phone.class))).thenReturn(true);
+ mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+ verify(mMockDatagramDispatcher).sendSms(any());
+
+ clearInvocations(mMockDatagramDispatcher);
+ ArrayList<String> parts = new ArrayList<>();
+ ArrayList<PendingIntent> sentIntents = new ArrayList<>();
+ ArrayList<PendingIntent> deliveryIntents = new ArrayList<>();
+ mSmsDispatchersController.testSendMultipartText("1111", "2222", parts, sentIntents,
+ deliveryIntents, null, "test-app", mCallingUserId, false, 0, false, 10, 1L);
+ processAllMessages();
+ verify(mMockDatagramDispatcher).sendSms(any());
+ }
+
+ @Test
+ public void testSendCarrierRoamingNbIotNtnText() {
+ PendingRequest pendingRequest = createPendingRequest();
+ switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ mSmsDispatchersController.sendCarrierRoamingNbIotNtnText(pendingRequest);
+ processAllMessages();
+ verify(mSimulatedCommandsVerifier, times(0)).sendImsGsmSms(anyString(), anyString(),
+ anyInt(), anyInt(), any(Message.class));
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mSmsDispatchersController.sendCarrierRoamingNbIotNtnText(pendingRequest);
+ processAllMessages();
+ verify(mSimulatedCommandsVerifier, times(1)).sendImsGsmSms(anyString(), anyString(),
+ anyInt(), anyInt(), any(Message.class));
+ }
+
private void setUpDomainSelectionEnabled(boolean enabled) {
mSmsDispatchersController.setDomainSelectionResolverProxy(
new SmsDispatchersController.DomainSelectionResolverProxy() {
@@ -1152,7 +1209,7 @@
byte[] data = new byte[] { 0x01 };
mSmsDispatchersController.testSendData(
- "test-app", "1111", "2222", 8080, data, mSentIntent, null, false);
+ "test-app", mCallingUserId, "1111", "2222", 8080, data, mSentIntent, null, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -1168,14 +1225,14 @@
verify(mSmsDsc).finishSelection();
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
- verify(mImsSmsDispatcher).sendData(eq("test-app"), eq("1111"), eq("2222"), eq(8080),
- eq(data), eq(mSentIntent), any(), eq(false));
+ verify(mImsSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
} else if (isCdmaMo) {
- verify(mCdmaSmsDispatcher).sendData(eq("test-app"), eq("1111"), eq("2222"), eq(8080),
- eq(data), eq(mSentIntent), any(), eq(false));
+ verify(mCdmaSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
} else {
- verify(mGsmSmsDispatcher).sendData(eq("test-app"), eq("1111"), eq("2222"), eq(8080),
- eq(data), eq(mSentIntent), any(), eq(false));
+ verify(mGsmSmsDispatcher).sendData(eq("test-app"), eq(0), eq("1111"), eq("2222"),
+ eq(8080), eq(data), eq(mSentIntent), any(), eq(false), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1188,7 +1245,7 @@
setUpSmsDispatchers();
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
- "test-app", false, 0, false, 10, false, 1L, false);
+ "test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -1205,16 +1262,16 @@
verify(mSmsDsc).finishSelection();
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false), anyLong());
} else if (isCdmaMo) {
verify(mCdmaSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false), anyLong());
} else {
verify(mGsmSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
- any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
- eq(1L), eq(false));
+ any(), any(), eq("test-app"), eq(0), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1230,7 +1287,7 @@
ArrayList<PendingIntent> sentIntents = new ArrayList<>();
ArrayList<PendingIntent> deliveryIntents = new ArrayList<>();
mSmsDispatchersController.testSendMultipartText("1111", "2222", parts, sentIntents,
- deliveryIntents, null, "test-app", false, 0, false, 10, 1L);
+ deliveryIntents, null, "test-app", mCallingUserId, false, 0, false, 10, 1L);
processAllMessages();
SmsDispatchersController.DomainSelectionConnectionHolder holder =
@@ -1247,16 +1304,17 @@
verify(mSmsDsc).finishSelection();
if (domain == NetworkRegistrationInfo.DOMAIN_PS) {
verify(mImsSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
- eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(false), eq(0),
- eq(false), eq(10), eq(1L));
+ eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0), eq(false), eq(10), eq(1L), anyLong());
} else if (isCdmaMo) {
verify(mCdmaSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
- eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(false), eq(0),
- eq(false), eq(10), eq(1L));
+ eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0),
+ eq(false), eq(10), eq(1L), anyLong());
} else {
verify(mGsmSmsDispatcher).sendMultipartText(eq("1111"), eq("2222"), eq(parts),
- eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(false), eq(0),
- eq(false), eq(10), eq(1L));
+ eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0), eq(false), eq(10), eq(1L), anyLong());
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1321,4 +1379,18 @@
verify(mGsmSmsDispatcher).sendSms(eq(mTracker));
}
}
+
+ private static <T> ArrayList<T> asArrayList(T object) {
+ ArrayList<T> list = new ArrayList<>();
+ list.add(object);
+ return list;
+ }
+
+ private PendingRequest createPendingRequest() {
+ return new PendingRequest(
+ SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
+ mCallingUserId, "1111", "2222", asArrayList(mSentIntent), asArrayList(null),
+ false, null, 0, asArrayList("text"), null,
+ false, 0, false, 10, 100L, false);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
index 4483c61..bdf7e78 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsStorageMonitorTest.java
@@ -52,7 +52,7 @@
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
- mSmsStorageMonitor = new SmsStorageMonitor(mPhone);
+ mSmsStorageMonitor = new SmsStorageMonitor(mPhone, mFeatureFlags);
mSmsStorageMonitor.setMaxRetries(MAX_RETRIES);
mSmsStorageMonitor.setRetryDelayInMillis(RETRY_DELAY);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
index ac92b8f..99ece85 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
@@ -48,7 +48,6 @@
@Before
public void setUp() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
mSetFlagsRule.enableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG);
mSubscriptionInfoUT = new SubscriptionInfo.Builder()
.setId(1)
@@ -69,6 +68,7 @@
.setServiceCapabilities(SubscriptionManager.getServiceCapabilitiesSet(
SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK))
.setTransferStatus(1)
+ .setSatelliteESOSSupported(true)
.build();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
index a2763fe..5db1206 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
@@ -39,6 +39,8 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.os.AsyncResult;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
@@ -48,6 +50,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.telephony.flags.FeatureFlags;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -72,6 +77,8 @@
LocaleTracker mMockLocaleTracker2;
@Mock Location mMockLocation;
@Mock Network mMockNetwork;
+ @Mock
+ private FeatureFlags mMockFeatureFlags;
@Captor
private ArgumentCaptor<LocationListener> mLocationListenerCaptor;
@@ -105,25 +112,27 @@
when(mSST2.getLocaleTracker()).thenReturn(mMockLocaleTracker2);
when(mMockLocaleTracker2.getCurrentCountry()).thenReturn("");
- when(mConnectivityManager.getActiveNetwork()).thenReturn(mMockNetwork);
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
- when(mConnectivityManager.getNetworkCapabilities(any(Network.class)))
- .thenReturn(mNetworkCapabilities);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
when(mLocationManager.getProviders(true)).thenReturn(Arrays.asList("TEST_PROVIDER"));
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
mCountryDetectorUT = new TestTelephonyCountryDetector(
- mLooper, mContext, mLocationManager, mConnectivityManager);
+ mLooper, mContext, mLocationManager, mConnectivityManager, mMockFeatureFlags);
+ verify(mConnectivityManager).registerNetworkCallback(
+ any(NetworkRequest.class), mNetworkCallbackCaptor.capture());
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
if (isGeoCoderImplemented()) {
verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
mLocationListenerCaptor.capture());
verify(mLocationManager).getProviders(true);
verify(mLocationManager).getLastKnownLocation(anyString());
}
- verify(mConnectivityManager).registerNetworkCallback(
- any(NetworkRequest.class), mNetworkCallbackCaptor.capture());
}
@After
@@ -137,8 +146,10 @@
clearInvocations(mLocationManager);
clearInvocations(mConnectivityManager);
when(mMockLocaleTracker.getCurrentCountry()).thenReturn("US");
- TelephonyCountryDetector inst1 = TelephonyCountryDetector.getInstance(mContext);
- TelephonyCountryDetector inst2 = TelephonyCountryDetector.getInstance(mContext);
+ TelephonyCountryDetector inst1 = TelephonyCountryDetector
+ .getInstance(mContext, mMockFeatureFlags);
+ TelephonyCountryDetector inst2 = TelephonyCountryDetector
+ .getInstance(mContext, mMockFeatureFlags);
assertEquals(inst1, inst2);
if (isGeoCoderImplemented()) {
verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(),
@@ -275,7 +286,7 @@
// Wi-fi is not available
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
mTestableLooper.processAllMessages();
verify(mLocationManager, never()).removeUpdates(any(LocationListener.class));
@@ -284,6 +295,9 @@
clearInvocations(mLocationManager);
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.processAllMessages();
// Location updates were already requested
verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
@@ -291,7 +305,10 @@
// Make Wi-fi not available and reset the quota
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.moveTimeForward(
TestTelephonyCountryDetector.getLocationUpdateRequestQuotaResetTimeoutMillis());
mTestableLooper.processAllMessages();
@@ -301,6 +318,9 @@
clearInvocations(mLocationManager);
mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
mTestableLooper.processAllMessages();
verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
any(LocationListener.class));
@@ -314,14 +334,87 @@
verify(mLocationManager, never()).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
any(LocationListener.class));
- // Wi-fi becomes not available
+ // Wi-fi lost
clearInvocations(mLocationManager);
- mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
- mNetworkCallbackCaptor.getValue().onUnavailable();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
mTestableLooper.processAllMessages();
verify(mLocationManager).removeUpdates(any(LocationListener.class));
}
+ @Test
+ public void testRegisterUnregisterForWifiConnectivityStateChanged() {
+ // Set Wi-Fi unavailable.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+
+ WifiConnectivityStateChangedListener listener = new WifiConnectivityStateChangedListener(
+ mLooper);
+
+ mCountryDetectorUT.registerForWifiConnectivityStateChanged(listener,
+ 1 /* EVENT_WIFI_CONNECTIVITY_STATE_CHANGED*/, null);
+
+ // Wi-fi becomes available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertTrue(listener.getIsWifiConnected());
+
+ // Wi-fi lost
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ assertFalse(listener.getIsWifiConnected());
+
+ mCountryDetectorUT.unregisterForWifiConnectivityStateChanged(listener);
+ }
+
+ @Test
+ public void testReflectWifiConnectedStatusChanged() {
+ // 1. Wi-Fi is turned off, network capability is not available.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, false);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 2. Wi-Fi is turned on, but network capability has not been updated.
+ mNetworkCallbackCaptor.getValue().onAvailable(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 3. Network capability has been updated, not some of them still false.
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, false);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 4. Network capability has been updated to validated.
+ mNetworkCapabilities = new NetworkCapabilities();
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET, true);
+ mNetworkCapabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED, true);
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork, mNetworkCapabilities);
+ mTestableLooper.processAllMessages();
+ assertTrue(mCountryDetectorUT.isWifiNetworkConnected());
+
+ // 5. Wi-Fi is turned off.
+ mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
+ mTestableLooper.processAllMessages();
+ assertFalse(mCountryDetectorUT.isWifiNetworkConnected());
+ }
+
private static boolean isGeoCoderImplemented() {
return Geocoder.isPresent();
}
@@ -357,8 +450,9 @@
* @param locationManager The LocationManager instance.
*/
TestTelephonyCountryDetector(Looper looper, Context context,
- LocationManager locationManager, ConnectivityManager connectivityManager) {
- super(looper, context, locationManager, connectivityManager);
+ LocationManager locationManager, ConnectivityManager connectivityManager,
+ FeatureFlags featureFlags) {
+ super(looper, context, locationManager, connectivityManager, featureFlags);
}
@Override
@@ -375,4 +469,37 @@
return WAIT_FOR_LOCATION_UPDATE_REQUEST_QUOTA_RESET_TIMEOUT_MILLIS;
}
}
+
+ private static class WifiConnectivityStateChangedListener extends Handler {
+ private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 1;
+ private final Object mIsWifiConnectedLock = new Object();
+ @GuardedBy("mIsWifiConnectedLock")
+ private boolean mIsWifiConnected = false;
+
+ WifiConnectivityStateChangedListener(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ synchronized (mIsWifiConnectedLock) {
+ mIsWifiConnected = (boolean) ar.result;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ public boolean getIsWifiConnected() {
+ synchronized (mIsWifiConnectedLock) {
+ return mIsWifiConnected;
+ }
+ }
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index d4717dd..ac89501 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -37,6 +37,7 @@
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Process;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.permission.LegacyPermissionManager;
@@ -558,6 +559,38 @@
UserHandle.SYSTEM));
}
+ @Test
+ public void testIsSystemOrPhone_systemUser() {
+ assertTrue(TelephonyPermissions.isSystemOrPhone(Process.SYSTEM_UID));
+ assertTrue(TelephonyPermissions.isSystemOrPhone(Process.PHONE_UID));
+
+ assertFalse(TelephonyPermissions.isSystemOrPhone(1002));
+ }
+
+ @Test
+ public void testIsSystemOrPhone_nonSystemUser() {
+ assertTrue(TelephonyPermissions.isSystemOrPhone(1001000));
+ assertTrue(TelephonyPermissions.isSystemOrPhone(1001001));
+
+ assertFalse(TelephonyPermissions.isSystemOrPhone(1001002));
+ }
+
+ @Test
+ public void testIsRootOrShell_systemUser() {
+ assertTrue(TelephonyPermissions.isRootOrShell(Process.ROOT_UID));
+ assertTrue(TelephonyPermissions.isRootOrShell(Process.SHELL_UID));
+
+ assertFalse(TelephonyPermissions.isRootOrShell(1002));
+ }
+
+ @Test
+ public void testIsRootOrShell_nonSystemUser() {
+ assertTrue(TelephonyPermissions.isRootOrShell(1000000));
+ assertTrue(TelephonyPermissions.isRootOrShell(1002000));
+
+ assertFalse(TelephonyPermissions.isRootOrShell(1001002));
+ }
+
// Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
private void setTelephonyMockAsService() throws Exception {
when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 3e447a9..ed45fac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -45,6 +45,8 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.BarringInfo;
@@ -75,13 +77,16 @@
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import com.android.internal.telephony.flags.Flags;
import com.android.server.TelephonyRegistry;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -94,6 +99,8 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class TelephonyRegistryTest extends TelephonyTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
// Mocked classes
private SubscriptionInfo mMockSubInfo;
private TelephonyRegistry.ConfigurationProvider mMockConfigurationProvider;
@@ -117,7 +124,10 @@
private CellIdentity mCellIdentityForRegiFail;
private int mRegistrationFailReason;
private Set<Integer> mSimultaneousCallingSubscriptions;
+ private int mCallbackModeStopReason = TelephonyManager.STOP_REASON_UNKNOWN;
+ private long mCallbackModeDurationMillis;
private boolean mCarrierRoamingNtnMode;
+ private boolean mCarrierRoamingNtnEligible;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -194,6 +204,7 @@
TelephonyCallback.RegistrationFailedListener,
TelephonyCallback.DataActivityListener,
TelephonyCallback.SimultaneousCellularCallingSupportListener,
+ TelephonyCallback.EmergencyCallbackModeListener,
TelephonyCallback.CarrierRoamingNtnModeListener {
// This class isn't mockable to get invocation counts because the IBinder is null and
// crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
@@ -291,10 +302,37 @@
}
@Override
+ public void onCallbackModeStarted(@TelephonyManager.EmergencyCallbackModeType int type,
+ @NonNull Duration timerDuration, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeDurationMillis = timerDuration.toMillis();
+ }
+
+ @Override
+ public void onCallbackModeRestarted(@TelephonyManager.EmergencyCallbackModeType int type,
+ @NonNull Duration timerDuration, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeDurationMillis = timerDuration.toMillis();
+ }
+
+ @Override
+ public void onCallbackModeStopped(@TelephonyManager.EmergencyCallbackModeType int type,
+ @TelephonyManager.EmergencyCallbackModeStopReason int reason, int subId) {
+ invocationCount.incrementAndGet();
+ mCallbackModeStopReason = reason;
+ }
+
+ @Override
public void onCarrierRoamingNtnModeChanged(boolean active) {
invocationCount.incrementAndGet();
mCarrierRoamingNtnMode = active;
}
+
+ @Override
+ public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnEligible = eligible;
+ }
}
private void addTelephonyRegistryService() {
@@ -329,6 +367,10 @@
mContextFixture.putStringArrayResource(
com.android.internal.R.array.config_serviceStateLocationAllowedPackages,
new String[0]);
+
+ UserInfo userInfo = new UserInfo(UserHandle.myUserId(), "" /* name */, 0 /* flags */);
+ doReturn(userInfo.id).when(mIActivityManager).getCurrentUserId();
+
processAllMessages();
assertEquals(mTelephonyRegistry.asBinder(),
ServiceManager.getService("telephony.registry"));
@@ -964,6 +1006,8 @@
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.TIRAMISU;
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(anyString(), anyInt());
+ doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ anyString(), anyInt(), any(UserHandle.class));
mContextFixture.addCallingOrSelfPermission("");
mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(
@@ -1060,6 +1104,8 @@
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.TIRAMISU;
doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(anyString(), anyInt());
+ doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfoAsUser(
+ anyString(), anyInt(), any(UserHandle.class));
mContextFixture.addCallingOrSelfPermission("");
mContextFixture.addCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(
@@ -1572,6 +1618,57 @@
}
@Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeStarted() {
+ final long durationMillis = 1000;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeStarted(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, durationMillis);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(durationMillis, mCallbackModeDurationMillis);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeReStarted() {
+ final long durationMillis = 1000;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeRestarted(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, durationMillis);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(durationMillis, mCallbackModeDurationMillis);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EMERGENCY_CALLBACK_MODE_NOTIFICATION)
+ public void testNotifyCallbackModeStopped() {
+ final int reason = TelephonyManager.STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED;
+ int[] events = {TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, 1/*subId*/,
+ mContext.getOpPackageName(), mContext.getAttributionTag(),
+ mTelephonyCallback.callback, events, true);
+ mTelephonyRegistry.notifyCallbackModeStopped(0/*phoneId*/, 1/*subId*/,
+ TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL, reason);
+ processAllMessages();
+
+ assertEquals(1, mTelephonyCallback.invocationCount.get());
+ assertEquals(reason, mCallbackModeStopReason);
+ }
+
+ @Test
public void testNotifyCarrierRoamingNtnModeChanged() {
int subId = INVALID_SUBSCRIPTION_ID;
doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
@@ -1585,4 +1682,20 @@
processAllMessages();
assertTrue(mCarrierRoamingNtnMode);
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnEligibleStateChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ mTelephonyRegistry.notifyCarrierRoamingNtnEligibleStateChanged(subId, true);
+ processAllMessages();
+ assertTrue(mCarrierRoamingNtnEligible);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 38b4f77..d80c9a2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -580,6 +580,9 @@
mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
+ doReturn(true).when(mFeatureFlags).supportNetworkProvider();
+ doReturn(true).when(mFeatureFlags).hsumBroadcast();
+ doReturn(true).when(mFeatureFlags).hsumPackageManager();
TelephonyManager.disableServiceHandleCaching();
PropertyInvalidatedCache.disableForTestMode();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
index c3db35c..58e5617 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
@@ -30,17 +30,23 @@
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Telephony;
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.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
public class WapPushOverSmsTest extends TelephonyTest {
// Mocked classes
@@ -48,6 +54,9 @@
private WapPushOverSms mWapPushOverSmsUT;
+ @Mock private FeatureFlags mFeatureFlags;
+ private static final UserHandle MOCKED_MAIN_USER = UserHandle.of(10);
+
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
@@ -56,9 +65,14 @@
// Note that this replaces only cached services in ServiceManager. If a service is not found
// in the cache, a real instance is used.
mServiceManagerMockedServices.put("isms", mISmsStub);
+ mFeatureFlags = Mockito.mock(FeatureFlags.class);
+ doReturn(true).when(mFeatureFlags).smsMmsDeliverBroadcastsRedirectToMainUser();
doReturn(mISmsStub).when(mISmsStub).queryLocalInterface(anyString());
- mWapPushOverSmsUT = new WapPushOverSms(mContext);
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ doReturn(MOCKED_MAIN_USER).when(userManager).getMainUser();
+
+ mWapPushOverSmsUT = new WapPushOverSms(mContext, mFeatureFlags);
}
@After
@@ -94,7 +108,7 @@
eq(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH),
nullable(Bundle.class),
isNull(InboundSmsHandler.SmsBroadcastReceiver.class),
- eq(UserHandle.SYSTEM),
+ eq(MOCKED_MAIN_USER),
anyInt());
Intent intent = intentArgumentCaptor.getValue();
assertEquals(Telephony.Sms.Intents.WAP_PUSH_DELIVER_ACTION, intent.getAction());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
index 24f7d2c..cab76f7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
@@ -83,6 +83,7 @@
private InboundSmsTracker mInboundSmsTracker;
private final byte[] mSmsPdu = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
private final int mSubId0 = 0;
+ private static final UserHandle MOCKED_MAIN_USER = UserHandle.of(10);
private IState getCurrentState() {
try {
@@ -108,10 +109,13 @@
UserManager userManager = (UserManager) mContextFixture.getTestDouble().
getSystemService(Context.USER_SERVICE);
+ doReturn(MOCKED_MAIN_USER).when(userManager).getMainUser();
doReturn(true).when(userManager).isUserUnlocked();
+ doReturn(true).when(mFeatureFlags).smsMmsDeliverBroadcastsRedirectToMainUser();
try {
- doReturn(new int[]{UserHandle.USER_SYSTEM}).when(mIActivityManager).getRunningUserIds();
+ doReturn(new int[]{0, MOCKED_MAIN_USER.getIdentifier()})
+ .when(mIActivityManager).getRunningUserIds();
} catch (RemoteException re) {
StringWriter reString = new StringWriter();
re.printStackTrace(new PrintWriter(reString));
@@ -157,7 +161,8 @@
Telephony.Sms.CONTENT_URI.getAuthority(), mContentProvider);
mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(mContext,
- mSmsStorageMonitor, mPhone, null, mTestableLooper.getLooper());
+ mSmsStorageMonitor, mPhone, null, mTestableLooper.getLooper(),
+ mFeatureFlags);
monitorTestableLooper(new TestableLooper(mCdmaInboundSmsHandler.getHandler().getLooper()));
processAllMessages();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
index 1f52cea..118adbc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
@@ -18,6 +18,7 @@
import static org.mockito.Mockito.*;
+import android.os.Binder;
import android.os.HandlerThread;
import android.os.Message;
@@ -38,6 +39,7 @@
private CdmaSMSDispatcher mCdmaSmsDispatcher;
private CdmaSmsDispatcherTestHandler mCdmaSmsDispatcherTestHandler;
+ private int mCallingUserId;
private class CdmaSmsDispatcherTestHandler extends HandlerThread {
@@ -63,6 +65,7 @@
mCdmaSmsDispatcherTestHandler = new CdmaSmsDispatcherTestHandler(TAG);
mCdmaSmsDispatcherTestHandler.start();
waitUntilReady();
+ mCallingUserId = Binder.getCallingUserHandle().getIdentifier();
}
@After
@@ -84,14 +87,14 @@
@Test @SmallTest
public void testSendText() {
mCdmaSmsDispatcher.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier).sendCdmaSms(any(byte[].class), any(Message.class));
}
@Test @SmallTest
public void testSendTextWithOutDesAddr() {
mCdmaSmsDispatcher.sendText(null, "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier, times(0)).sendImsGsmSms(anyString(), anyString(),
anyInt(), anyInt(), any(Message.class));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
index 005b312..95cefd8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
@@ -146,7 +146,6 @@
@Test
public void testMeteredNetworkCapabilities() {
- doReturn(true).when(mFeatureFlags).meteredEmbbUrlcc();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[] {ApnSetting.TYPE_MMS_STRING, ApnSetting.TYPE_DEFAULT_STRING});
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
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 499c1f5..ee713c6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -159,7 +159,6 @@
private static final int EVENT_SUBSCRIPTION_OVERRIDE = 23;
// Mocked classes
- private PhoneSwitcher mMockedPhoneSwitcher;
protected ISub mMockedIsub;
private DataNetworkControllerCallback mMockedDataNetworkControllerCallback;
private DataRetryManagerCallback mMockedDataRetryManagerCallback;
@@ -855,7 +854,6 @@
public void setUp() throws Exception {
logd("DataNetworkControllerTest +Setup!");
super.setUp(getClass().getSimpleName());
- mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
mMockedIsub = Mockito.mock(ISub.class);
mMockedImsManager = mContext.getSystemService(ImsManager.class);
mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class);
@@ -878,7 +876,6 @@
mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
mMockedWlanDataServiceManager);
- replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doReturn(1).when(mMockedIsub).getDefaultDataSubId();
doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
doReturn(mPhone).when(mPhone).getImsPhone();
@@ -891,10 +888,11 @@
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn(new SubscriptionInfoInternal.Builder().setId(1).build())
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
doReturn(true).when(mFeatureFlags).satelliteInternet();
- doReturn(true).when(mFeatureFlags)
- .ignoreExistingNetworksForInternetAllowedChecking();
+ doReturn(true).when(mFeatureFlags).simDisabledGracefulTearDown();
+
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
@@ -2844,7 +2842,6 @@
@Test
public void testHandoverDataNetworkNotAllowedByPolicyDelayDueToVoiceCall() throws Exception {
- doReturn(true).when(mFeatureFlags).relaxHoTeardown();
// Config delay IMS tear down enabled
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
true);
@@ -3222,6 +3219,118 @@
}
@Test
+ public void testSetupDataNetworkWithCandidateProfileWithIncompatibleRetryDataProfile() throws Exception {
+ mDataNetworkControllerUT
+ .getDataRetryManager()
+ .registerCallback(mMockedDataRetryManagerCallback);
+ setFailedSetupDataResponse(mMockedWwanDataServiceManager,
+ DataFailCause.ONLY_IPV4_ALLOWED, 2500 /* mSec */, false);
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+ verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+
+ moveTimeForward(2500);
+ processAllMessages();
+ ArgumentCaptor<DataRetryManager.DataSetupRetryEntry> retryEntry =
+ ArgumentCaptor.forClass(DataRetryManager.DataSetupRetryEntry.class);
+ verify(mMockedDataRetryManagerCallback, times(1))
+ .onDataNetworkSetupRetry(retryEntry.capture());
+
+ ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor =
+ ArgumentCaptor.forClass(List.class);
+ verify(mMockedDataRetryManagerCallback)
+ .onThrottleStatusChanged(throttleStatusCaptor.capture());
+
+ assertThat(retryEntry.getValue().dataProfile).isNotNull();
+
+ assertThat(retryEntry.getValue().dataProfile).isEqualTo(mGeneralPurposeDataProfile);
+ doReturn(false)
+ .when(mDataProfileManager)
+ .isDataProfileCompatible(retryEntry.getValue().dataProfile);
+
+ doReturn(mDuplicatedGeneralPurposeDataProfile).when(mDataProfileManager)
+ .getDataProfileForNetworkRequest(any(TelephonyNetworkRequest.class),
+ anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+
+ setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 2);
+
+ mDataNetworkControllerUT
+ .getDataRetryManager()
+ .obtainMessage(
+ 6 /* EVENT_DATA_PROFILE_UNTHROTTLED*/,
+ new AsyncResult(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mGeneralPurposeDataProfile,
+ null))
+ .sendToTarget();
+ processAllFutureMessages();
+
+ verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ verifyConnectedNetworkHasDataProfile(mDuplicatedGeneralPurposeDataProfile);
+ }
+
+ @Test
+ public void testSetupDataNetworkRetryWithCompatibleRetryDataProfile() throws Exception {
+ mDataNetworkControllerUT
+ .getDataRetryManager()
+ .registerCallback(mMockedDataRetryManagerCallback);
+ setFailedSetupDataResponse(mMockedWwanDataServiceManager,
+ DataFailCause.ONLY_IPV4_ALLOWED, 2500 /* mSec */, false);
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+ verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+
+ moveTimeForward(2500);
+ processAllMessages();
+ ArgumentCaptor<DataRetryManager.DataSetupRetryEntry> retryEntry =
+ ArgumentCaptor.forClass(DataRetryManager.DataSetupRetryEntry.class);
+ verify(mMockedDataRetryManagerCallback, times(1))
+ .onDataNetworkSetupRetry(retryEntry.capture());
+
+ ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor =
+ ArgumentCaptor.forClass(List.class);
+ verify(mMockedDataRetryManagerCallback)
+ .onThrottleStatusChanged(throttleStatusCaptor.capture());
+
+ assertThat(retryEntry.getValue().dataProfile).isNotNull();
+
+ assertThat(retryEntry.getValue().dataProfile).isEqualTo(mGeneralPurposeDataProfile);
+
+ assertThat(mDataProfileManager.isDataProfileCompatible(retryEntry.getValue().dataProfile))
+ .isTrue();
+
+ setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 2);
+
+ mDataNetworkControllerUT
+ .getDataRetryManager()
+ .obtainMessage(
+ 6 /* EVENT_DATA_PROFILE_UNTHROTTLED*/,
+ new AsyncResult(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ mGeneralPurposeDataProfile,
+ null))
+ .sendToTarget();
+ processAllFutureMessages();
+
+ verify(mMockedWwanDataServiceManager, times(2)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
+ }
+
+ @Test
public void testSetupDataNetworkRetryFailed() {
mDataNetworkControllerUT.getDataRetryManager()
.registerCallback(mMockedDataRetryManagerCallback);
@@ -3901,7 +4010,6 @@
@Test
public void testNonVoPStoVoPSImsSetup() throws Exception {
- doReturn(true).when(mFeatureFlags).allowMmtelInNonVops();
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
// Config that allows non-vops bring up when Roaming
mCarrierConfig.putIntArray(CarrierConfigManager.Ims
@@ -4203,7 +4311,7 @@
}
@Test
- public void testImsGracefulTearDown() throws Exception {
+ public void testImsGracefulTearDownSimRemoval() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
@@ -4249,6 +4357,52 @@
}
@Test
+ public void testImsGracefulTearDownSimDisabled() throws Exception {
+ setImsRegistered(true);
+ setRcsRegistered(true);
+
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ netCaps.maybeMarkCapabilitiesRestricted();
+ netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
+
+ NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
+ TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
+ nativeNetworkRequest, mPhone, mFeatureFlags);
+
+ mDataNetworkControllerUT.addNetworkRequest(networkRequest);
+
+ processAllMessages();
+ Mockito.clearInvocations(mPhone);
+
+ // SIM disabled
+ mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+ TelephonyManager.SIM_STATE_NOT_READY, 0).sendToTarget();
+ processAllMessages();
+
+ // Make sure data network enters disconnecting state
+ ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
+ ArgumentCaptor.forClass(PreciseDataConnectionState.class);
+ verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
+ PreciseDataConnectionState pdcs = pdcsCaptor.getValue();
+ assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING);
+
+ // IMS de-registered. Now data network is safe to be torn down.
+ Mockito.clearInvocations(mPhone);
+ setImsRegistered(false);
+ setRcsRegistered(false);
+ processAllMessages();
+
+ // All data should be disconnected.
+ verifyAllDataDisconnected();
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
+ pdcs = pdcsCaptor.getValue();
+ assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
+ }
+
+ @Test
public void testNoGracefulTearDownForEmergencyDataNetwork() throws Exception {
setImsRegistered(true);
@@ -4908,14 +5062,10 @@
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, 0, NetworkRequest.Type.REQUEST);
-
- mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone, mFeatureFlags));
- processAllMessages();
-
- // Intentionally create a new telephony request with the original native network request.
TelephonyNetworkRequest request = new TelephonyNetworkRequest(
nativeNetworkRequest, mPhone, mFeatureFlags);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
mDataNetworkControllerUT.removeNetworkRequest(request);
processAllFutureMessages();
@@ -4936,7 +5086,7 @@
processAllMessages();
// this slot is 0, modem preferred on slot 1
- doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
+ doReturn(1).when(mPhoneSwitcher).getPreferredDataPhoneId();
// Simulate telephony network factory remove request due to switch.
mDataNetworkControllerUT.removeNetworkRequest(request);
@@ -4949,7 +5099,7 @@
@Test
public void testSetupDataOnNonDds() throws Exception {
// this slot is 0, modem preferred on slot 1
- doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
+ doReturn(1).when(mPhoneSwitcher).getPreferredDataPhoneId();
TelephonyNetworkRequest request = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_MMS);
@@ -5475,4 +5625,18 @@
assertThat(mDataNetworkControllerUT.getInternetEvaluation(true/*ignoreExistingNetworks*/)
.containsDisallowedReasons()).isTrue();
}
+
+ @Test
+ public void testRemoveNetworkRequestClearState() throws Exception {
+ TelephonyNetworkRequest request = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ assertThat(request.getState()).isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
+
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ processAllMessages();
+ assertThat(request.getState()).isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+ }
}
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 09cfa6f..f832a6b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -86,6 +87,7 @@
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
import com.android.internal.telephony.metrics.DataCallSessionStats;
import com.android.internal.telephony.test.SimulatedCommands;
@@ -238,14 +240,14 @@
// Mocked classes
private DataNetworkCallback mDataNetworkCallback;
private DataCallSessionStats mDataCallSessionStats;
- private PhoneSwitcher mMockedPhoneSwitcher;
-
private final NetworkRegistrationInfo mIwlanNetworkRegistrationInfo =
new NetworkRegistrationInfo.Builder()
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.build();
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid) {
setSuccessfulSetupDataResponse(dsm, cid, Collections.emptyList(), null);
}
@@ -379,14 +381,13 @@
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
+ doReturn(1).when(mPhone).getSubId();
doReturn(mImsPhone).when(mPhone).getImsPhone();
doReturn(mImsCT).when(mImsPhone).getCallTracker();
doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
mDataNetworkCallback = Mockito.mock(DataNetworkCallback.class);
mDataCallSessionStats = Mockito.mock(DataCallSessionStats.class);
- mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
- replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
return null;
@@ -2418,10 +2419,12 @@
@Test
public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
- doReturn(true).when(mFeatureFlags).forceIwlanMms();
- doReturn(true).when(mDataConfigManager).isForceIwlanMmsFeatureEnabled();
setupDataNetwork();
+ TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+ replaceInstance(DataNetwork.class, "mNetworkAgent",
+ mDataNetworkUT, mockNetworkAgent);
+
assertThat(mDataNetworkUT.getNetworkCapabilities()
.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
@@ -2466,11 +2469,13 @@
.onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS, false);
processAllMessages();
- // Check if MMS capability is removed.
+ // Check if MMS capability is removed, and we don't recreat network agent which triggers
+ // powering comsuming internet validation.
assertThat(mDataNetworkUT.getNetworkCapabilities()
.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isFalse();
+ verify(mockNetworkAgent, never()).abandon();
- // Now QNS prefers MMS on IWLAN
+ // Now QNS prefers MMS on WWAN
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
accessNetworksManagerCallbackArgumentCaptor.getValue()
@@ -2657,4 +2662,35 @@
assertThat(mDataNetworkUT.getNetworkCapabilities()
.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
}
+
+ @Test
+ public void testPrimaryTransport() throws Exception {
+ doReturn(0).when(mPhoneSwitcher).getPreferredDataPhoneId();
+ setupDataNetwork();
+ TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+ replaceInstance(DataNetwork.class, "mNetworkAgent",
+ mDataNetworkUT, mockNetworkAgent);
+
+ ArgumentCaptor<PhoneSwitcherCallback> callbackCaptor =
+ ArgumentCaptor.forClass(PhoneSwitcherCallback.class);
+ verify(mPhoneSwitcher).registerCallback(callbackCaptor.capture());
+ mPhoneSwitcherCallback = callbackCaptor.getValue();
+
+ // Switch the preferred data subscription to another.
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(1);
+ processAllMessages();
+
+ ArgumentCaptor<NetworkScore> networkScoreCaptor =
+ ArgumentCaptor.forClass(NetworkScore.class);
+ verify(mockNetworkAgent).sendNetworkScore(networkScoreCaptor.capture());
+ assertThat(networkScoreCaptor.getValue().isTransportPrimary()).isFalse();
+ clearInvocations(mockNetworkAgent);
+
+ // Switch back
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(0);
+ processAllMessages();
+
+ verify(mockNetworkAgent).sendNetworkScore(networkScoreCaptor.capture());
+ assertThat(networkScoreCaptor.getValue().isTransportPrimary()).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 30ce46f..96d0c8c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -1046,7 +1046,6 @@
@Test
public void testSetPreferredDataProfile() {
- doReturn(true).when(mFeatureFlags).refinePreferredDataProfileSelection();
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
index acfa16d..78bb553 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
@@ -341,7 +341,6 @@
@Test
public void testDataSetupUnthrottling() throws Exception {
- doReturn(true).when(mFeatureFlags).unthrottleCheckTransport();
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
@@ -807,7 +806,6 @@
@Test
public void testDataRetryLongTimer() {
- doReturn(true).when(mFeatureFlags).useAlarmCallback();
// Rule requires a long timer
DataSetupRetryRule retryRule = new DataSetupRetryRule(
"capabilities=internet, retry_interval=120000, maximum_retries=2");
@@ -882,6 +880,40 @@
}
@Test
+ public void testTrafficDescriptorRequestRetry() {
+ DataSetupRetryRule retryRule = new DataSetupRetryRule(
+ "capabilities=PRIORITIZE_BANDWIDTH, retry_interval=200, maximum_retries=2");
+ doReturn(Collections.singletonList(retryRule)).when(mDataConfigManager)
+ .getDataSetupRetryRules();
+ mDataConfigManagerCallback.onCarrierConfigChanged();
+ processAllMessages();
+
+ NetworkRequest request = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
+ DataNetworkController.NetworkRequestList
+ networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
+
+ // failed and retry.
+ mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile1,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN, networkRequestList, 123,
+ DataCallResponse.RETRY_DURATION_UNDEFINED);
+ processAllFutureMessages();
+
+ tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .build(), mPhone, mFeatureFlags);
+ assertThat(mDataRetryManagerUT.isSimilarNetworkRequestRetryScheduled(tnr,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN)).isTrue();
+ assertThat(mDataRetryManagerUT.isSimilarNetworkRequestRetryScheduled(tnr,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).isFalse();
+ }
+
+
+ @Test
public void testRilCrashedReset() {
testDataSetupRetryNetworkSuggestedNeverRetry();
Mockito.clearInvocations(mDataRetryManagerCallbackMock, mDataProfileManager);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
index 3f18a3a..620cf39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
@@ -42,6 +42,7 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.After;
import org.junit.Before;
@@ -184,6 +185,49 @@
}
@Test
+ public void testUpdateDataEnabledAndNotifyOverrideDdsChange() throws Exception {
+ // Mock 2nd phone the DDS phone.
+ int phone2Id = 1;
+ int phone2SubId = 2;
+ doReturn(phone2SubId).when(mSubscriptionManagerService).getDefaultDataSubId();
+ Phone phone2 = Mockito.mock(Phone.class);
+ doReturn(phone2Id).when(phone2).getPhoneId();
+ doReturn(phone2SubId).when(phone2).getSubId();
+ doReturn(phone2Id).when(mSubscriptionManagerService).getPhoneId(phone2SubId);
+ DataSettingsManager dataSettingsManager2 = Mockito.mock(DataSettingsManager.class);
+ doReturn(dataSettingsManager2).when(phone2).getDataSettingsManager();
+ doReturn(true).when(phone2).isUserDataEnabled();
+
+ mPhones = new Phone[] {mPhone, phone2};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ ArgumentCaptor<SubscriptionManagerService.SubscriptionManagerServiceCallback>
+ callbackArgumentCaptor = ArgumentCaptor
+ .forClass(SubscriptionManagerService.SubscriptionManagerServiceCallback.class);
+
+ mDataSettingsManagerUT.sendEmptyMessage(11 /* EVENT_INITIALIZE */);
+ mDataSettingsManagerUT.setDataEnabled(TelephonyManager.DATA_ENABLED_REASON_USER, false, "");
+ processAllMessages();
+
+ // Verify listening to DDS change callback
+ verify(mSubscriptionManagerService, times(2))
+ .registerCallback(callbackArgumentCaptor.capture());
+ SubscriptionManagerService.SubscriptionManagerServiceCallback callback =
+ callbackArgumentCaptor.getValue();
+
+ // Mock the phone as nonDDS auto switch override enabled.
+ clearInvocations(mPhones);
+ mDataSettingsManagerUT.setMobileDataPolicy(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, true);
+ processAllMessages();
+ verify(mPhone).notifyDataEnabled(true, TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+
+ // The phone became DDS, data should be disabled
+ doReturn(mPhone.getSubId()).when(mSubscriptionManagerService).getDefaultDataSubId();
+ callback.onDefaultDataSubscriptionChanged(mPhone.getSubId());
+ verify(mPhone).notifyDataEnabled(false, TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+ }
+
+ @Test
public void testNotifyDataEnabledFromNewValidSubId() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mDataSettingsManagerUT.registerCallback(
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 2a1fedb..f7990b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -52,18 +52,15 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
-import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.Messenger;
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
@@ -75,8 +72,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import androidx.test.filters.SmallTest;
-
import com.android.ims.ImsException;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CommandException;
@@ -87,11 +82,11 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
import org.junit.After;
import org.junit.Before;
@@ -140,9 +135,6 @@
private PhoneSwitcher mPhoneSwitcherUT;
private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
- private ConnectivityManager mConnectivityManager;
- // The messenger of PhoneSwitcher used to receive network requests.
- private Messenger mNetworkProviderMessenger = null;
private Map<Integer, DataSettingsManager.DataSettingsManagerCallback>
mDataSettingsManagerCallbacks;
private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -155,6 +147,7 @@
private TelephonyDisplayInfo mTelephonyDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_NR,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
+ private SubscriptionManagerServiceCallback mSubscriptionManagerServiceCallback;
@Before
public void setUp() throws Exception {
@@ -203,14 +196,13 @@
mServiceManagerMockedServices.put("isub", mIBinder);
doReturn(mTelephonyDisplayInfo).when(mDisplayInfoController).getTelephonyDisplayInfo();
+ doReturn(true).when(mFeatureFlags).ddsCallback();
}
@After
public void tearDown() throws Exception {
mPhoneSwitcherUT = null;
mSubChangedListener = null;
- mConnectivityManager = null;
- mNetworkProviderMessenger = null;
mTelephonyDisplayInfo = null;
super.tearDown();
}
@@ -219,7 +211,6 @@
* Test that a single phone case results in our phone being active and the RIL called
*/
@Test
- @SmallTest
public void testRegister() throws Exception {
initialize();
@@ -466,7 +457,6 @@
}
@Test
- @SmallTest
public void testAutoDataSwitch_exemptPingTest() throws Exception {
initialize();
@@ -504,7 +494,6 @@
* - don't switch phones when in emergency mode
*/
@Test
- @SmallTest
public void testPrioritization() throws Exception {
initialize();
@@ -539,7 +528,6 @@
* wins (ie, switch to wifi).
*/
@Test
- @SmallTest
public void testHigherPriorityDefault() throws Exception {
initialize();
@@ -572,7 +560,6 @@
* active one.
*/
@Test
- @SmallTest
public void testSetPreferredData() throws Exception {
initialize();
@@ -618,7 +605,6 @@
* 3. CBRS requests OR Auto switch requests - only one case applies at a time
*/
@Test
- @SmallTest
public void testSetPreferredDataCasePriority_CbrsWaitsForVoiceCall() throws Exception {
initialize();
setAllPhonesInactive();
@@ -672,7 +658,6 @@
}
@Test
- @SmallTest
public void testSetPreferredData_NoAutoSwitchWhenCbrs() throws Exception {
initialize();
setAllPhonesInactive();
@@ -726,7 +711,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataModemCommand() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -825,7 +809,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataWithValidation() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -886,7 +869,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds() throws Exception {
initialize();
setAllPhonesInactive();
@@ -914,7 +896,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallDialingOnLte_shouldSwitchDds()
throws Exception {
initialize();
@@ -948,7 +929,6 @@
assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallIncomingOnLte_shouldSwitchDds()
throws Exception {
initialize();
@@ -977,7 +957,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1004,7 +983,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1167,7 +1145,6 @@
}
@Test
- @SmallTest
public void testNetworkRequestOnNonDefaultData() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1192,7 +1169,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1213,7 +1189,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideNoDdsChange() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1233,7 +1208,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideEndSuccess() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1271,7 +1245,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideEcbmStartEnd() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1321,7 +1294,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideNoCallStart() throws Exception {
PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1353,7 +1325,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1404,7 +1375,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataCallback() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1579,7 +1549,6 @@
}
@Test
- @SmallTest
public void testMultiSimConfigChange() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
mActiveModemCount = 1;
@@ -1607,7 +1576,6 @@
}
@Test
- @SmallTest
public void testValidationOffSwitch_shouldSwitchOnNetworkAvailable() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1648,7 +1616,6 @@
}
@Test
- @SmallTest
public void testValidationOffSwitch_shouldSwitchOnTimeOut() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1771,7 +1738,6 @@
}
@Test
- @SmallTest
public void testRegisterForImsRegistrationCallback() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1799,7 +1765,6 @@
}
@Test
- @SmallTest
public void testReceivingImsRegistrationTech() throws Exception {
doReturn(true).when(mFeatureFlags).changeMethodOfObtainingImsRegistrationRadioTech();
@@ -1880,9 +1845,6 @@
doReturn(true).when(mPhone2).isDataAllowed();
doReturn(true).when(mDataSettingsManager2).isDataEnabled();
- // 3.1 No default network
- doReturn(null).when(mConnectivityManager).getNetworkCapabilities(any());
-
mPhoneSwitcherUT.sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH);
}
@@ -2032,19 +1994,12 @@
}
}
- private void sendDefaultDataSubChanged() {
- final Intent intent = new Intent(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
- mContext.sendBroadcast(intent);
- processAllMessages();
- }
-
private void initialize() throws Exception {
setNumPhones(mActiveModemCount, mSupportedModemCount);
initializeSubControllerMock();
initializeCommandInterfacesMock();
initializeTelRegistryMock();
- initializeConnManagerMock();
initializeConfigMock();
mPhoneSwitcherUT = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper(),
@@ -2066,6 +2021,11 @@
processAllMessages();
verify(mTelephonyRegistryManager).addOnSubscriptionsChangedListener(any(), any());
+
+ ArgumentCaptor<SubscriptionManagerServiceCallback> callbackCaptor =
+ ArgumentCaptor.forClass(SubscriptionManagerServiceCallback.class);
+ verify(mSubscriptionManagerService).registerCallback(callbackCaptor.capture());
+ mSubscriptionManagerServiceCallback = callbackCaptor.getValue();
}
/**
@@ -2153,21 +2113,6 @@
* Capture mNetworkProviderMessenger so that testing can request or release
* network requests on PhoneSwitcher.
*/
- private void initializeConnManagerMock() {
- mConnectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- doAnswer(invocation -> {
- mNetworkProviderMessenger =
- ((NetworkProvider) invocation.getArgument(0)).getMessenger();
- return null;
- }).when(mConnectivityManager).registerNetworkProvider(any());
- }
-
- /**
- * Capture mNetworkProviderMessenger so that testing can request or release
- * network requests on PhoneSwitcher.
- */
private void initializeSubControllerMock() throws Exception {
doReturn(mDefaultDataSub).when(mSubscriptionManagerService).getDefaultDataSubId();
doReturn(mDefaultDataSub).when(mMockedIsub).getDefaultDataSubId();
@@ -2231,7 +2176,8 @@
doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
.when(phone).isUserDataEnabled();
}
- sendDefaultDataSubChanged();
+ mSubscriptionManagerServiceCallback.onDefaultDataSubscriptionChanged(defaultDataSub);
+ processAllMessages();
}
private void setSlotIndexToSubId(int slotId, int subId) {
@@ -2263,13 +2209,7 @@
NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
0, NetworkRequest.Type.REQUEST);
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
- message.arg1 = score;
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
-
+ mPhoneSwitcherUT.onRequestNetwork(networkRequest);
return networkRequest;
}
@@ -2287,14 +2227,7 @@
}
NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
1, NetworkRequest.Type.REQUEST);
-
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
- message.arg1 = 50; // Score
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
-
+ mPhoneSwitcherUT.onRequestNetwork(networkRequest);
return networkRequest;
}
@@ -2302,10 +2235,6 @@
* Tell PhoneSwitcher to release a network request.
*/
private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_CANCEL_REQUEST;
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
+ mPhoneSwitcherUT.onReleaseNetwork(networkRequest);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
new file mode 100644
index 0000000..d62ee2f
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
@@ -0,0 +1,394 @@
+/*
+ * 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.data;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.NonNull;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
+import android.net.NetworkRequest;
+import android.net.NetworkScore;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.connectivity.android.net.INetworkOfferCallback;
+import android.os.Looper;
+import android.telephony.Annotation.NetCapability;
+import android.telephony.SubscriptionManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Arrays;
+import java.util.Set;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class TelephonyNetworkProviderTest extends TelephonyTest {
+
+ private TelephonyNetworkProvider mTelephonyNetworkProvider;
+
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
+ // Mocked classes
+ private DataNetworkController mDataNetworkController2;
+
+
+ /**
+ * Set the preferred data phone, which is supposed to take the network request.
+ *
+ * @param phoneId The phone id
+ */
+ private void setPreferredDataPhone(int phoneId) {
+ doAnswer(invocation -> {
+ TelephonyNetworkRequest request = (TelephonyNetworkRequest)
+ invocation.getArguments()[0];
+ int id = (int) invocation.getArguments()[1];
+
+ logd("shouldApplyNetworkRequest: request phone id=" + id
+ + ", preferred data phone id=" + phoneId);
+
+ TelephonyNetworkSpecifier specifier = (TelephonyNetworkSpecifier)
+ request.getNetworkSpecifier();
+ if (specifier != null) {
+ int subId = specifier.getSubscriptionId();
+ logd("shouldApplyNetworkRequest: requested on sub " + subId);
+ if (subId == 1 && mPhone.getPhoneId() == id) {
+ logd("shouldApplyNetworkRequest: matched phone 0");
+ return true;
+ }
+ if (subId == 2 && mPhone2.getPhoneId() == id) {
+ logd("shouldApplyNetworkRequest: matched phone 1");
+ return true;
+ }
+ return false;
+ }
+
+ if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) return true;
+ return id == phoneId;
+ }).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(TelephonyNetworkRequest.class),
+ anyInt());
+ }
+
+ /**
+ * Create a simple network request with internet capability.
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequest() {
+ return createNetworkRequestForSub(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ /**
+ * Create a network request with specified network capabilities.
+ *
+ * @param caps Network capabilities
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequest(@NetCapability int... caps) {
+ return createNetworkRequestForSub(SubscriptionManager.INVALID_SUBSCRIPTION_ID, caps);
+ }
+
+ /**
+ * Create a network request with subscription id specified.
+ *
+ * @param subId The subscription in for the network request
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequestForSub(int subId) {
+ return createNetworkRequestForSub(subId, NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ /**
+ * Create the network request.
+ *
+ * @param subId The subscription id. {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if no
+ * @param caps Network capabilities in the network request need to specify.
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequestForSub(int subId, @NetCapability int... caps) {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ Arrays.stream(caps).boxed().toList().forEach(builder::addCapability);
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ builder.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+ builder.setSubscriptionIds(Set.of(subId));
+ }
+
+ return builder.build();
+ }
+
+ /** Clear all invocations from all DataNetworkControllers. */
+ private void resetInvocations() {
+ clearInvocations(mDataNetworkController);
+ clearInvocations(mDataNetworkController2);
+ }
+
+ /**
+ * Verify the request was sent to the correct phone's DataNetworkController.
+ *
+ * @param phoneId The id of the phone that the request is supposed to send
+ * @param request The network request
+ */
+ private void verifyRequestSentOnPhone(int phoneId, @NonNull NetworkRequest request) {
+ ArgumentCaptor<TelephonyNetworkRequest> requestCaptor =
+ ArgumentCaptor.forClass(TelephonyNetworkRequest.class);
+
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.getPhoneId() == phoneId) {
+ verify(phone.getDataNetworkController(), times(1)
+ .description("Did not request on phone " + phoneId))
+ .addNetworkRequest(requestCaptor.capture());
+ assertThat(requestCaptor.getValue().getNativeNetworkRequest()).isEqualTo(request);
+ } else {
+ verifyNoRequestSentOnPhone(phone.getPhoneId());
+ }
+ }
+ }
+
+ /**
+ * Verify the request was released on the specified phone's DataNetworkController.
+ *
+ * @param phoneId The id of the phone that the request is supposed to send
+ * @param request The network request
+ */
+ private void verifyRequestReleasedOnPhone(int phoneId, @NonNull NetworkRequest request) {
+ ArgumentCaptor<TelephonyNetworkRequest> requestCaptor =
+ ArgumentCaptor.forClass(TelephonyNetworkRequest.class);
+
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.getPhoneId() == phoneId) {
+ verify(phone.getDataNetworkController(), times(1)
+ .description("Did not remove on phone " + phoneId))
+ .removeNetworkRequest(requestCaptor.capture());
+ assertThat(requestCaptor.getValue().getNativeNetworkRequest()).isEqualTo(request);
+ } else {
+ verifyNoRequestReleasedOnPhone(phone.getPhoneId());
+ }
+ }
+ }
+
+ /**
+ * Verify there is no request sent on specified phone.
+ *
+ * @param phoneId The phone id
+ */
+ private void verifyNoRequestSentOnPhone(int phoneId) {
+ verify(PhoneFactory.getPhone(phoneId).getDataNetworkController(), never()
+ .description("Should not request on phone " + phoneId))
+ .addNetworkRequest(any(TelephonyNetworkRequest.class));
+ }
+
+ /**
+ * Verify there is no request released on specified phone.
+ *
+ * @param phoneId The phone id
+ */
+ private void verifyNoRequestReleasedOnPhone(int phoneId) {
+ verify(PhoneFactory.getPhone(phoneId).getDataNetworkController(), never()
+ .description("Should not release on phone " + phoneId))
+ .removeNetworkRequest(any(TelephonyNetworkRequest.class));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ logd("TelephonyNetworkProviderTest +Setup!");
+ super.setUp(getClass().getSimpleName());
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mPhone2});
+
+ mDataNetworkController2 = mock(DataNetworkController.class);
+
+ doReturn(0).when(mPhone).getPhoneId();
+ doReturn(1).when(mPhone).getSubId();
+ doReturn(1).when(mPhone2).getPhoneId();
+ doReturn(2).when(mPhone2).getSubId();
+
+ doReturn(mDataNetworkController2).when(mPhone2).getDataNetworkController();
+
+ setPreferredDataPhone(0);
+
+ doAnswer(invocation -> {
+ NetworkProvider provider = (NetworkProvider) invocation.getArguments()[0];
+ provider.setProviderId(1);
+ return 1;
+ }).when(mConnectivityManager).registerNetworkProvider(any(NetworkProvider.class));
+
+ mTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
+ mContext, mFeatureFlags);
+
+ ArgumentCaptor<PhoneSwitcherCallback> callbackCaptor =
+ ArgumentCaptor.forClass(PhoneSwitcherCallback.class);
+ verify(mPhoneSwitcher).registerCallback(callbackCaptor.capture());
+ mPhoneSwitcherCallback = callbackCaptor.getValue();
+
+ logd("TelephonyNetworkProviderTest -Setup!");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logd("tearDown");
+ super.tearDown();
+ }
+
+ @Test
+ public void testRegisterProvider() {
+ verify(mConnectivityManager).registerNetworkProvider(any(TelephonyNetworkProvider.class));
+
+ ArgumentCaptor<NetworkCapabilities> capsCaptor =
+ ArgumentCaptor.forClass(NetworkCapabilities.class);
+ verify(mConnectivityManager).offerNetwork(anyInt(), any(NetworkScore.class),
+ capsCaptor.capture(), any(INetworkOfferCallback.class));
+
+ NetworkCapabilities caps = capsCaptor.getValue();
+
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities().forEach(
+ (cap) -> assertThat(caps.hasCapability(cap)).isTrue());
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)).isTrue();
+ assertThat(caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+ assertThat(caps.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+
+ assertThat(caps.getNetworkSpecifier()).isInstanceOf(MatchAllNetworkSpecifier.class);
+ }
+
+ @Test
+ public void testRequestNetwork() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ }
+
+ @Test
+ public void testReleaseNetwork() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ resetInvocations();
+
+ // Now release the network request.
+ mTelephonyNetworkProvider.onNetworkUnneeded(request);
+ // Should release on phone 0
+ verifyRequestReleasedOnPhone(0, request);
+ resetInvocations();
+
+ // Release the same request again should not result in another remove
+ mTelephonyNetworkProvider.onNetworkUnneeded(request);
+ verifyNoRequestReleasedOnPhone(0);
+ verifyNoRequestReleasedOnPhone(1);
+ }
+
+ @Test
+ public void testRequestNetworkDuplicate() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+
+ resetInvocations();
+ // send the same request again should be blocked.
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ verifyNoRequestSentOnPhone(0);
+ verifyNoRequestSentOnPhone(1);
+ }
+
+ @Test
+ public void testRequestNetworkPreferredPhone1() {
+ setPreferredDataPhone(1);
+
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 1
+ verifyRequestSentOnPhone(1, request);
+ }
+
+ @Test
+ public void testRequestEmergencyNetwork() {
+ setPreferredDataPhone(1);
+
+ NetworkRequest request = createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_EIMS);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ }
+
+ @Test
+ public void testRequestNetworkOnSpecifiedSub() {
+ NetworkRequest request = createNetworkRequestForSub(1);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ verifyRequestSentOnPhone(0, request);
+
+ resetInvocations();
+ request = createNetworkRequestForSub(2);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 1
+ verifyRequestSentOnPhone(1, request);
+ }
+
+ @Test
+ public void testPreferredDataSwitch() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ resetInvocations();
+
+ // Now switch from phone 0 to phone 1
+ setPreferredDataPhone(1);
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(1);
+ verifyRequestReleasedOnPhone(0, request);
+ verifyRequestSentOnPhone(1, request);
+ resetInvocations();
+
+ // Now switch back to phone 0
+ setPreferredDataPhone(0);
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(0);
+ verifyRequestReleasedOnPhone(1, request);
+ verifyRequestSentOnPhone(0, request);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
index 9f11a3a..27c87e2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
@@ -189,7 +189,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
.build(), mPhone, mFeatureFlags);
- assertThat(request.getApnTypeNetworkCapability())
+ assertThat(request.getHighestPriorityApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_SUPL);
request = new TelephonyNetworkRequest(
@@ -198,7 +198,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build(), mPhone, mFeatureFlags);
- assertThat(request.getApnTypeNetworkCapability())
+ assertThat(request.getHighestPriorityApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_FOTA);
request = new TelephonyNetworkRequest(
@@ -207,7 +207,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build(), mPhone, mFeatureFlags);
- assertThat(request.getApnTypeNetworkCapability())
+ assertThat(request.getHighestPriorityApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_EIMS);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
index 5fd7a77..ec7ad3c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
@@ -16,9 +16,12 @@
package com.android.internal.telephony.domainselection;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UNKNOWN;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN;
+import static android.telephony.DomainSelectionService.SCAN_TYPE_FULL_SERVICE;
import static android.telephony.DomainSelectionService.SCAN_TYPE_NO_PREFERENCE;
import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_SMS;
import static com.google.common.truth.Truth.assertThat;
@@ -46,6 +49,7 @@
import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.EmergencyRegistrationResult;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PreciseDisconnectCause;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
@@ -55,6 +59,8 @@
import androidx.test.filters.SmallTest;
import com.android.internal.telephony.CallFailCause;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IDomainSelector;
import com.android.internal.telephony.ITransportSelectorCallback;
import com.android.internal.telephony.ITransportSelectorResultCallback;
@@ -83,6 +89,7 @@
private static final String TELECOM_CALL_ID1 = "TC1";
+ private CommandsInterface mCi;
private DomainSelectionController mDomainSelectionController;
private DomainSelectionConnection.DomainSelectionConnectionCallback mConnectionCallback;
private DomainSelectionConnection mDsc;
@@ -91,6 +98,9 @@
public void setUp() throws Exception {
super.setUp(this.getClass().getSimpleName());
+ mCi = Mockito.mock(CommandsInterface.class);
+ mPhone.mCi = mCi;
+
mDomainSelectionController = Mockito.mock(DomainSelectionController.class);
doReturn(true).when(mDomainSelectionController).selectDomain(any(), any());
mConnectionCallback =
@@ -187,6 +197,7 @@
verify(mPhone).registerForEmergencyNetworkScan(
handlerCaptor.capture(), eventCaptor.capture(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
@@ -235,6 +246,7 @@
processAllMessages();
verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
verify(mPhone).triggerEmergencyNetworkScan(any(), anyInt(), any());
wwanCallback.onCancel();
@@ -280,6 +292,7 @@
verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());
verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi, times(0)).registerForModemReset(any(), anyInt(), any());
verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());
Message msg = msgCaptor.getValue();
@@ -295,6 +308,7 @@
verify(mPhone).registerForEmergencyNetworkScan(
handlerCaptor.capture(), eventCaptor.capture(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
@@ -350,6 +364,7 @@
verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());
verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi, times(0)).registerForModemReset(any(), anyInt(), any());
verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());
Message msg = msgCaptor.getValue();
@@ -363,6 +378,7 @@
// Verify that scan is requested.
verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
verify(mPhone).triggerEmergencyNetworkScan(any(), anyInt(), any());
// Cancele scan after reset completes.
@@ -410,6 +426,7 @@
verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());
verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi, times(0)).registerForModemReset(any(), anyInt(), any());
verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());
Message msg = msgCaptor.getValue();
@@ -430,11 +447,395 @@
// Verify there is no scan request after reset completes.
verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi, times(0)).registerForModemReset(any(), anyInt(), any());
verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());
}
@Test
@SmallTest
+ public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndRadioNotAvailableError()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
+ false, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(handlerCaptor.capture(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), msgCaptor.capture());
+
+ Handler handler = handlerCaptor.getValue();
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(msg);
+
+ CommandException commandException =
+ new CommandException(CommandException.Error.RADIO_NOT_AVAILABLE);
+ handler.sendMessage(handler.obtainMessage(msg.what,
+ new AsyncResult((Integer) scanType, null, commandException)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(mPhone).unregisterForEmergencyNetworkScan(any());
+ verify(mCi).unregisterForModemReset(any());
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ verify(mDomainSelectionController).removeConnection(eq(mDsc));
+ }
+
+ @Test
+ @SmallTest
+ public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndErrorForScanTypeFull()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_FULL_SERVICE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
+ false, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(handlerCaptor.capture(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), msgCaptor.capture());
+
+ Handler handler = handlerCaptor.getValue();
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(msg);
+
+ CommandException commandException =
+ new CommandException(CommandException.Error.INTERNAL_ERR);
+ handler.sendMessage(handler.obtainMessage(msg.what,
+ new AsyncResult((Integer) scanType, null, commandException)));
+ processAllMessages();
+
+ EmergencyRegistrationResult regResult = new EmergencyRegistrationResult(UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+ verify(resultCallback).onComplete(eq(regResult));
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanAndErrorForScanTypeNoPref()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
+ false, resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(handlerCaptor.capture(), anyInt(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), msgCaptor.capture());
+
+ Handler handler = handlerCaptor.getValue();
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(msg);
+
+ CommandException commandException =
+ new CommandException(CommandException.Error.INTERNAL_ERR);
+ handler.sendMessage(handler.obtainMessage(msg.what,
+ new AsyncResult((Integer) scanType, null, commandException)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testModemResetOnRequestEmergencyNetworkDuringNetworkScan()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_FULL_SERVICE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, false,
+ resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> eventCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi).registerForModemReset(handlerCaptor.capture(), eventCaptor.capture(),
+ any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), any());
+
+ Handler handler = handlerCaptor.getValue();
+ Integer event = eventCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(event);
+
+ handler.sendMessage(handler.obtainMessage(event.intValue(),
+ new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(resultCallback, times(0)).onComplete(any());
+ verify(mPhone).unregisterForEmergencyNetworkScan(any());
+ verify(mCi).unregisterForModemReset(any());
+ verify(mPhone).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testModemResetOnRequestEmergencyNetworkDuringNetworkScanForSms()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_SMS, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_SMS, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_FULL_SERVICE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, false,
+ resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> eventCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
+ verify(mCi).registerForModemReset(handlerCaptor.capture(), eventCaptor.capture(),
+ any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), any());
+
+ Handler handler = handlerCaptor.getValue();
+ Integer event = eventCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(event);
+
+ handler.sendMessage(handler.obtainMessage(event.intValue(),
+ new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(mPhone, times(0)).unregisterForEmergencyNetworkScan(any());
+ verify(mCi, times(0)).unregisterForModemReset(any());
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testModemResetOnRequestEmergencyNetworkAfterNetworkScanDone()
+ throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();
+
+ assertNotNull(transportCallback);
+
+ DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
+ mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
+ false, 0, TELECOM_CALL_ID1, null, null, null);
+
+ mDsc.selectDomain(attr);
+
+ IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
+ transportCallback.onCreated(domainSelector);
+
+ IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);
+
+ assertNotNull(wwanCallback);
+
+ int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
+ int scanType = SCAN_TYPE_FULL_SERVICE;
+ IWwanSelectorResultCallback resultCallback =
+ Mockito.mock(IWwanSelectorResultCallback.class);
+
+ wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, false,
+ resultCallback);
+ processAllMessages();
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> scanEventCaptor = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> resetEventCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mPhone).registerForEmergencyNetworkScan(any(), scanEventCaptor.capture(), any());
+ verify(mCi).registerForModemReset(handlerCaptor.capture(),
+ resetEventCaptor.capture(), any());
+ processAllMessages();
+
+ int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
+
+ verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
+ eq(scanType), any());
+
+ Handler handler = handlerCaptor.getValue();
+ Integer scanEvent = scanEventCaptor.getValue();
+ Integer resetEvent = resetEventCaptor.getValue();
+
+ assertNotNull(handler);
+ assertNotNull(scanEvent);
+ assertNotNull(resetEvent);
+
+ EmergencyRegistrationResult regResult =
+ new EmergencyRegistrationResult(UTRAN, 0, 0, true, false, 0, 0, "", "", "");
+ handler.sendMessage(handler.obtainMessage(scanEvent,
+ new AsyncResult(null, regResult, null)));
+ processAllMessages();
+ wwanCallback.onDomainSelected(NetworkRegistrationInfo.DOMAIN_CS_PS, true);
+
+ handler.sendMessage(handler.obtainMessage(resetEvent, new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(resultCallback).onComplete(any());
+ verify(mPhone, times(0)).unregisterForEmergencyNetworkScan(any());
+ verify(mCi, times(0)).unregisterForModemReset(any());
+ verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
+ }
+
+ @Test
+ @SmallTest
public void testDomainSelectorCancelSelection() throws Exception {
mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
mDomainSelectionController);
@@ -601,6 +1002,7 @@
verify(mPhone).registerForEmergencyNetworkScan(
handlerCaptor.capture(), eventCaptor.capture(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
@@ -686,6 +1088,7 @@
verify(mPhone).registerForEmergencyNetworkScan(
handlerCaptor.capture(), eventCaptor.capture(), any());
+ verify(mCi).registerForModemReset(any(), anyInt(), any());
int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 0eb5c13..6694e98 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -21,6 +21,8 @@
import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS_PS;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
+import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN;
@@ -36,6 +38,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyVararg;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -121,6 +124,7 @@
doReturn(TelephonyManager.SIM_STATE_READY)
.when(mTelephonyManagerProxy).getSimState(anyInt());
+ doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
}
@After
@@ -135,7 +139,7 @@
EmergencyStateTracker.getInstance();
});
- EmergencyStateTracker.make(mContext, true);
+ EmergencyStateTracker.make(mContext, true, mFeatureFlags);
assertNotNull(EmergencyStateTracker.getInstance());
}
@@ -143,7 +147,7 @@
@Test
@SmallTest
public void getInstance_returnsSameInstance() {
- EmergencyStateTracker.make(mContext, true);
+ EmergencyStateTracker.make(mContext, true, mFeatureFlags);
EmergencyStateTracker instance1 = EmergencyStateTracker.getInstance();
EmergencyStateTracker instance2 = EmergencyStateTracker.getInstance();
@@ -180,7 +184,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
// isOkToCall() should return true when IN_SERVICE state
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -239,7 +243,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
// onTimeout should return true when radion on
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -287,7 +291,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
// Hangup the call
emergencyStateTracker.endCall(mTestConnection1);
@@ -323,7 +327,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF);
@@ -346,7 +350,7 @@
true /* isRadioOn */);
when(mSST.isRadioOn()).thenReturn(true);
// Satellite enabled
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(true);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(true);
setConfigForDdsSwitch(testPhone, null,
CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150");
@@ -359,11 +363,11 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0));
+ eq(false), eq(0), eq(false));
// isOkToCall() should return true once satellite modem is off
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(false);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(false);
assertTrue(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
// Once radio on is complete, trigger delay dial
@@ -391,7 +395,7 @@
Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
true /* isRadioOn */);
// Satellite enabled
- when(mSatelliteController.isSatelliteEnabled()).thenReturn(true);
+ when(mSatelliteController.isSatelliteEnabledOrBeingEnabled()).thenReturn(true);
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(testPhone,
mTestConnection1, false);
@@ -400,7 +404,7 @@
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(0));
+ eq(false), eq(0), eq(false));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.SATELLITE_ENABLED);
@@ -428,7 +432,7 @@
// Radio already on so shouldn't trigger this
verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
- anyBoolean(), eq(0));
+ anyBoolean(), eq(0), eq(false));
// Carrier supports control-plane fallback, so no DDS switch
verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
}
@@ -761,6 +765,8 @@
.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, true));
// Verify emergency callback mode set on modem
verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any());
+ // Verify emergency callback mode started with the correct emergency type
+ verify(testPhone).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
}
/**
@@ -819,6 +825,9 @@
processAllFutureMessages();
+ // Verify emergency callback mode stopped with the correct emergency type and reason.
+ verify(testPhone).stopEmergencyCallbackMode(eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL),
+ eq(TelephonyManager.STOP_REASON_TIMER_EXPIRED));
// Verify exitEmergencyMode() is called after timeout
verify(testPhone).exitEmergencyMode(any(Message.class));
assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -854,6 +863,9 @@
emergencyStateTracker.onCellularRadioPowerOffRequested();
+ // Verify emergency callback mode stopped with the correct emergency type and reason.
+ verify(testPhone).stopEmergencyCallbackMode(eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL),
+ eq(TelephonyManager.STOP_REASON_UNKNOWN));
// Verify exitEmergencyMode() is called.
verify(testPhone).exitEmergencyMode(any(Message.class));
assertFalse(emergencyStateTracker.isInEcm());
@@ -1005,7 +1017,8 @@
assertTrue(emergencyStateTracker.isInEcm());
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
-
+ verify(phone0, times(1)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
// Second emergency call started.
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
mTestConnection2, false);
@@ -1013,6 +1026,8 @@
assertFalse(future.isDone());
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0, times(1)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
}
@Test
@@ -1087,6 +1102,10 @@
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WLAN), any(Message.class));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
verify(phone0, never()).exitEmergencyMode(any(Message.class));
+ verify(phone0, times(2)).startEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
+ verify(phone0, never()).stopEmergencyCallbackMode(
+ eq(EMERGENCY_CALLBACK_MODE_CALL), anyInt());
}
@Test
@@ -1224,6 +1243,7 @@
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1256,6 +1276,7 @@
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1288,6 +1309,8 @@
verify(mCarrierConfigManager, times(2)).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
+ verify(phone0).restartEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
}
@@ -1413,6 +1436,7 @@
processAllMessages();
verify(phone0, times(2)).setEmergencyMode(anyInt(), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
// Expect: DisconnectCause#NOT_DISCONNECTED.
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
@@ -1473,6 +1497,8 @@
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone1,
TEST_SMS_ID_2, false);
+ verify(phone0).stopEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS),
+ eq(TelephonyManager.STOP_REASON_EMERGENCY_SMS_SENT));
verify(phone0).exitEmergencyMode(any(Message.class));
// Waits for exiting emergency mode on other phone.
assertFalse(future.isDone());
@@ -1726,6 +1752,7 @@
assertFalse(emergencyStateTracker.isInEmergencyCall());
assertTrue(emergencyStateTracker.isInScbm());
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
}
@Test
@@ -2156,6 +2183,7 @@
processAllMessages();
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInEmergencyCall());
@@ -2212,6 +2240,8 @@
// Enter emergency callback mode and emergency mode changed by SMS end.
verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
+ verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInEmergencyCall());
@@ -3168,7 +3198,7 @@
// Wait for the radio off for all phones
verify(mSST, times(2)).registerForVoiceRegStateOrRatChanged(any(), anyInt(), any());
verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
- anyBoolean(), eq(0));
+ anyBoolean(), eq(0), eq(false));
}
/**
@@ -3379,7 +3409,7 @@
anyInt(), anyInt(), any());
return new EmergencyStateTracker(mContext, mTestableLooper.getLooper(),
isSuplDdsSwitchRequiredForEmergencyCall, mPhoneFactoryProxy, mPhoneSwitcherProxy,
- mTelephonyManagerProxy, mRadioOnHelper, TEST_ECM_EXIT_TIMEOUT_MS);
+ mTelephonyManagerProxy, mRadioOnHelper, TEST_ECM_EXIT_TIMEOUT_MS, mFeatureFlags);
}
private Phone setupTestPhoneForEmergencyCall(boolean isRoaming, boolean isRadioOn) {
@@ -3483,6 +3513,7 @@
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
if (!emergencyStateTracker.isInEcm() && !emergencyStateTracker.isInEmergencyCall()) {
verify(phone).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+ verify(phone).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_SMS), anyLong());
}
assertTrue(emergencyStateTracker.isInEmergencyMode());
assertTrue(emergencyStateTracker.isInScbm());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
index 037f82c..e9bff91 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
@@ -90,11 +90,10 @@
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
verify(mMockPhone).unregisterForServiceStateChanged(any(Handler.class));
- verify(mSatelliteController).unregisterForModemStateChanged(anyInt(), any());
+ verify(mSatelliteController).unregisterForModemStateChanged(any());
verify(mMockPhone).registerForServiceStateChanged(any(Handler.class),
eq(RadioOnStateListener.MSG_SERVICE_STATE_CHANGED), isNull());
- verify(mSatelliteController, never()).registerForSatelliteModemStateChanged(
- anyInt(), any());
+ verify(mSatelliteController, never()).registerForSatelliteModemStateChanged(any());
verify(mMockCi).registerForOffOrNotAvailable(any(Handler.class),
eq(RadioOnStateListener.MSG_RADIO_OFF_OR_NOT_AVAILABLE), isNull());
@@ -105,13 +104,13 @@
*/
@Test
public void testRegisterForSatelliteCallback() {
- doReturn(true).when(mSatelliteController).isSatelliteEnabled();
+ doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
mListener.waitForRadioOn(mMockPhone, mCallback, false, false, 0);
waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
- verify(mSatelliteController).unregisterForModemStateChanged(anyInt(), any());
- verify(mSatelliteController).registerForSatelliteModemStateChanged(anyInt(), any());
+ verify(mSatelliteController).unregisterForModemStateChanged(any());
+ verify(mSatelliteController).registerForSatelliteModemStateChanged(any());
}
/**
@@ -205,7 +204,7 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(false), eq(false), eq(false));
verify(mSatelliteController, never()).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), eq(false), any());
+ eq(false), eq(false), eq(false), any());
}
@Test
@@ -225,12 +224,12 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(true), eq(true), eq(false));
verify(mSatelliteController, never()).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), eq(false), any());
+ eq(false), eq(false), eq(false), any());
}
@Test
public void testTimeout_RetryFailure_WithSatellite() {
- doReturn(true).when(mSatelliteController).isSatelliteEnabled();
+ doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
ServiceState state = new ServiceState();
state.setState(ServiceState.STATE_POWER_OFF);
when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
@@ -246,7 +245,7 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(true), eq(true), eq(false));
verify(mSatelliteController, times(2)).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), eq(false), any());
+ eq(false), eq(false), eq(false), any());
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index e374551..569785b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -41,7 +41,6 @@
import android.Manifest;
import android.annotation.Nullable;
import android.app.PendingIntent;
-import android.app.admin.flags.Flags;
import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.Intent;
@@ -49,6 +48,7 @@
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.os.Build;
+import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.UserManager;
@@ -87,8 +87,13 @@
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
import org.mockito.stubbing.Stubber;
@@ -106,6 +111,8 @@
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Rule
+ public MockitoRule rule = MockitoJUnit.rule();
private static final DownloadableSubscription SUBSCRIPTION =
DownloadableSubscription.forActivationCode("abcde");
@@ -145,8 +152,8 @@
private static final long AVAILABLE_MEMORY = 123L;
// Mocked classes
- private EuiccConnector mMockConnector;
- private UiccSlot mUiccSlot;
+ @Mock private EuiccConnector mMockConnector;
+ @Captor private ArgumentCaptor<Bundle> mBundleCaptor;
private TestEuiccController mController;
private int mSavedEuiccProvisionedValue;
@@ -218,8 +225,6 @@
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
- mMockConnector = Mockito.mock(EuiccConnector.class);
- mUiccSlot = Mockito.mock(UiccSlot.class);
mController = new TestEuiccController(mContext, mMockConnector, mFeatureFlags);
PackageInfo pi = new PackageInfo();
@@ -580,8 +585,15 @@
public void testDownloadSubscription_success() throws Exception {
setHasWriteEmbeddedPermission(true);
setUpUiccSlotData();
+
callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
EuiccService.RESULT_OK, 0 /* resolvableError */, "whatever" /* callingPackage */);
+
+ verify(mMockConnector).downloadSubscription(anyInt(), anyInt(),
+ any(), eq(true), anyBoolean(), mBundleCaptor.capture(), any());
+ assertEquals(
+ "whatever",
+ mBundleCaptor.getValue().getString(EuiccService.EXTRA_PACKAGE_NAME));
verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
// switchAfterDownload = true so no refresh should occur.
assertFalse(mController.mCalledRefreshSubscriptionsAndSendResult);
@@ -591,8 +603,15 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_noSwitch_success() throws Exception {
setHasWriteEmbeddedPermission(true);
+
callDownloadSubscription(SUBSCRIPTION, false /* switchAfterDownload */, true /* complete */,
EuiccService.RESULT_OK, 0 /* resolvableError */, "whatever" /* callingPackage */);
+
+ verify(mMockConnector).downloadSubscription(anyInt(), anyInt(),
+ any(), eq(false), anyBoolean(), mBundleCaptor.capture(), any());
+ assertEquals(
+ "whatever",
+ mBundleCaptor.getValue().getString(EuiccService.EXTRA_PACKAGE_NAME));
verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
assertTrue(mController.mCalledRefreshSubscriptionsAndSendResult);
}
@@ -857,7 +876,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_noAdminPermission()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(false);
setUpUiccSlotData();
@@ -883,7 +901,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_adminPermission()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setHasWriteEmbeddedPermission(false);
@@ -898,7 +915,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_adminPermission_usingSwitchAfterDownload_fails()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setUpUiccSlotData();
@@ -924,7 +940,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_profileOwner_usingSwitchAfterDownload_fails()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setUpUiccSlotData();
@@ -953,7 +968,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_orgOwnedProfileOwner_usingSwitchAfterDownload_success()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setUpUiccSlotData();
@@ -979,7 +993,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_deviceOwner_usingSwitchAfterDownload_success()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setUpUiccSlotData();
@@ -1005,7 +1018,6 @@
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_onlyAdminManagedAllowed_callerNotAdmin_error()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasManageDevicePolicyManagedSubscriptionsPermission(false);
setHasWriteEmbeddedPermission(true);
doReturn(true)
@@ -1021,27 +1033,8 @@
@Test
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
- public void testDownloadSubscription_onlyAdminManagedAllowed_callerNotAdmin_disabled_success()
- throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
- setHasManageDevicePolicyManagedSubscriptionsPermission(false);
- setHasWriteEmbeddedPermission(true);
- doReturn(true)
- .when(mUserManager)
- .hasUserRestriction(UserManager.DISALLOW_SIM_GLOBALLY);
-
- callDownloadSubscription(SUBSCRIPTION, false /* switchAfterDownload */, true /* complete */,
- EuiccService.RESULT_OK, 0 /* resolvableError */, "whatever" /* callingPackage */);
-
- verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
- assertTrue(mController.mCalledRefreshSubscriptionsAndSendResult);
- }
-
- @Test
- @DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
public void testDownloadSubscription_onlyAdminManagedAllowed_callerIsAdmin_success()
throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
setHasWriteEmbeddedPermission(false);
doReturn(true)
@@ -1102,7 +1095,6 @@
@Test
public void testDeleteSubscription_adminOwned_success() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(true);
String callingPackage = "whatever";
@@ -1126,33 +1118,7 @@
}
@Test
- public void testDeleteSubscription_adminOwned_featureDisabled_success() throws Exception {
- mSetFlagsRule.disableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
- setHasWriteEmbeddedPermission(true);
- setHasManageDevicePolicyManagedSubscriptionsPermission(false);
- String callingPackage = "whatever";
- SubscriptionInfo subInfo1 = new SubscriptionInfo.Builder()
- .setId(SUBSCRIPTION_ID)
- .setEmbedded(true)
- .setIccId(ICC_ID)
- .setCardId(CARD_ID)
- .setPortIndex(TelephonyManager.DEFAULT_PORT_INDEX)
- .setGroupOwner(callingPackage)
- .build();
- ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1));
- when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(subInfos);
-
- callDeleteSubscription(
- SUBSCRIPTION_ID, ICC_ID, true /* complete */,
- 0 /* result */, callingPackage /* callingPackage */);
-
- verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK,
- 0 /* detailedCode */);
- }
-
- @Test
public void testDeleteSubscription_adminOwned_noPermissions_error() throws Exception {
- mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
setHasManageDevicePolicyManagedSubscriptionsPermission(false);
String callingPackage = "whatever";
@@ -1940,6 +1906,8 @@
when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo), eq(PACKAGE_NAME), any()))
+ .thenReturn(hasPrivileges);
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
Collections.singletonList(subInfo));
}
@@ -1977,8 +1945,12 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo1), eq(PACKAGE_NAME),
+ any())).thenReturn(hasPrivileges);
when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo2), eq(PACKAGE_NAME),
+ any())).thenReturn(hasPrivileges);
ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1, subInfo2));
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subInfos);
}
@@ -1997,8 +1969,12 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo1, PACKAGE_NAME)).thenReturn(
false);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo1), eq(PACKAGE_NAME),
+ any())).thenReturn(false);
when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(
true);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo2), eq(PACKAGE_NAME),
+ any())).thenReturn(true);
ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1, subInfo2));
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subInfos);
}
@@ -2013,6 +1989,8 @@
.build();
when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
hasPrivileges);
+ when(mSubscriptionManager.canManageSubscriptionAsUser(eq(subInfo), eq(PACKAGE_NAME), any()))
+ .thenReturn(hasPrivileges);
when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
Collections.singletonList(subInfo));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
new file mode 100644
index 0000000..6e0d383
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
@@ -0,0 +1,214 @@
+/*
+ * 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.euicc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.never;
+
+import android.app.PendingIntent;
+import android.compat.testing.PlatformCompatChangeRule;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+import android.service.euicc.DownloadSubscriptionResult;
+import android.service.euicc.EuiccService;
+import android.service.euicc.GetDefaultDownloadableSubscriptionListResult;
+import android.service.euicc.GetDownloadableSubscriptionMetadataResult;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.UiccAccessRule;
+import android.telephony.UiccCardInfo;
+import android.telephony.UiccPortInfo;
+import android.telephony.euicc.DownloadableSubscription;
+import android.telephony.euicc.EuiccInfo;
+import android.telephony.euicc.EuiccManager;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.euicc.EuiccConnector.GetOtaStatusCommandCallback;
+import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback;
+import com.android.internal.telephony.uicc.euicc.apdu.ApduSender;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.uicc.UiccSlot;
+
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class EuiccSessionTest extends TelephonyTest {
+ @Rule
+ public final TestRule compatChangeRule = new PlatformCompatChangeRule();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Rule
+ public final MockitoRule rule = MockitoJUnit.rule();
+
+ private static final String SESSION_ID_1 = "SESSION_ID_1";
+ private static final String SESSION_ID_2 = "SESSION_ID_2";
+
+ private EuiccSession mEuiccSession;
+ @Mock private ApduSender mApduSender;
+ @Mock private ApduSender mApduSender2;
+
+ @Before
+ public void setUp() throws Exception {
+ mEuiccSession = new EuiccSession();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void startOneSession_featureDisabled_noop() throws Exception {
+ mEuiccSession.startSession(SESSION_ID_1);
+ mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.noteChannelOpen(mApduSender2);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+
+ mEuiccSession.endSession(SESSION_ID_1);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender, never()).closeAnyOpenChannel();
+ verify(mApduSender2, never()).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void startOneSession_endSession_hasSession() throws Exception {
+ mEuiccSession.startSession(SESSION_ID_1);
+ mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.noteChannelOpen(mApduSender2);
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+
+ mEuiccSession.endSession(SESSION_ID_2);
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+ verify(mApduSender, never()).closeAnyOpenChannel();
+
+ mEuiccSession.endSession(SESSION_ID_1);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender).closeAnyOpenChannel();
+ verify(mApduSender2).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void startTwoSession_endSession_hasSession() throws Exception {
+ mEuiccSession.startSession(SESSION_ID_1);
+ mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.startSession(SESSION_ID_2);
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+
+ mEuiccSession.endSession(SESSION_ID_1);
+ verify(mApduSender, never()).closeAnyOpenChannel();
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+
+ mEuiccSession.endSession(SESSION_ID_2);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void startTwoSessions_endAllSessions_hasSession() throws Exception {
+ mEuiccSession.startSession(SESSION_ID_1);
+ mEuiccSession.noteChannelOpen(mApduSender);
+ mEuiccSession.startSession(SESSION_ID_2);
+ mEuiccSession.noteChannelOpen(mApduSender2);
+
+ assertThat(mEuiccSession.hasSession()).isTrue();
+
+ mEuiccSession.endAllSessions();
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender).closeAnyOpenChannel();
+ verify(mApduSender2).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void noteChannelOpen_noSession_endSession_noop() throws Exception {
+ // noteChannelOpen called without a session started
+ mEuiccSession.noteChannelOpen(mApduSender);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+
+ mEuiccSession.endSession(SESSION_ID_1);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender, never()).closeAnyOpenChannel();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+ public void endAllSessions_noSession_endAllSessions_noOp() throws Exception {
+ // noteChannelOpen called without a session started
+ mEuiccSession.noteChannelOpen(mApduSender);
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+
+ mEuiccSession.endAllSessions();
+
+ assertThat(mEuiccSession.hasSession()).isFalse();
+ verify(mApduSender, never()).closeAnyOpenChannel();
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
index c261afe..e542a41 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -44,6 +44,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncResult;
@@ -109,6 +110,7 @@
private static final String RAW_TABLE_NAME = "raw";
private static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI,
RAW_TABLE_NAME);
+ private static final UserHandle MOCKED_MAIN_USER = UserHandle.of(0);
private final String mMessageBody = "This is the message body of a single-part message";
private final String mMessageBodyPart1 = "This is the first part of a multi-part message";
@@ -165,15 +167,19 @@
mSmsFilter = Mockito.mock(InboundSmsHandler.SmsFilter.class);
mSmsFilter2 = Mockito.mock(InboundSmsHandler.SmsFilter.class);
+ when(mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()).thenReturn(true);
doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
UserManager userManager = (UserManager)mContext.getSystemService(Context.USER_SERVICE);
doReturn(true).when(userManager).isUserUnlocked();
+ doReturn(true).when(userManager).isUserUnlocked(any(UserHandle.class));
doReturn(true).when(userManager).isUserRunning(any(UserHandle.class));
List<UserHandle> userHandles = new ArrayList();
- userHandles.add(UserHandle.SYSTEM);
+ userHandles.add(MOCKED_MAIN_USER);
+
+ doReturn(MOCKED_MAIN_USER).when(userManager).getMainUser();
doReturn(userHandles).when(userManager).getUserHandles(anyBoolean());
mSmsMessage.mWrappedSmsMessage = mGsmSmsMessage;
@@ -204,7 +210,7 @@
Telephony.Sms.CONTENT_URI.getAuthority(), mContentProvider);
mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(mContext,
- mSmsStorageMonitor, mPhone, mTestableLooper.getLooper());
+ mSmsStorageMonitor, mPhone, mTestableLooper.getLooper(), mFeatureFlags);
mSmsFilters = new ArrayList<>();
mSmsFilters.add(mSmsFilter);
mSmsFilters.add(mSmsFilter2);
@@ -331,6 +337,33 @@
@Test
@MediumTest
+ public void testNewSMSProcessedThroughMainUser() {
+ transitionFromStartupToIdle();
+ UserHandle mockedMainSecUser = UserHandle.of(10);
+
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ List<UserHandle> userHandles = new ArrayList();
+ userHandles.add(mockedMainSecUser);
+ doReturn(mockedMainSecUser).when(userManager).getMainUser();
+ doReturn(userHandles).when(userManager).getUserHandles(anyBoolean());
+
+ // send new SMS to state machine and verify that it triggers SMS_DELIVER_ACTION
+ // and context being used is from the MAIN user
+ sendNewSms();
+
+ // Verify that the context created to send the broadcast is created from the MAIN user.
+ try {
+ verify(mContext).createPackageContextAsUser(any(String.class),
+ any(Integer.class), eq(mockedMainSecUser));
+ } catch (PackageManager.NameNotFoundException e) {
+ fail(e.toString());
+ }
+
+ verifySmsIntentBroadcasts(0);
+ }
+
+ @Test
+ @MediumTest
public void testNewSmsFromBlockedNumber_noBroadcastsSent() {
String blockedNumber = "1234567890";
mFakeBlockedNumberContentProvider.mBlockedNumbers.add(blockedNumber);
@@ -352,6 +385,7 @@
// user locked
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
doReturn(false).when(userManager).isUserUnlocked();
+ doReturn(false).when(userManager).isUserUnlocked(any(UserHandle.class));
transitionFromStartupToIdle();
@@ -366,10 +400,19 @@
// New message notification should be shown.
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- verify(notificationManager).notify(
- eq(InboundSmsHandler.NOTIFICATION_TAG),
- eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
- any(Notification.class));
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ verify(notificationManager).notifyAsUser(
+ eq(InboundSmsHandler.NOTIFICATION_TAG),
+ eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
+ any(Notification.class),
+ eq(MOCKED_MAIN_USER));
+ } else {
+ verify(notificationManager).notify(
+ eq(InboundSmsHandler.NOTIFICATION_TAG),
+ eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
+ any(Notification.class));
+
+ }
}
@Test
@@ -381,6 +424,7 @@
// user locked
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
doReturn(false).when(userManager).isUserUnlocked();
+ doReturn(false).when(userManager).isUserUnlocked(any(UserHandle.class));
transitionFromStartupToIdle();
@@ -395,10 +439,19 @@
// No new message notification should be shown.
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
- verify(notificationManager, never()).notify(
- eq(InboundSmsHandler.NOTIFICATION_TAG),
- eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
- any(Notification.class));
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ verify(notificationManager, never()).notifyAsUser(
+ eq(InboundSmsHandler.NOTIFICATION_TAG),
+ eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
+ any(Notification.class),
+ eq(MOCKED_MAIN_USER));
+ } else {
+ verify(notificationManager, never()).notify(
+ eq(InboundSmsHandler.NOTIFICATION_TAG),
+ eq(InboundSmsHandler.NOTIFICATION_ID_NEW_MESSAGE),
+ any(Notification.class));
+
+ }
}
@Test
@@ -1042,16 +1095,23 @@
mContentProvider.insert(sRawUri, mInboundSmsTracker.getContentValues());
// user locked
- UserManager userManager = (UserManager)mContext.getSystemService(Context.USER_SERVICE);
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
doReturn(false).when(userManager).isUserUnlocked();
+ doReturn(false).when(userManager).isUserUnlocked(any(UserHandle.class));
- SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(
+ mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
- // verify that a broadcast receiver is registered for current user (user == null) based on
- // implementation in ContextFixture. registerReceiver may be called more than once (for
- // example by GsmInboundSmsHandler if TEST_MODE is true)
- verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class),
- any(IntentFilter.class));
+ if (mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()) {
+ verify(mContext).registerReceiverAsUser(any(BroadcastReceiver.class),
+ any(UserHandle.class), any(IntentFilter.class), any(), any());
+ } else {
+ // verify that a broadcast receiver is registered for current user (user == null) based
+ // on implementation in ContextFixture. registerReceiver may be called more than once
+ // (for example by GsmInboundSmsHandler if TEST_MODE is true)
+ verify(mContext, atLeastOnce()).registerReceiver(any(BroadcastReceiver.class),
+ any(IntentFilter.class));
+ }
// wait for ScanRawTableThread
waitForMs(100);
@@ -1062,7 +1122,10 @@
// when user unlocks the device, the message in db should be broadcast
doReturn(true).when(userManager).isUserUnlocked();
- mContext.sendBroadcast(new Intent(Intent.ACTION_USER_UNLOCKED));
+ doReturn(true).when(userManager).isUserUnlocked(any(UserHandle.class));
+ mContext.sendBroadcast(
+ new Intent(Intent.ACTION_USER_UNLOCKED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, MOCKED_MAIN_USER.getIdentifier()));
// wait for ScanRawTableThread
waitForMs(100);
processAllMessages();
@@ -1097,7 +1160,8 @@
// add a fake entry to db
mContentProvider.insert(sRawUri, mInboundSmsTracker.getContentValues());
- SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(
+ mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
// wait for ScanRawTableThread
waitForMs(100);
@@ -1112,7 +1176,8 @@
@MediumTest
public void testBroadcastUndeliveredDeleted() throws Exception {
replaceInstance(SmsBroadcastUndelivered.class, "instance", null, null);
- SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(
+ mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
mInboundSmsTracker = new InboundSmsTracker(
mContext,
mSmsPdu, /* pdu */
@@ -1138,7 +1203,9 @@
mContentProvider.insert(sRawUri, rawSms);
//when user unlocks the device, broadcast should not be sent for new message
- mContext.sendBroadcast(new Intent(Intent.ACTION_USER_UNLOCKED));
+ mContext.sendBroadcast(
+ new Intent(Intent.ACTION_USER_UNLOCKED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, MOCKED_MAIN_USER.getIdentifier()));
// wait for ScanRawTableThread
waitForMs(100);
processAllMessages();
@@ -1165,7 +1232,8 @@
when(mTelephonyComponentFactory).makeInboundSmsTracker(any(Context.class),
any(Cursor.class), anyBoolean());
- SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(
+ mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
// wait for ScanRawTableThread
waitForMs(100);
processAllMessages();
@@ -1183,7 +1251,8 @@
mContentProvider.insert(sRawUri, mInboundSmsTracker.getContentValues());
mContentProvider.insert(sRawUri, mInboundSmsTrackerSub1.getContentValues());
- SmsBroadcastUndelivered.initialize(mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
+ SmsBroadcastUndelivered.initialize(
+ mContext, mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
// wait for ScanRawTableThread
waitForMs(100);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
index 8374daa..639a2a3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -45,6 +45,7 @@
import android.content.pm.ServiceInfo;
import android.location.Country;
import android.location.CountryDetector;
+import android.os.Binder;
import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
@@ -114,6 +115,7 @@
private GsmSMSDispatcher mGsmSmsDispatcher;
private GsmSmsDispatcherTestHandler mGsmSmsDispatcherTestHandler;
+ private int mCallingUserId;
private class GsmSmsDispatcherTestHandler extends HandlerThread {
@@ -149,6 +151,7 @@
waitUntilReady();
mGsmSmsDispatcher = new GsmSMSDispatcher(mPhone, mSmsDispatchersController,
mGsmInboundSmsHandler);
+ mCallingUserId = Binder.getCallingUserHandle().getIdentifier();
processAllMessages();
}
@@ -177,7 +180,7 @@
.thenReturn(new Country("US", Country.COUNTRY_SOURCE_SIM));
mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class));
// Blocked number provider is notified about the emergency contact asynchronously.
@@ -197,7 +200,7 @@
mGsmSmsDispatcher.sendText(
getEmergencyNumberFromSystemPropertiesOrDefault(), "121" /*scAddr*/, "test sms",
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class));
// Blocked number provider is notified about the emergency contact asynchronously.
@@ -245,7 +248,7 @@
// send invalid dest address: +
mReceivedTestIntent = false;
mGsmSmsDispatcher.sendText("+", "222" /*scAddr*/, TAG,
- pendingIntent, null, null, null, false, -1, false, -1, false, 0L);
+ pendingIntent, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
waitForMs(500);
verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(),
any(Message.class));
@@ -310,7 +313,7 @@
// send SMS and check sentIntent
mReceivedTestIntent = false;
mGsmSmsDispatcher.sendMultipartText("+123" /*destAddr*/, "222" /*scAddr*/, parts,
- sentIntents, null, null, null, false, -1, false, -1, 0L);
+ sentIntents, null, null, null, mCallingUserId, false, -1, false, -1, 0L, 0L);
waitForMs(500);
synchronized (mLock) {
@@ -390,7 +393,7 @@
mReceivedTestIntent = false;
mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
- pendingIntent, null, null, null, false, -1, false, -1, false, 0L);
+ pendingIntent, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
processAllMessages();
synchronized (mLock) {
if (!mReceivedTestIntent) {
@@ -414,7 +417,7 @@
mGsmSmsDispatcher.mCarrierMessagingTimeout = 100;
mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
// wait for timeout
waitForMs(150);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class));
@@ -428,7 +431,7 @@
mockUiccWithCarrierApp();
mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
processAllMessages();
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class));
}
@@ -452,7 +455,8 @@
sentIntents.add(sentIntent2);
mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts,
- withSentIntents ? sentIntents : null, null, null, null, false, -1, false, -1, 0L);
+ withSentIntents ? sentIntents : null, null, null, null, mCallingUserId,
+ false, -1, false, -1, 0L, 0L);
}
@Test
@@ -524,7 +528,7 @@
}
mGsmSmsDispatcher.sendText("111", "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), pduCaptor.capture(),
@@ -545,7 +549,7 @@
messageRef += parts.size();
}
mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts,
- null, null, null, null, false, -1, false, -1, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, 0L, 0L);
waitForMs(150);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
@@ -561,14 +565,14 @@
@Test
public void testSendTextWithMessageRefNegativeBoundaryCondition() throws Exception {
mIsimUiccRecords = new IsimUiccRecords(mUiccCardApplication3gpp, mContext,
- mSimulatedCommands);
+ mSimulatedCommands, mFeatureFlags);
doReturn(mIsimUiccRecords).when(mPhone).getIccRecords();
Message msg = mGsmSmsDispatcher.obtainMessage(17);
mPhone.getIccRecords().setSmssTpmrValue(-1, msg);
mSubscriptionManagerService.setLastUsedTPMessageReference(mPhone.getSubId(), -1);
mGsmSmsDispatcher.sendText("111", "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), pduCaptor.capture(),
@@ -580,12 +584,12 @@
@Test
public void testSendTextWithMessageRefMaxBoundaryCondition() throws Exception {
mIsimUiccRecords = new IsimUiccRecords(mUiccCardApplication3gpp, mContext,
- mSimulatedCommands);
+ mSimulatedCommands, mFeatureFlags);
doReturn(mIsimUiccRecords).when(mPhone).getIccRecords();
Message msg = mGsmSmsDispatcher.obtainMessage(17);
mPhone.getIccRecords().setSmssTpmrValue(255, msg);
mGsmSmsDispatcher.sendText("111", "222" /*scAddr*/, TAG,
- null, null, null, null, false, -1, false, -1, false, 0L);
+ null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
verify(mSimulatedCommandsVerifier).sendSMS(anyString(), pduCaptor.capture(),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
index 3b362b1..8cf422e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.imsphone;
-import static android.telephony.CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA;
import static android.telephony.CarrierConfigManager.CARRIER_NR_AVAILABILITY_SA;
import static android.telephony.CarrierConfigManager.Ims.KEY_NR_SA_DISABLE_POLICY_INT;
import static android.telephony.CarrierConfigManager.Ims.NR_SA_DISABLE_POLICY_NONE;
@@ -24,6 +23,7 @@
import static android.telephony.CarrierConfigManager.Ims.NR_SA_DISABLE_POLICY_WFC_ESTABLISHED;
import static android.telephony.CarrierConfigManager.Ims.NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY;
+import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
@@ -32,6 +32,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.os.Handler;
@@ -55,7 +56,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Arrays;
import java.util.Set;
@RunWith(AndroidTestingRunner.class)
@@ -69,7 +69,7 @@
private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener;
private Handler mPreciseCallStateHandler;
- private Phone mPassthroughPhone;
+ private Phone mDefaultPhone;
@Mock private ImsPhoneCall mForegroundCall;
@Mock private ImsPhoneCall mBackgroundCall;
@@ -77,8 +77,7 @@
private Call.State mIdleState = ImsPhoneCall.State.IDLE;
private int mAnyInt = 0;
- private final Set<String> mFeatureTags =
- new ArraySet<String>(Arrays.asList(ImsNrSaModeHandler.MMTEL_FEATURE_TAG));
+ private final Set<String> mFeatureTags = new ArraySet<String>();
@Before
public void setUp() throws Exception {
@@ -96,12 +95,12 @@
doReturn(mContextFixture.getCarrierConfigBundle()).when(mCarrierConfigManager)
.getConfigForSubId(anyInt(), any());
- mPassthroughPhone = new GsmCdmaPhone(
+ mDefaultPhone = new GsmCdmaPhone(
mContext, mSimulatedCommands, mNotifier, true, 0,
PhoneConstants.PHONE_TYPE_GSM, mTelephonyComponentFactory,
(c, p) -> mImsManager, mFeatureFlags);
- doReturn(mPassthroughPhone).when(mImsPhone).getDefaultPhone();
+ doReturn(mDefaultPhone).when(mImsPhone).getDefaultPhone();
doReturn(mForegroundCall).when(mImsPhone).getForegroundCall();
doReturn(mBackgroundCall).when(mImsPhone).getBackgroundCall();
@@ -140,19 +139,19 @@
}
@Test
- public void testOnImsRegisteredWithSaDisablePolicyNone() {
+ public void testOnImsRegisteredWithNrSaCapabilityAndVoiceCapabilityAndSaDisablePolicyNone() {
mContextFixture.getCarrierConfigBundle().putInt(
KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_NONE);
mContextFixture.getCarrierConfigBundle().putIntArray(
KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
-
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
@@ -163,17 +162,24 @@
KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
verify(mImsPhone).registerForPreciseCallStateChanged(any(), anyInt(), any());
mSimulatedCommands.setN1ModeEnabled(false, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ mTestImsNrSaModeHandler.setNrSaDisabledForWfc(true);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
mTestImsNrSaModeHandler.setImsCallStatus(true);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
+
+ mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
+
+ assertFalse(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
@@ -185,54 +191,42 @@
KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
verify(mImsPhone).registerForPreciseCallStateChanged(any(), anyInt(), any());
mSimulatedCommands.setN1ModeEnabled(true, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
mTestImsNrSaModeHandler.setImsCallStatus(true);
mSimulatedCommands.setVonrEnabled(true);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
processAllMessages();
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
mSimulatedCommands.setN1ModeEnabled(true, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
mTestImsNrSaModeHandler.setImsCallStatus(true);
mSimulatedCommands.setVonrEnabled(false);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
processAllMessages();
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
assertFalse(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
mSimulatedCommands.setN1ModeEnabled(true, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
mTestImsNrSaModeHandler.setImsCallStatus(true);
- mSimulatedCommands.setVonrEnabled(false);
+ mSimulatedCommands.setVonrEnabled(true);
- mFeatureTags.remove(ImsNrSaModeHandler.MMTEL_FEATURE_TAG);
- mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
+ mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
processAllMessages();
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
assertTrue(mSimulatedCommands.isN1ModeEnabled());
-
- mSimulatedCommands.setN1ModeEnabled(true, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
- mTestImsNrSaModeHandler.setImsCallStatus(true);
- mSimulatedCommands.setVonrEnabled(false);
-
- mFeatureTags.add(ImsNrSaModeHandler.MMTEL_FEATURE_TAG);
- mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
- processAllMessages();
-
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
- assertFalse(mSimulatedCommands.isN1ModeEnabled());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
@@ -243,26 +237,50 @@
KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
+
+ verify(mImsPhone).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
mSimulatedCommands.setN1ModeEnabled(true, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
assertFalse(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
mSimulatedCommands.setN1ModeEnabled(false, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
- public void testOnImsUnregisteredDoNothingIfNotVowifiRegNoti() {
+ public void testOnImsRegisteredWithoutNrSaCapabilityWithSaDisablePolicyVowifiRegistered() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
+
+ verify(mImsPhone, times(0)).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
+
+ mSimulatedCommands.setN1ModeEnabled(true, null);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
+
+ mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
+
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
+ }
+
+ @Test
+ public void testOnImsRegisteredWithoutVoiceCapabilityWithSaDisablePolicyVowifiRegistered() {
mContextFixture.getCarrierConfigBundle().putInt(
KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
mContextFixture.getCarrierConfigBundle().putIntArray(
@@ -270,37 +288,100 @@
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ verify(mImsPhone).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
- mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_NONE);
+ mSimulatedCommands.setN1ModeEnabled(true, null);
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
+ mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
+
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
- public void testOnImsUnregisteredWithSaDisablePolicyVowifiRegistered() {
+ public void testOnImsUnregisteredWithoutNrSaCapability() {
mContextFixture.getCarrierConfigBundle().putInt(
KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
mContextFixture.getCarrierConfigBundle().putIntArray(
- KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
- mSimulatedCommands.setN1ModeEnabled(false, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_IWLAN);
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
- assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
+ }
+
+
+ @Test
+ public void testOnImsUnregisteredWithSaDisablePolicyNone() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_NONE);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
+
+ mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_IWLAN);
+
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
+ }
+
+ @Test
+ public void testOnImsUnregisteredWithoutRadioTechIwlan() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
+
+ mTestImsNrSaModeHandler.onImsUnregistered(NR_SA_DISABLE_POLICY_NONE);
+
+ assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
+ }
+
+ @Test
+ public void testOnImsUnregisteredWithoutWifiResistring() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+
+ mTestImsNrSaModeHandler.setWifiRegStatus(false);
+
+ mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_IWLAN);
+
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
+ }
+
+ @Test
+ public void testOnImsUnregisteredWithNrSaCapabilityAndVoiceCapabilityAndRadioTechIwlan() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_VOWIFI_REGISTERED);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
mSimulatedCommands.setN1ModeEnabled(false, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ mTestImsNrSaModeHandler.setNrSaDisabledForWfc(true);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
- mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_NONE);
+ mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_IWLAN);
- assertTrue(mTestImsNrSaModeHandler.isVowifiRegistered());
- assertFalse(mSimulatedCommands.isN1ModeEnabled());
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
}
@Test
@@ -311,12 +392,13 @@
KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
verify(mImsPhone).registerForPreciseCallStateChanged(
mPreciseCallStateHandlerCaptor.capture(), anyInt(), any());
mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
mSimulatedCommands.setN1ModeEnabled(true, null);
mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
@@ -324,38 +406,55 @@
assertTrue(mTestImsNrSaModeHandler.isImsCallOngoing());
assertFalse(mSimulatedCommands.isN1ModeEnabled());
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
- mSimulatedCommands.setN1ModeEnabled(true, null);
-
- doReturn(mActiveState).when(mForegroundCall).getState();
- doReturn(mActiveState).when(mBackgroundCall).getState();
- mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
-
- assertTrue(mTestImsNrSaModeHandler.isImsCallOngoing());
- assertTrue(mSimulatedCommands.isN1ModeEnabled());
-
- mTestImsNrSaModeHandler.setVowifiRegStatus(false);
- mTestImsNrSaModeHandler.setImsCallStatus(false);
- mSimulatedCommands.setN1ModeEnabled(true, null);
-
doReturn(mIdleState).when(mForegroundCall).getState();
doReturn(mIdleState).when(mBackgroundCall).getState();
mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
assertFalse(mTestImsNrSaModeHandler.isImsCallOngoing());
assertTrue(mSimulatedCommands.isN1ModeEnabled());
-
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
- mTestImsNrSaModeHandler.setImsCallStatus(true);
- mSimulatedCommands.setN1ModeEnabled(false, null);
- mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
-
- assertFalse(mTestImsNrSaModeHandler.isImsCallOngoing());
- assertTrue(mSimulatedCommands.isN1ModeEnabled());
}
@Test
- public void testUnregisterForPreciseCallStateChangeIfNeeded() {
+ public void testOnPreciseCallStateChangedWithSaDisablePolicyWfcEstablishedWithVonrDisabled() {
+ mContextFixture.getCarrierConfigBundle().putInt(
+ KEY_NR_SA_DISABLE_POLICY_INT,
+ NR_SA_DISABLE_POLICY_WFC_ESTABLISHED_WHEN_VONR_DISABLED);
+ mContextFixture.getCarrierConfigBundle().putIntArray(
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
+
+ mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
+
+ verify(mImsPhone).registerForPreciseCallStateChanged(
+ mPreciseCallStateHandlerCaptor.capture(), anyInt(), any());
+ mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
+
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
+ mSimulatedCommands.setN1ModeEnabled(true, null);
+ mSimulatedCommands.setVonrEnabled(false);
+
+ mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
+ processAllMessages();
+
+ assertFalse(mSimulatedCommands.isN1ModeEnabled());
+
+ doReturn(mIdleState).when(mForegroundCall).getState();
+ doReturn(mIdleState).when(mBackgroundCall).getState();
+ mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
+
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+
+ doReturn(mActiveState).when(mForegroundCall).getState();
+ doReturn(mActiveState).when(mBackgroundCall).getState();
+ mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
+ mTestImsNrSaModeHandler.setImsCallStatus(false);
+ processAllMessages();
+
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+ }
+
+ @Test
+ public void testOnCarrierConfigChangedRegisterOrUnregisterListenerForPreciseCallStateChange() {
mContextFixture.getCarrierConfigBundle().putInt(
KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_WFC_ESTABLISHED);
mContextFixture.getCarrierConfigBundle().putIntArray(
@@ -376,20 +475,29 @@
}
@Test
- public void testNrSaModeIsNotHandledWhenNotSupported() {
+ public void testUpdateImsCapabilityWithSaDisablePolicyWfcEstablished() {
mContextFixture.getCarrierConfigBundle().putInt(
KEY_NR_SA_DISABLE_POLICY_INT, NR_SA_DISABLE_POLICY_WFC_ESTABLISHED);
mContextFixture.getCarrierConfigBundle().putIntArray(
- KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_NSA});
+ KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_SA});
mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
- mSimulatedCommands.setN1ModeEnabled(false, null);
- mTestImsNrSaModeHandler.setVowifiRegStatus(true);
+ verify(mImsPhone).registerForPreciseCallStateChanged(
+ mPreciseCallStateHandlerCaptor.capture(), anyInt(), any());
+ mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
- mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
+ mTestImsNrSaModeHandler.setWifiRegStatus(true);
+ mSimulatedCommands.setN1ModeEnabled(true, null);
+ mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
- assertFalse(mTestImsNrSaModeHandler.isVowifiRegistered());
+ assertTrue(mTestImsNrSaModeHandler.isImsCallOngoing());
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
+
+ mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
assertFalse(mSimulatedCommands.isN1ModeEnabled());
+
+ mTestImsNrSaModeHandler.updateImsCapability(0);
+ assertTrue(mSimulatedCommands.isN1ModeEnabled());
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 6056112..a74a408 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -1477,6 +1477,17 @@
@Test
@SmallTest
+ public void testSipRequestCancelled() {
+ doReturn(true).when(mFeatureFlags).remapDisconnectCauseSipRequestCancelled();
+
+ assertEquals(DisconnectCause.NORMAL,
+ mCTUT.getDisconnectCauseFromReasonInfo(
+ new ImsReasonInfo(ImsReasonInfo.CODE_SIP_REQUEST_CANCELLED, 0),
+ Call.State.DIALING));
+ }
+
+ @Test
+ @SmallTest
public void testLowBatteryDisconnectDialing() {
assertEquals(DisconnectCause.DIAL_LOW_BATTERY, mCTUT.getDisconnectCauseFromReasonInfo(
new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_LOW_BATTERY, 0), Call.State.DIALING));
@@ -2774,6 +2785,32 @@
assertNetworkStatsEquals(expectedStats, uidStatsCaptor.getValue());
}
+ @Test
+ public void testPreventHangupDuringCallMerge() {
+ // Enable feature flag
+ doReturn(true).when(mFeatureFlags).preventHangupDuringCallMerge();
+
+ // Change carrier config to allow call hold for 2nd call setup
+ PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
+ bundle.putBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_VIDEO_CALL_BOOL, true);
+ mCTUT.updateCarrierConfigCache(bundle);
+
+ // Place a call.
+ placeCallAndMakeActive();
+ // Place a 2nd call
+ ImsPhoneConnection imsPhoneConnection = placeCallAndMakeActive();
+
+ // Try call merge
+ mCTUT.conference();
+
+ try {
+ mCTUT.hangup(imsPhoneConnection.getCall());
+ fail("Expect CallStateException but not");
+ } catch (CallStateException e) {
+ // Expected exception
+ }
+ }
+
private ImsPhoneConnection placeCallAndMakeActive() {
ImsPhoneConnection connection = placeCall();
ImsCall imsCall = connection.getImsCall();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index 3c1b045..6f42350 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -19,10 +19,13 @@
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.os.AsyncResult;
@@ -35,6 +38,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
@@ -54,6 +58,9 @@
private static final String TEST_DIAL_STRING_SERVICE_CODE = "*67911";
private static final String TEST_DIAL_STRING_NO_SERVICE_CODE = "*767911";
private static final String TEST_DIAL_STRING_NON_EMERGENCY_NUMBER = "11976";
+ private static final String TEST_DIAL_NUMBER = "123456789";
+ private static final String TEST_DIAL_STRING_CFNRY_ACTIVE_CODE = "**61*" + TEST_DIAL_NUMBER;
+ private static final String TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE = "##61#";
private ImsPhoneMmiCode mImsPhoneMmiCode;
private ImsPhone mImsPhoneUT;
@@ -90,7 +97,7 @@
// Test *67911 is treated as temporary mode CLIR
doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_SERVICE_CODE);
mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_SERVICE_CODE,
- mImsPhoneUT);
+ mImsPhoneUT, mFeatureFlags);
assertTrue(mImsPhoneMmiCode.isTemporaryModeCLIR());
}
@@ -99,7 +106,7 @@
// Test if prefix isn't *67 or *82
doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_NO_SERVICE_CODE);
mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NO_SERVICE_CODE,
- mImsPhoneUT);
+ mImsPhoneUT, mFeatureFlags);
assertTrue(mImsPhoneMmiCode == null);
}
@@ -107,13 +114,14 @@
public void testIsTemporaryModeCLIRForNonEmergencyNumber() {
// Test if dialing string isn't an emergency number
mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NON_EMERGENCY_NUMBER,
- mImsPhoneUT);
+ mImsPhoneUT, mFeatureFlags);
assertTrue(mImsPhoneMmiCode == null);
}
@Test
public void testNoCrashOnEmptyMessage() {
- ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+ ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+ mFeatureFlags);
try {
mmi.onUssdFinishedError();
} catch (Exception e) {
@@ -134,7 +142,8 @@
@Test
@SmallTest
public void testOperationNotSupported() {
- mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+ mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+ mFeatureFlags);
// Emulate request not supported from the network.
AsyncResult ar = new AsyncResult(null, null,
@@ -143,4 +152,80 @@
verify(mContext.getResources()).getText(
eq(com.android.internal.R.string.mmiErrorNotSupported));
}
+
+ @Test
+ @SmallTest
+ public void testActivationCfnrWithCfnry() throws Exception {
+ doNothing().when(mImsPhone).setCallForwardingOption(
+ anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+ doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+ int carrierConfigTime = 40;
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(CarrierConfigManager
+ .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+ int mmiTime = 30;
+ String withoutTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "#";
+ String withTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "**" + mmiTime + "#";
+
+ mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withoutTimeCode, mImsPhoneUT,
+ mFeatureFlags);
+ // For verification, replace the internal object of target with mock
+ replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+ mImsPhoneMmiCode.processCode();
+ verify(mImsPhone, times(1)).setCallForwardingOption(
+ eq(CommandsInterface.CF_ACTION_REGISTRATION),
+ anyInt(),
+ eq(TEST_DIAL_NUMBER),
+ anyInt(),
+ eq(carrierConfigTime),
+ any());
+
+ mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withTimeCode, mImsPhoneUT,
+ mFeatureFlags);
+ // For verification, replace the internal object of target with mock
+ replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+ mImsPhoneMmiCode.processCode();
+ verify(mImsPhone, times(1)).setCallForwardingOption(
+ eq(CommandsInterface.CF_ACTION_REGISTRATION),
+ anyInt(),
+ eq(TEST_DIAL_NUMBER),
+ anyInt(),
+ eq(mmiTime),
+ any());
+ }
+
+ @Test
+ @SmallTest
+ public void testDeactivationCfnrWithCfnry() throws Exception {
+ doNothing().when(mImsPhone).setCallForwardingOption(
+ anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+ doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+ int carrierConfigTime = 40;
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(CarrierConfigManager
+ .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+ mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE,
+ mImsPhoneUT, mFeatureFlags);
+ // For verification, replace the internal object of target with mock
+ replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+ mImsPhoneMmiCode.processCode();
+ verify(mImsPhone, times(1)).setCallForwardingOption(
+ eq(CommandsInterface.CF_ACTION_ERASURE),
+ anyInt(),
+ eq(null),
+ anyInt(),
+ eq(carrierConfigTime),
+ any());
+ }
}
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 8ee3a37..110dade 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -1146,6 +1146,8 @@
mSatelliteController1.countOfDemoModeIncomingDatagramFail = 2;
mSatelliteController1.countOfDatagramTypeKeepAliveSuccess = 1;
mSatelliteController1.countOfDatagramTypeKeepAliveFail = 2;
+ mSatelliteController1.isProvisioned = true;
+ mSatelliteController1.carrierId = 1;
mSatelliteController2 = new SatelliteController();
mSatelliteController2.countOfSatelliteServiceEnablementsSuccess = 2 + 1;
@@ -1173,6 +1175,8 @@
mSatelliteController2.countOfDemoModeIncomingDatagramFail = 3;
mSatelliteController2.countOfDatagramTypeKeepAliveSuccess = 4;
mSatelliteController2.countOfDatagramTypeKeepAliveFail = 5;
+ mSatelliteController2.isProvisioned = false;
+ mSatelliteController2.carrierId = 10;
// SatelliteController atom has one data point
mSatelliteControllers =
@@ -1182,12 +1186,12 @@
mSatelliteSession1 = new SatelliteSession();
mSatelliteSession1.satelliteServiceInitializationResult =
- SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteSession1.satelliteTechnology =
SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_PROPRIETARY;
mSatelliteSession1.count = 1;
mSatelliteSession1.satelliteServiceTerminationResult =
- SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteSession1.initializationProcessingTimeMillis = 100;
mSatelliteSession1.terminationProcessingTimeMillis = 200;
mSatelliteSession1.sessionDurationSeconds = 3;
@@ -1197,15 +1201,19 @@
mSatelliteSession1.countOfIncomingDatagramFailed = 0;
mSatelliteSession1.isDemoMode = false;
mSatelliteSession1.maxNtnSignalStrengthLevel = 2;
+ mSatelliteSession1.carrierId = 2;
+ mSatelliteSession1.countOfSatelliteNotificationDisplayed = 4;
+ mSatelliteSession1.countOfAutoExitDueToScreenOff = 6;
+ mSatelliteSession1.countOfAutoExitDueToTnNetwork = 7;
mSatelliteSession2 = new SatelliteSession();
mSatelliteSession2.satelliteServiceInitializationResult =
- SatelliteProtoEnums.SATELLITE_MODEM_ERROR;
+ SatelliteProtoEnums.SATELLITE_RESULT_MODEM_ERROR;
mSatelliteSession2.satelliteTechnology =
SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
mSatelliteSession2.count = 1;
mSatelliteSession2.satelliteServiceTerminationResult =
- SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteSession2.initializationProcessingTimeMillis = 300;
mSatelliteSession2.terminationProcessingTimeMillis = 100;
mSatelliteSession2.sessionDurationSeconds = 10;
@@ -1215,6 +1223,10 @@
mSatelliteSession2.countOfIncomingDatagramFailed = 1;
mSatelliteSession2.isDemoMode = true;
mSatelliteSession2.maxNtnSignalStrengthLevel = 4;
+ mSatelliteSession2.carrierId = 20;
+ mSatelliteSession2.countOfSatelliteNotificationDisplayed = 40;
+ mSatelliteSession2.countOfAutoExitDueToScreenOff = 60;
+ mSatelliteSession2.countOfAutoExitDueToTnNetwork = 70;
mSatelliteSessions =
new SatelliteSession[] {
@@ -1222,16 +1234,18 @@
};
mSatelliteIncomingDatagram1 = new SatelliteIncomingDatagram();
- mSatelliteIncomingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ mSatelliteIncomingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteIncomingDatagram1.datagramSizeBytes = 1 * 1024;
mSatelliteIncomingDatagram1.datagramTransferTimeMillis = 3 * 1000;
mSatelliteIncomingDatagram1.isDemoMode = false;
+ mSatelliteIncomingDatagram1.carrierId = 1;
mSatelliteIncomingDatagram2 = new SatelliteIncomingDatagram();
- mSatelliteIncomingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_MODEM_ERROR;
+ mSatelliteIncomingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_RESULT_MODEM_ERROR;
mSatelliteIncomingDatagram2.datagramSizeBytes = 512;
mSatelliteIncomingDatagram2.datagramTransferTimeMillis = 1 * 1000;
- mSatelliteIncomingDatagram1.isDemoMode = true;
+ mSatelliteIncomingDatagram2.isDemoMode = true;
+ mSatelliteIncomingDatagram2.carrierId = 10;
mSatelliteIncomingDatagrams =
new SatelliteIncomingDatagram[] {
@@ -1241,18 +1255,20 @@
mSatelliteOutgoingDatagram1 = new SatelliteOutgoingDatagram();
mSatelliteOutgoingDatagram1.datagramType =
SatelliteProtoEnums.DATAGRAM_TYPE_LOCATION_SHARING;
- mSatelliteOutgoingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ mSatelliteOutgoingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteOutgoingDatagram1.datagramSizeBytes = 1 * 1024;
mSatelliteOutgoingDatagram1.datagramTransferTimeMillis = 3 * 1000;
mSatelliteOutgoingDatagram1.isDemoMode = false;
+ mSatelliteOutgoingDatagram1.carrierId = 1;
mSatelliteOutgoingDatagram2 = new SatelliteOutgoingDatagram();
mSatelliteOutgoingDatagram2.datagramType =
SatelliteProtoEnums.DATAGRAM_TYPE_SOS_MESSAGE;
- mSatelliteOutgoingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_MODEM_ERROR;
+ mSatelliteOutgoingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_RESULT_MODEM_ERROR;
mSatelliteOutgoingDatagram2.datagramSizeBytes = 512;
mSatelliteOutgoingDatagram2.datagramTransferTimeMillis = 1 * 1000;
- mSatelliteOutgoingDatagram1.isDemoMode = true;
+ mSatelliteOutgoingDatagram2.isDemoMode = true;
+ mSatelliteOutgoingDatagram2.carrierId = 10;
mSatelliteOutgoingDatagrams =
new SatelliteOutgoingDatagram[] {
@@ -1260,17 +1276,19 @@
};
mSatelliteProvision1 = new SatelliteProvision();
- mSatelliteProvision1.resultCode = SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ mSatelliteProvision1.resultCode = SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS;
mSatelliteProvision1.provisioningTimeSec = 3 * 60;
mSatelliteProvision1.isProvisionRequest = true;
mSatelliteProvision1.isCanceled = false;
+ mSatelliteProvision1.carrierId = 1;
mSatelliteProvision2 = new SatelliteProvision();
mSatelliteProvision2.resultCode =
- SatelliteProtoEnums.SATELLITE_SERVICE_NOT_PROVISIONED;
+ SatelliteProtoEnums.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
mSatelliteProvision2.provisioningTimeSec = 0;
mSatelliteProvision2.isProvisionRequest = false;
mSatelliteProvision2.isCanceled = true;
+ mSatelliteProvision2.carrierId = 10;
mSatelliteProvisions =
new SatelliteProvision[] {
@@ -1286,6 +1304,8 @@
mSatelliteSosMessageRecommender1.isMultiSim = true;
mSatelliteSosMessageRecommender1.recommendingHandoverType = 1;
mSatelliteSosMessageRecommender1.isSatelliteAllowedInCurrentLocation = true;
+ mSatelliteSosMessageRecommender1.isWifiConnected = true;
+ mSatelliteSosMessageRecommender1.carrierId = 1;
mSatelliteSosMessageRecommender1.count = 1;
mSatelliteSosMessageRecommender2 = new SatelliteSosMessageRecommender();
@@ -1297,6 +1317,9 @@
mSatelliteSosMessageRecommender2.isMultiSim = false;
mSatelliteSosMessageRecommender2.recommendingHandoverType = 0;
mSatelliteSosMessageRecommender2.isSatelliteAllowedInCurrentLocation = true;
+ mSatelliteSosMessageRecommender2.isWifiConnected = false;
+ mSatelliteSosMessageRecommender2.carrierId = 2;
+
mSatelliteSosMessageRecommender2.count = 1;
mSatelliteSosMessageRecommenders =
@@ -1352,6 +1375,8 @@
mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMinSec = 2;
mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapAvgSec = 3;
mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec = 4;
+ mCarrierRoamingSatelliteControllerStats1.carrierId = 1;
+ mCarrierRoamingSatelliteControllerStats1.isDeviceEntitled = true;
mCarrierRoamingSatelliteControllerStats2 = new CarrierRoamingSatelliteControllerStats();
mCarrierRoamingSatelliteControllerStats2.configDataSource =
@@ -1362,6 +1387,8 @@
mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec = 5;
mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec = 10;
mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec = 15;
+ mCarrierRoamingSatelliteControllerStats2.carrierId = 10;
+ mCarrierRoamingSatelliteControllerStats2.isDeviceEntitled = false;
// CarrierRoamingSatelliteController has one data point
mCarrierRoamingSatelliteControllerStats = new CarrierRoamingSatelliteControllerStats[] {
@@ -1380,7 +1407,7 @@
mSatelliteEntitlement2.result = 1;
mSatelliteEntitlement2.entitlementStatus =
SatelliteProtoEnums.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
- mSatelliteEntitlement1.isRetry = true;
+ mSatelliteEntitlement2.isRetry = true;
mSatelliteEntitlement2.count = 1;
mSatelliteEntitlements = new SatelliteEntitlement[] {mSatelliteEntitlement1,
@@ -1414,10 +1441,11 @@
mSatelliteAccessController1.resultCode = SATELLITE_RESULT_SUCCESS;
mSatelliteAccessController1.countryCodes = new String[]{"AB", "CD"};
mSatelliteAccessController1.configDataSource = CONFIG_DATA_SOURCE_DEVICE_CONFIG;
+ mSatelliteAccessController1.carrierId = 1;
mSatelliteAccessController2 = new SatelliteAccessController();
- mSatelliteAccessController1.accessControlType = ACCESS_CONTROL_TYPE_CURRENT_LOCATION;
- mSatelliteAccessController1.locationQueryTimeMillis = TimeUnit.SECONDS.toMillis(4);
+ mSatelliteAccessController2.accessControlType = ACCESS_CONTROL_TYPE_CURRENT_LOCATION;
+ mSatelliteAccessController2.locationQueryTimeMillis = TimeUnit.SECONDS.toMillis(4);
mSatelliteAccessController2.onDeviceLookupTimeMillis = TimeUnit.SECONDS.toMillis(5);
mSatelliteAccessController2.totalCheckingTimeMillis = TimeUnit.SECONDS.toMillis(6);
mSatelliteAccessController2.isAllowed = false;
@@ -1425,6 +1453,7 @@
mSatelliteAccessController2.resultCode = SATELLITE_RESULT_SUCCESS;
mSatelliteAccessController2.countryCodes = new String[]{"EF", "GH"};
mSatelliteAccessController2.configDataSource = CONFIG_DATA_SOURCE_CONFIG_UPDATER;
+ mSatelliteAccessController2.carrierId = 10;
mSatelliteAccessControllers = new SatelliteAccessController[]{
mSatelliteAccessController1, mSatelliteAccessController2
@@ -4421,6 +4450,8 @@
expected.countOfDatagramTypeKeepAliveFail =
mSatelliteController1.countOfDatagramTypeKeepAliveFail
+ mSatelliteController2.countOfDatagramTypeKeepAliveFail;
+ expected.isProvisioned = mSatelliteController2.isProvisioned;
+ expected.carrierId = mSatelliteController2.carrierId;
// Service state and service switch should be added successfully
verifyCurrentStateSavedToFileOnce();
@@ -4943,41 +4974,56 @@
}
@Test
- public void addCarrierRoamingSatelliteControllerStats_withExistingEntries() throws Exception {
+ public void addCarrierRoamingSatelliteControllerStats_withExistingCarrierId() throws Exception {
createEmptyTestFile();
mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
- mCarrierRoamingSatelliteControllerStats1);
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
- mCarrierRoamingSatelliteControllerStats2);
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
mPersistAtomsStorage.incTimeMillis(100L);
CarrierRoamingSatelliteControllerStats expected =
new CarrierRoamingSatelliteControllerStats();
- expected.configDataSource = mCarrierRoamingSatelliteControllerStats2.configDataSource;
+ expected.configDataSource = mCarrierRoamingSatelliteControllerStats1.configDataSource;
expected.countOfEntitlementStatusQueryRequest =
- mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest
- + mCarrierRoamingSatelliteControllerStats2
- .countOfEntitlementStatusQueryRequest;
+ mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest * 2;
expected.countOfSatelliteConfigUpdateRequest =
- mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest
- + mCarrierRoamingSatelliteControllerStats2
- .countOfSatelliteConfigUpdateRequest;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest * 2;
expected.countOfSatelliteNotificationDisplayed =
- mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed
- + mCarrierRoamingSatelliteControllerStats2
- .countOfSatelliteNotificationDisplayed;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed * 2;
expected.satelliteSessionGapMinSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMinSec;
expected.satelliteSessionGapAvgSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapAvgSec;
expected.satelliteSessionGapMaxSec =
- mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec;
-
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec;
+ expected.carrierId = mCarrierRoamingSatelliteControllerStats1.carrierId;
+ expected.isDeviceEntitled = mCarrierRoamingSatelliteControllerStats1.isDeviceEntitled;
verifyCurrentStateSavedToFileOnce();
CarrierRoamingSatelliteControllerStats[] output =
mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
- assertHasStats(output, expected);
+ assertHasStats(output, expected, 1);
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteControllerStats_addNewCarrierId() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ copyOf(mCarrierRoamingSatelliteControllerStats1));
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ copyOf(mCarrierRoamingSatelliteControllerStats2));
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ CarrierRoamingSatelliteControllerStats expected1 = mCarrierRoamingSatelliteControllerStats1;
+ CarrierRoamingSatelliteControllerStats expected2 = mCarrierRoamingSatelliteControllerStats2;
+
+ CarrierRoamingSatelliteControllerStats[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
+
+ assertHasStats(output, expected1, 1);
+ assertHasStats(output, expected2, 1);
}
@Test
@@ -5825,6 +5871,18 @@
expectedStats.countOfDemoModeIncomingDatagramSuccess);
assertEquals(tested[0].countOfDemoModeIncomingDatagramFail,
expectedStats.countOfDemoModeIncomingDatagramFail);
+ assertEquals(tested[0].countOfDatagramTypeKeepAliveSuccess,
+ expectedStats.countOfDatagramTypeKeepAliveSuccess);
+ assertEquals(tested[0].countOfDatagramTypeKeepAliveFail,
+ expectedStats.countOfDatagramTypeKeepAliveFail);
+ assertEquals(tested[0].countOfAllowedSatelliteAccess,
+ expectedStats.countOfAllowedSatelliteAccess);
+ assertEquals(tested[0].countOfDisallowedSatelliteAccess,
+ expectedStats.countOfDisallowedSatelliteAccess);
+ assertEquals(tested[0].countOfSatelliteAccessCheckFail,
+ expectedStats.countOfSatelliteAccessCheckFail);
+ assertEquals(tested[0].isProvisioned, expectedStats.isProvisioned);
+ assertEquals(tested[0].carrierId, expectedStats.carrierId);
}
private static void assertHasStatsAndCount(
@@ -5851,7 +5909,14 @@
== expectedStats.countOfIncomingDatagramSuccess
&& stats.countOfIncomingDatagramFailed
== expectedStats.countOfIncomingDatagramFailed
- && stats.isDemoMode == expectedStats.isDemoMode) {
+ && stats.isDemoMode == expectedStats.isDemoMode
+ && stats.carrierId == expectedStats.carrierId
+ && stats.countOfSatelliteNotificationDisplayed
+ == expectedStats.countOfSatelliteNotificationDisplayed
+ && stats.countOfAutoExitDueToScreenOff
+ == expectedStats.countOfAutoExitDueToScreenOff
+ && stats.countOfAutoExitDueToTnNetwork
+ == expectedStats.countOfAutoExitDueToTnNetwork) {
actualCount = stats.count;
}
}
@@ -5868,7 +5933,8 @@
&& stats.datagramSizeBytes == expectedStats.datagramSizeBytes
&& stats.datagramTransferTimeMillis
== expectedStats.datagramTransferTimeMillis
- && stats.isDemoMode == expectedStats.isDemoMode) {
+ && stats.isDemoMode == expectedStats.isDemoMode
+ && stats.carrierId == expectedStats.carrierId) {
actualCount++;
}
}
@@ -5886,7 +5952,8 @@
&& stats.datagramSizeBytes == expectedStats.datagramSizeBytes
&& stats.datagramTransferTimeMillis
== expectedStats.datagramTransferTimeMillis
- && stats.isDemoMode == expectedStats.isDemoMode) {
+ && stats.isDemoMode == expectedStats.isDemoMode
+ && stats.carrierId == expectedStats.carrierId) {
actualCount++;
}
}
@@ -5902,7 +5969,8 @@
if (stats.resultCode == expectedStats.resultCode
&& stats.provisioningTimeSec == expectedStats.provisioningTimeSec
&& stats.isProvisionRequest == expectedStats.isProvisionRequest
- && stats.isCanceled == expectedStats.isCanceled) {
+ && stats.isCanceled == expectedStats.isCanceled
+ && stats.carrierId == expectedStats.carrierId) {
actualCount++;
}
}
@@ -5923,7 +5991,9 @@
&& stats.isMultiSim == expectedStats.isMultiSim
&& stats.recommendingHandoverType == expectedStats.recommendingHandoverType
&& stats.isSatelliteAllowedInCurrentLocation
- == expectedStats.isSatelliteAllowedInCurrentLocation) {
+ == expectedStats.isSatelliteAllowedInCurrentLocation
+ && stats.isWifiConnected == expectedStats.isWifiConnected
+ && stats.carrierId == expectedStats.carrierId) {
actualCount = stats.count;
}
}
@@ -5945,7 +6015,8 @@
&& stats.isEmergency == expectedStats.isEmergency
&& stats.resultCode == expectedStats.resultCode
&& Arrays.equals(stats.countryCodes, expectedStats.countryCodes)
- && stats.configDataSource == expectedStats.configDataSource) {
+ && stats.configDataSource == expectedStats.configDataSource
+ && stats.carrierId == expectedStats.carrierId) {
actualCount++;
}
}
@@ -6193,18 +6264,29 @@
}
private static void assertHasStats(CarrierRoamingSatelliteControllerStats[] tested,
- @Nullable CarrierRoamingSatelliteControllerStats expectedStats) {
+ @Nullable CarrierRoamingSatelliteControllerStats expectedStats, int expectedCount) {
assertNotNull(tested);
- assertEquals(tested[0].configDataSource, expectedStats.configDataSource);
- assertEquals(tested[0].countOfEntitlementStatusQueryRequest,
- expectedStats.countOfEntitlementStatusQueryRequest);
- assertEquals(tested[0].countOfSatelliteConfigUpdateRequest,
- expectedStats.countOfSatelliteConfigUpdateRequest);
- assertEquals(tested[0].countOfSatelliteNotificationDisplayed,
- expectedStats.countOfSatelliteNotificationDisplayed);
- assertEquals(tested[0].satelliteSessionGapMinSec, expectedStats.satelliteSessionGapMinSec);
- assertEquals(tested[0].satelliteSessionGapAvgSec, expectedStats.satelliteSessionGapAvgSec);
- assertEquals(tested[0].satelliteSessionGapMaxSec, expectedStats.satelliteSessionGapMaxSec);
+ int count = 0;
+ for (CarrierRoamingSatelliteControllerStats stats : tested) {
+ if (expectedStats.carrierId == stats.carrierId) {
+ assertEquals(expectedStats.configDataSource, stats.configDataSource);
+ assertEquals(expectedStats.countOfEntitlementStatusQueryRequest,
+ stats.countOfEntitlementStatusQueryRequest);
+ assertEquals(expectedStats.countOfSatelliteConfigUpdateRequest,
+ stats.countOfSatelliteConfigUpdateRequest);
+ assertEquals(expectedStats.countOfSatelliteNotificationDisplayed,
+ stats.countOfSatelliteNotificationDisplayed);
+ assertEquals(expectedStats.satelliteSessionGapMinSec,
+ stats.satelliteSessionGapMinSec);
+ assertEquals(expectedStats.satelliteSessionGapAvgSec,
+ stats.satelliteSessionGapAvgSec);
+ assertEquals(expectedStats.satelliteSessionGapMaxSec,
+ stats.satelliteSessionGapMaxSec);
+ assertEquals(expectedStats.isDeviceEntitled, stats.isDeviceEntitled);
+ count++;
+ }
+ }
+ assertEquals(expectedCount, count);
}
private static void assertHasStatsAndCount(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
index cda96ef..5740336 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
@@ -23,6 +23,7 @@
import static com.android.internal.telephony.satellite.SatelliteConstants.ACCESS_CONTROL_TYPE_CACHED_COUNTRY_CODE;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -102,6 +103,10 @@
.setCountOfDemoModeIncomingDatagramFail(2)
.setCountOfDatagramTypeKeepAliveSuccess(1)
.setCountOfDatagramTypeKeepAliveFail(2)
+ .setCountOfAllowedSatelliteAccess(1)
+ .setCountOfDisallowedSatelliteAccess(2)
+ .setCountOfSatelliteAccessCheckFail(3)
+ .setIsProvisioned(true)
.build();
mSatelliteStats.onSatelliteControllerMetrics(param);
@@ -160,6 +165,59 @@
stats.countOfDatagramTypeKeepAliveSuccess);
assertEquals(param.getCountOfDatagramTypeKeepAliveFail(),
stats.countOfDatagramTypeKeepAliveFail);
+ assertEquals(param.getCountOfAllowedSatelliteAccess(), stats.countOfAllowedSatelliteAccess);
+ assertEquals(param.getCountOfDisallowedSatelliteAccess(),
+ stats.countOfDisallowedSatelliteAccess);
+ assertEquals(param.getCountOfSatelliteAccessCheckFail(),
+ stats.countOfSatelliteAccessCheckFail);
+ assertEquals(param.isProvisioned(), stats.isProvisioned);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onSatelliteControllerMetrics_isProvisioned() throws Exception {
+ SatelliteStats.SatelliteControllerParams param =
+ new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSatelliteServiceEnablementsSuccess(2)
+ .setIsProvisioned(true)
+ .build();
+ mSatelliteStats.onSatelliteControllerMetrics(param);
+
+ ArgumentCaptor<SatelliteController> captor =
+ ArgumentCaptor.forClass(SatelliteController.class);
+ verify(mPersistAtomsStorage, times(1)).addSatelliteControllerStats(captor.capture());
+ SatelliteController stats = captor.getValue();
+ assertEquals(param.getCountOfSatelliteServiceEnablementsSuccess(),
+ stats.countOfSatelliteServiceEnablementsSuccess);
+ assertEquals(param.isProvisioned(), stats.isProvisioned);
+
+ param = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSatelliteServiceEnablementsSuccess(2)
+ .build();
+ mSatelliteStats.onSatelliteControllerMetrics(param);
+
+ captor = ArgumentCaptor.forClass(SatelliteController.class);
+ verify(mPersistAtomsStorage, times(2)).addSatelliteControllerStats(captor.capture());
+ stats = captor.getValue();
+ // count should be added
+ assertEquals(2, stats.countOfSatelliteServiceEnablementsSuccess);
+ // isProvisioned value should not be updated
+ assertEquals(true, stats.isProvisioned);
+
+ param = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSatelliteServiceEnablementsSuccess(2)
+ .setIsProvisioned(false)
+ .build();
+ mSatelliteStats.onSatelliteControllerMetrics(param);
+
+ captor = ArgumentCaptor.forClass(SatelliteController.class);
+ verify(mPersistAtomsStorage, times(3)).addSatelliteControllerStats(captor.capture());
+ stats = captor.getValue();
+ // count should be added
+ assertEquals(2, stats.countOfSatelliteServiceEnablementsSuccess);
+ // isProvisioned should be updated
+ assertEquals(false, stats.isProvisioned);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -169,9 +227,9 @@
SatelliteStats.SatelliteSessionParams param =
new SatelliteStats.SatelliteSessionParams.Builder()
.setSatelliteServiceInitializationResult(
- SatelliteProtoEnums.SATELLITE_ERROR_NONE)
+ SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS)
.setSatelliteTechnology(SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_PROPRIETARY)
- .setTerminationResult(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
+ .setTerminationResult(SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS)
.setInitializationProcessingTime(100)
.setTerminationProcessingTime(200)
.setSessionDuration(3)
@@ -212,7 +270,7 @@
public void onSatelliteIncomingDatagramMetrics_withAtoms() throws Exception {
SatelliteStats.SatelliteIncomingDatagramParams param =
new SatelliteStats.SatelliteIncomingDatagramParams.Builder()
- .setResultCode(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
+ .setResultCode(SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS)
.setDatagramSizeBytes(1 * 1024)
.setDatagramTransferTimeMillis(3 * 1000)
.setIsDemoMode(true)
@@ -236,7 +294,7 @@
SatelliteStats.SatelliteOutgoingDatagramParams param =
new SatelliteStats.SatelliteOutgoingDatagramParams.Builder()
.setDatagramType(SatelliteProtoEnums.DATAGRAM_TYPE_LOCATION_SHARING)
- .setResultCode(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
+ .setResultCode(SatelliteProtoEnums.SATELLITE_RESULT_SUCCESS)
.setDatagramSizeBytes(1 * 1024)
.setDatagramTransferTimeMillis(3 * 1000)
.setIsDemoMode(true)
@@ -261,7 +319,7 @@
SatelliteStats.SatelliteProvisionParams param =
new SatelliteStats.SatelliteProvisionParams.Builder()
.setResultCode(
- SatelliteProtoEnums.SATELLITE_SERVICE_PROVISION_IN_PROGRESS)
+ SatelliteProtoEnums.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS)
.setProvisioningTimeSec(5 * 1000)
.setIsProvisionRequest(true)
.setIsCanceled(false)
@@ -292,6 +350,8 @@
.setIsMultiSim(false)
.setRecommendingHandoverType(0)
.setIsSatelliteAllowedInCurrentLocation(true)
+ .setIsWifiConnected(true)
+ .setCarrierId(1)
.build();
mSatelliteStats.onSatelliteSosMessageRecommender(param);
@@ -309,6 +369,8 @@
assertEquals(param.getRecommendingHandoverType(), stats.recommendingHandoverType);
assertEquals(param.isSatelliteAllowedInCurrentLocation(),
stats.isSatelliteAllowedInCurrentLocation);
+ assertEquals(param.isWifiConnected(), stats.isWifiConnected);
+ assertEquals(param.getCarrierId(), stats.carrierId);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -372,6 +434,8 @@
.setSatelliteSessionGapMinSec(15)
.setSatelliteSessionGapAvgSec(30)
.setSatelliteSessionGapMaxSec(45)
+ .setCarrierId(10)
+ .setIsDeviceEntitled(true)
.build();
mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
@@ -390,6 +454,70 @@
assertEquals(param.getSatelliteSessionGapMinSec(), stats.satelliteSessionGapMinSec);
assertEquals(param.getSatelliteSessionGapAvgSec(), stats.satelliteSessionGapAvgSec);
assertEquals(param.getSatelliteSessionGapMaxSec(), stats.satelliteSessionGapMaxSec);
+ assertEquals(param.getCarrierId(), stats.carrierId);
+ assertEquals(param.isDeviceEntitled(), stats.isDeviceEntitled);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onCarrierRoamingSatelliteControllerStatsMetrics_testStaticFields()
+ throws Exception {
+ SatelliteStats.CarrierRoamingSatelliteControllerStatsParams param =
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setConfigDataSource(4)
+ .setCountOfEntitlementStatusQueryRequest(6)
+ .setCountOfSatelliteConfigUpdateRequest(2)
+ .setCountOfSatelliteNotificationDisplayed(1)
+ .setSatelliteSessionGapMinSec(15)
+ .setSatelliteSessionGapAvgSec(30)
+ .setSatelliteSessionGapMaxSec(45)
+ .setCarrierId(10)
+ .setIsDeviceEntitled(true)
+ .build();
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
+
+ ArgumentCaptor<CarrierRoamingSatelliteControllerStats> captor =
+ ArgumentCaptor.forClass(CarrierRoamingSatelliteControllerStats.class);
+ verify(mPersistAtomsStorage, times(1)).addCarrierRoamingSatelliteControllerStats(
+ captor.capture());
+ CarrierRoamingSatelliteControllerStats stats = captor.getValue();
+ assertEquals(param.getCountOfEntitlementStatusQueryRequest(),
+ stats.countOfEntitlementStatusQueryRequest);
+ assertEquals(param.getCarrierId(), stats.carrierId);
+ assertEquals(param.isDeviceEntitled(), stats.isDeviceEntitled);
+
+ param = new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCountOfSatelliteConfigUpdateRequest(2)
+ .build();
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
+
+ captor = ArgumentCaptor.forClass(CarrierRoamingSatelliteControllerStats.class);
+ verify(mPersistAtomsStorage, times(2)).addCarrierRoamingSatelliteControllerStats(
+ captor.capture());
+ stats = captor.getValue();
+ // count should be added
+ assertEquals(2, stats.countOfSatelliteConfigUpdateRequest);
+ // static values should not be updated
+ assertEquals(10, stats.carrierId);
+ assertEquals(true, stats.isDeviceEntitled);
+
+ param = new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCountOfSatelliteConfigUpdateRequest(2)
+ .setCarrierId(20)
+ .setIsDeviceEntitled(false)
+ .build();
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
+
+ captor = ArgumentCaptor.forClass(CarrierRoamingSatelliteControllerStats.class);
+ verify(mPersistAtomsStorage, times(3)).addCarrierRoamingSatelliteControllerStats(
+ captor.capture());
+ stats = captor.getValue();
+ // count should be added
+ assertEquals(2, stats.countOfSatelliteConfigUpdateRequest);
+ // static values should be updated
+ assertEquals(20, stats.carrierId);
+ assertEquals(false, stats.isDeviceEntitled);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index 04d140c..4347869 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -30,6 +30,10 @@
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_UNKNOWN;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -268,6 +272,8 @@
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -319,6 +325,8 @@
expectedCall.setupDurationMillis = 200;
expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 2200L, 1L);
@@ -363,6 +371,8 @@
expectedCall.setupDurationMillis = 200;
expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 2200L, 1L);
@@ -411,6 +421,8 @@
expectedCall.disconnectExtraMessage = "normal call clearing";
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 100000L, 1L);
@@ -569,6 +581,8 @@
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -628,6 +642,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.isMultiSim = false; // DSDS with one active SIM profile should not count
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
mVoiceCallSessionStats0.setTimeMillis(2000L);
doReturn(Call.State.INCOMING).when(mImsCall0).getState();
@@ -860,6 +876,8 @@
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
mVoiceCallSessionStats0.setTimeMillis(2000L);
doReturn(Call.State.INCOMING).when(mImsCall0).getState();
@@ -918,6 +936,8 @@
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 4000L, 1L);
@@ -996,6 +1016,8 @@
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 4000L, 1L);
@@ -1130,7 +1152,8 @@
expectedCall.rttEnabled = true;
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR;
-
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
mVoiceCallSessionStats0.setTimeMillis(2000L);
doReturn(Call.State.INCOMING).when(mImsCall0).getState();
doReturn(Call.State.INCOMING).when(mImsConnection0).getState();
@@ -1187,6 +1210,8 @@
expectedCall0.ratAtEnd = TelephonyManager.NETWORK_TYPE_HSPA;
expectedCall0.bandAtEnd = 0;
expectedCall0.lastKnownRat = TelephonyManager.NETWORK_TYPE_HSPA;
+ expectedCall0.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
// call 1 starts later, MT
doReturn(true).when(mImsConnection1).isIncoming();
doReturn(60000L).when(mImsConnection1).getCreateTime();
@@ -1210,6 +1235,8 @@
expectedCall1.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS;
expectedCall1.bandAtEnd = 0;
expectedCall1.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall1.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 80000L, 2L);
@@ -1319,6 +1346,8 @@
expectedCall0.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS;
expectedCall0.bandAtEnd = 0;
expectedCall0.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall0.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
// call 1 starts later, MT
doReturn(true).when(mImsConnection1).isIncoming();
doReturn(60000L).when(mImsConnection1).getCreateTime();
@@ -1342,6 +1371,8 @@
expectedCall1.ratAtEnd = TelephonyManager.NETWORK_TYPE_HSPA;
expectedCall1.bandAtEnd = 0;
expectedCall1.lastKnownRat = TelephonyManager.NETWORK_TYPE_HSPA;
+ expectedCall1.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 80000L, 2L);
@@ -1449,6 +1480,8 @@
expectedCall0.ratSwitchCount = 0L;
expectedCall0.ratSwitchCountAfterConnected = 0L;
expectedCall0.ratAtEnd = TelephonyManager.NETWORK_TYPE_LTE;
+ expectedCall0.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
// call 1 starts later, MT
doReturn(true).when(mImsConnection1).isIncoming();
doReturn(60000L).when(mImsConnection1).getCreateTime();
@@ -1472,6 +1505,8 @@
expectedCall1.ratAtEnd = TelephonyManager.NETWORK_TYPE_HSPA;
expectedCall1.bandAtEnd = 0;
expectedCall1.lastKnownRat = TelephonyManager.NETWORK_TYPE_HSPA;
+ expectedCall1.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 80000L, 2L);
@@ -1571,6 +1606,8 @@
expectedCall.disconnectExtraMessage = "normal call clearing";
expectedCall.callDuration =
VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_IWLAN, 2000L, 100000L, 1L);
@@ -1631,6 +1668,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 3000L, 1L);
@@ -1695,6 +1734,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_UNKNOWN;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_DISCONNECTED;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 3000L, 1L);
@@ -1753,6 +1794,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 3000L, 1L);
@@ -1818,6 +1861,8 @@
(1L << AudioCodec.AUDIO_CODEC_AMR) | (1L << AudioCodec.AUDIO_CODEC_AMR_WB);
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_UMTS, 2500L, 15000L, 1L);
@@ -1871,6 +1916,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.bandAtEnd = 0;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_UMTS, 2500L, 100000L, 1L);
@@ -1934,6 +1981,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 10000L, 1L);
@@ -2009,6 +2058,8 @@
expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR;
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2087,6 +2138,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 7000L, 1L);
@@ -2185,6 +2238,8 @@
expectedCall0.srvccCompleted = true;
expectedCall0.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
expectedCall0.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall0.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
// call 1 starts later, MT
doReturn(true).when(mImsConnection1).isIncoming();
doReturn(60000L).when(mImsConnection1).getCreateTime();
@@ -2213,6 +2268,8 @@
expectedCall1.srvccCompleted = true;
expectedCall1.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
expectedCall1.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
+ expectedCall1.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 80000L, 2L);
@@ -2312,6 +2369,8 @@
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.lastKnownRat = TelephonyManager.NETWORK_TYPE_UMTS;
expectedCall.handoverInProgress = false;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsageLte =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 3000L, 1L);
@@ -2386,6 +2445,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.handoverInProgress = true;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2440,6 +2501,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.handoverInProgress = true;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2498,6 +2561,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.handoverInProgress = false;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2562,6 +2627,8 @@
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.isEmergency = true;
expectedCall.handoverInProgress = true;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ACTIVE;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2627,6 +2694,8 @@
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
expectedCall.bandAtEnd = 0;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_IWLAN, 2000L, 8000L, 1L);
@@ -2677,6 +2746,8 @@
expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR;
expectedCall.mainCodecQuality =
VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_UNKNOWN;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_IWLAN, 2000L, 8000L, 1L);
@@ -2730,6 +2801,8 @@
expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
expectedCall.vonrEnabled = true;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
@@ -2826,6 +2899,8 @@
expectedCall.supportsBusinessCallComposer = true;
// 0 is defined as UNKNOWN, adding 1 to original value.
expectedCall.callComposerStatus = 3;
+ expectedCall.preciseCallStateOnSetup =
+ VOICE_CALL_SESSION__CALL_STATE_ON_SETUP__CALL_STATE_ALERTING;
VoiceCallRatUsage expectedRatUsage =
makeRatUsageProto(
CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
index 8173bbc..fdb94c9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
@@ -180,7 +180,7 @@
assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
- assertEquals(10, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
assertEquals(0, mTestStats.mCountOfProvisionSuccess);
assertEquals(0, mTestStats.mCountOfProvisionFail);
@@ -282,7 +282,7 @@
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
- assertEquals(10, mTestStats.mCountOfDatagramTypeLocationSharingFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
assertEquals(0, mTestStats.mCountOfProvisionSuccess);
assertEquals(0, mTestStats.mCountOfProvisionFail);
assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
index 2961b4d..21731f0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -92,8 +92,8 @@
// Move both send and receive to IDLE state
mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_UNKNOWN,
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS);
- mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
- SATELLITE_RESULT_SUCCESS);
+ mDatagramControllerUT.updateReceiveStatus(SUB_ID, DATAGRAM_TYPE_SOS_MESSAGE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS);
pushDemoModeSosDatagram(DATAGRAM_TYPE_SOS_MESSAGE);
}
@@ -197,7 +197,7 @@
errorCode);
verify(mMockSatelliteSessionController)
- .onDatagramTransferStateChanged(eq(sendState), anyInt());
+ .onDatagramTransferStateChanged(eq(sendState), anyInt(), anyInt());
verify(mMockPointingAppController).updateSendDatagramTransferState(
eq(SUB_ID), eq(datagramType), eq(sendState), eq(sendPendingCount), eq(errorCode));
@@ -219,10 +219,10 @@
int receivePendingCount = 1;
int errorCode = SATELLITE_RESULT_SUCCESS;
mDatagramControllerUT.updateReceiveStatus(
- SUB_ID, receiveState, receivePendingCount, errorCode);
+ SUB_ID, DATAGRAM_TYPE_SOS_MESSAGE, receiveState, receivePendingCount, errorCode);
verify(mMockSatelliteSessionController)
- .onDatagramTransferStateChanged(anyInt(), eq(receiveState));
+ .onDatagramTransferStateChanged(anyInt(), eq(receiveState), anyInt());
verify(mMockPointingAppController).updateReceiveDatagramTransferState(
eq(SUB_ID), eq(receiveState), eq(receivePendingCount), eq(errorCode));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index 7094399..142e70a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -16,9 +16,11 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import static com.android.internal.telephony.satellite.DatagramController.SATELLITE_ALIGN_TIMEOUT;
import static com.google.common.truth.Truth.assertThat;
@@ -47,10 +49,10 @@
import android.annotation.Nullable;
import android.content.Context;
import android.os.AsyncResult;
+import android.os.Binder;
import android.os.Looper;
import android.os.Message;
import android.telephony.Rlog;
-import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
@@ -59,6 +61,7 @@
import com.android.internal.R;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.SmsDispatchersController;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
@@ -91,6 +94,7 @@
SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP;
private static final int DATAGRAM_TYPE5 =
SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
+ private static final int DATAGRAM_TYPE6 = SatelliteManager.DATAGRAM_TYPE_SMS;
private static final String TEST_MESSAGE = "This is a test datagram message";
private static final long TEST_EXPIRE_TIMER_SATELLITE_ALIGN = TimeUnit.SECONDS.toMillis(1);
@@ -108,17 +112,20 @@
private TestDatagramDispatcher mDatagramDispatcherUT;
+ @Mock private SatelliteController mMockSatelliteController;
@Mock private DatagramController mMockDatagramController;
@Mock private DatagramReceiver mMockDatagramReceiver;
@Mock private SatelliteModemInterface mMockSatelliteModemInterface;
@Mock private ControllerMetricsStats mMockControllerMetricsStats;
@Mock private SatelliteSessionController mMockSatelliteSessionController;
@Mock private SessionMetricsStats mMockSessionMetricsStats;
+ @Mock private SmsDispatchersController mMockSmsDispatchersController;
/** Variables required to send datagram in the unit tests. */
LinkedBlockingQueue<Integer> mResultListener;
SatelliteDatagram mDatagram;
InOrder mInOrder;
+ private PendingRequest mPendingSms;
private static final long TIMEOUT = 500;
private List<Integer> mIntegerConsumerResult = new ArrayList<>();
@@ -142,6 +149,8 @@
MockitoAnnotations.initMocks(this);
logd(TAG + " Setup!");
+ replaceInstance(SatelliteController.class, "sInstance", null,
+ mMockSatelliteController);
replaceInstance(DatagramController.class, "sInstance", null,
mMockDatagramController);
replaceInstance(DatagramReceiver.class, "sInstance", null,
@@ -157,6 +166,7 @@
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mDatagramDispatcherUT = new TestDatagramDispatcher(mContext, Looper.myLooper(),
mFeatureFlags,
mMockDatagramController);
@@ -165,6 +175,10 @@
mDatagram = new SatelliteDatagram(TEST_MESSAGE.getBytes());
mInOrder = inOrder(mMockDatagramController);
when(mMockDatagramController.isPollingInIdleState()).thenReturn(true);
+ when(mMockSatelliteController.getSatellitePhone()).thenReturn(mPhone);
+ when(mPhone.getSmsDispatchersController()).thenReturn(mMockSmsDispatchersController);
+ when(mMockSatelliteController.getSatelliteCarrierId()).thenReturn(UNKNOWN_CARRIER_ID);
+ mPendingSms = createPendingRequest();
}
@After
@@ -175,6 +189,7 @@
mResultListener = null;
mDatagram = null;
mInOrder = null;
+ mPendingSms = null;
super.tearDown();
}
@@ -269,13 +284,13 @@
processAllMessages();
verifyZeroInteractions(mMockSatelliteModemInterface);
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ .updateSendStatus(eq(mPhone.getSubId()),
eq(datagramType),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
eq(1),
eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ .updateSendStatus(eq(mPhone.getSubId()),
eq(datagramType),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
eq(SATELLITE_RESULT_SUCCESS));
@@ -307,6 +322,9 @@
eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
assertEquals(0, mResultListener.size());
+ if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+ assertTrue(mDatagramDispatcherUT.isEmergencyCommunicationEstablished());
+ }
mDatagramDispatcherUT.onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
@@ -318,6 +336,7 @@
assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
verify(mMockSessionMetricsStats, times(1))
.addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
+ assertFalse(mDatagramDispatcherUT.isEmergencyCommunicationEstablished());
}
}
@@ -766,6 +785,360 @@
mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
}
+ @Test
+ public void testSendSms_success() {
+ int datagramType = DATAGRAM_TYPE6;
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ doReturn(true).when(mMockDatagramController).needsWaitingForSatelliteConnected(
+ eq(datagramType));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
+
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
+
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ processAllMessages();
+
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyNoMoreInteractions(mMockDatagramController);
+ }
+
+ @Test
+ public void testSendSms_failure() {
+ int datagramType = DATAGRAM_TYPE6;
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ doReturn(false).when(mMockDatagramController).needsWaitingForSatelliteConnected(
+ eq(datagramType));
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
+
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, false);
+ processAllMessages();
+
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(0),
+ eq(SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ }
+
+ @Test
+ public void testSendSms_handleEventDatagramWaitForConnectedStateTimedOut() {
+ int datagramType = DATAGRAM_TYPE6;
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ doReturn(true).when(mMockDatagramController).needsWaitingForSatelliteConnected(
+ eq(datagramType));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
+
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).onSendCarrierRoamingNbIotNtnTextError(
+ eq(mPendingSms), eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ }
+
+ @Test
+ public void testSendSms_handleModemStateOff() {
+ int datagramType = DATAGRAM_TYPE6;
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ doReturn(true).when(mMockDatagramController).needsWaitingForSatelliteConnected(
+ eq(datagramType));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
+
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).onSendCarrierRoamingNbIotNtnTextError(
+ eq(mPendingSms), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ }
+
+ @Test
+ public void testSendSmsAndDatagram_prioritizeDatagram() {
+ int datagramTypeSms = DATAGRAM_TYPE6;
+ int datagramTypeSos = DATAGRAM_TYPE1;
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[3];
+
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ new AsyncResult(message.obj, null, null))
+ .sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
+ anyBoolean(), anyBoolean(), any(Message.class));
+
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ clearInvocations(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSms));
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSos));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(
+ TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
+ mResultListener.clear();
+
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSms));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramTypeSms)));
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramTypeSos, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSos));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(2),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSms));
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSos));
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+ // First SOS message is sent, then SMS is sent
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSos));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(2),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos));
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+
+ // Send pending SMS
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSms));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
+
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ processAllMessages();
+
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyNoMoreInteractions(mMockDatagramController);
+ }
+
+ @Test
+ public void testSendSmsAndDatagram_sendingSmsAlreadyInProgress() {
+ int datagramTypeSms = DATAGRAM_TYPE6;
+ int datagramTypeSos = DATAGRAM_TYPE1;
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[3];
+
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ new AsyncResult(message.obj, null, null))
+ .sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
+ anyBoolean(), anyBoolean(), any(Message.class));
+
+ clearInvocations(mMockSmsDispatchersController);
+ clearInvocations(mMockDatagramController);
+ doReturn(false).when(mMockDatagramController).needsWaitingForSatelliteConnected(
+ eq(datagramTypeSms));
+ mDatagramDispatcherUT.sendSms(mPendingSms);
+ processAllMessages();
+
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSms));
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(mPhone.getSubId()), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSmsDispatchersController).sendCarrierRoamingNbIotNtnText(eq(mPendingSms));
+
+ // Sending SMS is already in progress, so datagram should not be sent
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramTypeSos, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+
+ mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSms),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+
+ // Send pending datagram
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramTypeSos));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramTypeSos),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos));
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ }
+
private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
try {
@@ -819,4 +1192,18 @@
private static void loge(String message) {
Rlog.e(TAG, message);
}
+
+ private static <T> ArrayList<T> asArrayList(T object) {
+ ArrayList<T> list = new ArrayList<>();
+ list.add(object);
+ return list;
+ }
+
+ private PendingRequest createPendingRequest() {
+ return new PendingRequest(
+ SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
+ Binder.getCallingUserHandle().getIdentifier(), "1111", "2222", asArrayList(null),
+ asArrayList(null), false, null, 0, asArrayList("text"), null, false, 0, false,
+ 10, 100L, false);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 947661b..a1f63d0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+
import static com.android.internal.telephony.satellite.DatagramController.SATELLITE_ALIGN_TIMEOUT;
import static com.google.common.truth.Truth.assertThat;
@@ -48,6 +50,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.provider.Telephony;
+import android.telephony.SubscriptionManager;
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
@@ -78,7 +81,7 @@
@TestableLooper.RunWithLooper
public class DatagramReceiverTest extends TelephonyTest {
private static final String TAG = "DatagramReceiverTest";
- private static final int SUB_ID = 0;
+ private static final int SUB_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
private static final String TEST_MESSAGE = "This is a test datagram message";
private static final long TEST_EXPIRE_TIMER_SATELLITE_ALIGN = TimeUnit.SECONDS.toMillis(1);
private static final long TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS =
@@ -144,6 +147,7 @@
when(mMockDatagramController.isPollingInIdleState()).thenReturn(true);
when(mMockDatagramController.needsWaitingForSatelliteConnected(
eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN))).thenReturn(false);
+ when(mMockSatelliteController.getSatelliteCarrierId()).thenReturn(UNKNOWN_CARRIER_ID);
processAllMessages();
}
@@ -183,6 +187,7 @@
mInOrder.verify(mMockDatagramController)
.needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
@@ -197,6 +202,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockSatelliteModemInterface, times(1))
@@ -221,9 +227,11 @@
moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
processAllMessages();
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verifyZeroInteractions(mMockSatelliteModemInterface);
@@ -262,10 +270,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR));
@@ -285,10 +295,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -308,10 +320,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
assertTrue(testSatelliteDatagramCallback.waitForOnSatelliteDatagramReceived());
@@ -335,6 +349,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS),
eq(10), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulIncomingDatagram();
@@ -352,16 +367,19 @@
verify(mMockDatagramController, times(1)).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -383,17 +401,20 @@
verify(mMockDatagramController, never()).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
processAllFutureMessages();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
anyInt(),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
@@ -445,10 +466,12 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED),
eq(10), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
@@ -464,6 +487,7 @@
mInOrder.verify(mMockDatagramController)
.updateReceiveStatus(anyInt(),
+ eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
index 319e39f..2b18468 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
@@ -119,7 +119,7 @@
moveToNotConnectedState();
verify(mISatelliteListener).onSatelliteModemStateChanged(
- SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ SatelliteModemState.SATELLITE_MODEM_STATE_OUT_OF_SERVICE);
ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
NtnSignalStrength.class);
verify(mISatelliteListener).onNtnSignalStrengthChanged(ntnSignalStrength.capture());
@@ -156,9 +156,9 @@
moveToConnectedState();
verify(mISatelliteListener).onSatelliteModemStateChanged(
- SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ SatelliteModemState.SATELLITE_MODEM_STATE_OUT_OF_SERVICE);
verify(mISatelliteListener).onSatelliteModemStateChanged(
- SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ SatelliteModemState.SATELLITE_MODEM_STATE_IN_SERVICE);
ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
NtnSignalStrength.class);
verify(mISatelliteListener, times(2))
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
index 36d32fe..a228617 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
@@ -39,6 +39,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.UserHandle;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.PointingInfo;
import android.telephony.satellite.SatelliteManager;
@@ -196,6 +197,11 @@
}
}
+ @Override
+ public void onSendDatagramRequested(int datagramType) {
+ logd("onSendDatagramRequested: datagramType=" + datagramType);
+ }
+
public int getDatagramType() {
return mDatagramType;
}
@@ -316,7 +322,7 @@
public void testStartPointingUI() throws Exception {
ArgumentCaptor<Intent> startedIntentCaptor = ArgumentCaptor.forClass(Intent.class);
mPointingAppController.startPointingUI(true, true, true);
- verify(mContext).startActivity(startedIntentCaptor.capture());
+ verify(mContext).startActivityAsUser(startedIntentCaptor.capture(), eq(UserHandle.CURRENT));
Intent intent = startedIntentCaptor.getValue();
assertEquals(KEY_POINTING_UI_PACKAGE_NAME, intent.getComponent().getPackageName());
assertEquals(KEY_POINTING_UI_CLASS_NAME, intent.getComponent().getClassName());
@@ -332,10 +338,12 @@
@Test
public void testRestartPointingUi() throws Exception {
mPointingAppController.startPointingUI(true, false, true);
- mInOrderForPointingUi.verify(mContext).startActivity(any(Intent.class));
+ mInOrderForPointingUi.verify(mContext).startActivityAsUser(any(Intent.class),
+ eq(UserHandle.CURRENT));
testRestartPointingUi(true, false, true);
mPointingAppController.startPointingUI(false, true, false);
- mInOrderForPointingUi.verify(mContext).startActivity(any(Intent.class));
+ mInOrderForPointingUi.verify(mContext).startActivityAsUser(any(Intent.class),
+ eq(UserHandle.CURRENT));
testRestartPointingUi(false, true, false);
}
@@ -346,7 +354,8 @@
.getPackagesForUid(anyInt());
mPointingAppController.mUidImportanceListener.onUidImportance(1, IMPORTANCE_GONE);
ArgumentCaptor<Intent> restartedIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- mInOrderForPointingUi.verify(mContext).startActivity(restartedIntentCaptor.capture());
+ mInOrderForPointingUi.verify(mContext).startActivityAsUser(restartedIntentCaptor.capture(),
+ eq(UserHandle.CURRENT));
Intent restartIntent = restartedIntentCaptor.getValue();
assertEquals(KEY_POINTING_UI_PACKAGE_NAME, restartIntent.getComponent().getPackageName());
assertEquals(KEY_POINTING_UI_CLASS_NAME, restartIntent.getComponent().getClassName());
@@ -413,7 +422,6 @@
TestSatelliteTransmissionUpdateCallback callback2 = new
TestSatelliteTransmissionUpdateCallback();
int subId1 = 3;
- int subId2 = 4;
mPointingAppController.registerForSatelliteTransmissionUpdates(subId1, callback1);
mInOrder.verify(mMockSatelliteModemInterface).registerForSatellitePositionInfoChanged(any(),
eq(1), eq(null));
@@ -424,16 +432,6 @@
.registerForSatellitePositionInfoChanged(any(), eq(1), eq(null));
mInOrder.verify(mMockSatelliteModemInterface, never())
.registerForDatagramTransferStateChanged(any(), eq(4), eq(null));
- mPointingAppController.registerForSatelliteTransmissionUpdates(subId2, callback1);
- mInOrder.verify(mMockSatelliteModemInterface).registerForSatellitePositionInfoChanged(any(),
- eq(1), eq(null));
- mInOrder.verify(mMockSatelliteModemInterface).registerForDatagramTransferStateChanged(any(),
- eq(4), eq(null));
- mPointingAppController.registerForSatelliteTransmissionUpdates(subId2, callback2);
- mInOrder.verify(mMockSatelliteModemInterface, never())
- .registerForSatellitePositionInfoChanged(any(), eq(1), eq(null));
- mInOrder.verify(mMockSatelliteModemInterface, never())
- .registerForDatagramTransferStateChanged(any(), eq(4), eq(null));
mPointingAppController.unregisterForSatelliteTransmissionUpdates(subId1,
mResultListener::offer, callback1);
processAllMessages();
@@ -446,22 +444,6 @@
any(Handler.class));
mInOrder.verify(mMockSatelliteModemInterface).unregisterForDatagramTransferStateChanged(
any(Handler.class));
- mPointingAppController.unregisterForSatelliteTransmissionUpdates(subId2,
- mResultListener::offer, callback1);
- processAllMessages();
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
- mResultListener.remove();
- mInOrder.verify(mMockSatelliteModemInterface, never())
- .unregisterForSatellitePositionInfoChanged(any(Handler.class));
- mInOrder.verify(mMockSatelliteModemInterface, never())
- .unregisterForDatagramTransferStateChanged(any(Handler.class));
- mPointingAppController.unregisterForSatelliteTransmissionUpdates(subId2,
- mResultListener::offer, callback2);
- processAllMessages();
- mInOrder.verify(mMockSatelliteModemInterface).unregisterForSatellitePositionInfoChanged(
- any(Handler.class));
- mInOrder.verify(mMockSatelliteModemInterface).unregisterForDatagramTransferStateChanged(
- any(Handler.class));
mInOrder = null;
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index d9ef95a..0a96f8c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -16,9 +16,21 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
+import static android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_MIGRATION;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
@@ -26,7 +38,11 @@
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_POOR;
import static android.telephony.satellite.SatelliteManager.KEY_DEMO_MODE_ENABLED;
+import static android.telephony.satellite.SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS;
+import static android.telephony.satellite.SatelliteManager.KEY_EMERGENCY_MODE_ENABLED;
import static android.telephony.satellite.SatelliteManager.KEY_NTN_SIGNAL_STRENGTH;
+import static android.telephony.satellite.SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS;
+import static android.telephony.satellite.SatelliteManager.KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_CAPABILITIES;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_ENABLED;
@@ -41,18 +57,21 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION;
import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_DISABLE_IN_PROGRESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
-import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_AUTHORIZED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_RESOURCES;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
@@ -64,6 +83,7 @@
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_TRUE;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -81,6 +101,7 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -89,9 +110,13 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.hardware.devicestate.DeviceState;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -99,14 +124,22 @@
import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Message;
+import android.os.OutcomeReceiver;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -119,6 +152,10 @@
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteManager.SatelliteException;
+import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SatelliteSubscriberInfo;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
+import android.telephony.satellite.SatelliteSubscriptionInfo;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
@@ -137,23 +174,26 @@
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
@@ -177,6 +217,8 @@
private static final int[] ACTIVE_SUB_IDS = {SUB_ID};
private static final int TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS =
(int) TimeUnit.SECONDS.toMillis(60);
+ private static final int TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS =
+ (int) TimeUnit.SECONDS.toMillis(60);
private static final String SATELLITE_PLMN = "00103";
private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
@@ -187,6 +229,7 @@
private PersistableBundle mCarrierConfigBundle;
private ServiceState mServiceState2;
+ @Mock private SatelliteController mMockSatelliteController;
@Mock private DatagramController mMockDatagramController;
@Mock private SatelliteModemInterface mMockSatelliteModemInterface;
@Mock private SatelliteSessionController mMockSatelliteSessionController;
@@ -205,6 +248,9 @@
@Mock private CellSignalStrength mCellSignalStrength;
@Mock private SatelliteConfig mMockConfig;
@Mock private DemoSimulator mMockDemoSimulator;
+ @Mock private Resources mResources;
+ @Mock private SubscriptionManager mSubscriptionManager;
+ @Mock private SubscriptionInfo mSubscriptionInfo;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -233,6 +279,17 @@
private SatelliteCapabilities mEmptySatelliteCapabilities = new SatelliteCapabilities(
new HashSet<>(), mIsPointingRequired, MAX_BYTES_PER_OUT_GOING_DATAGRAM,
new HashMap<>());
+ final int mCarrierId = 0;
+ final String mImsi = "1234567890123";
+ final String mNiddApn = "testApn";
+ final String mMsisdn = "0987654321";
+ final String mSubscriberId = mImsi.substring(0, 6) + mMsisdn;
+ final String mIccId = "1000000000000001";
+ final String mIccId2 = "2000000000000002";
+ final String mImsi2 = "2345678901234";
+ final String mMsisdn2 = "9876543210";
+ final String mSubscriberId2 = mIccId2;
+
private Semaphore mSatelliteCapabilitiesSemaphore = new Semaphore(0);
private SatelliteCapabilities mQueriedSatelliteCapabilities = null;
private int mQueriedSatelliteCapabilitiesResultCode = SATELLITE_RESULT_SUCCESS;
@@ -453,12 +510,35 @@
}
};
+ private boolean mRequestIsEmergency = false;
+ private ResultReceiver mRequestIsEmergencyReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ logd("requestIsEmergencyReceiver: resultCode=" + resultCode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_EMERGENCY_MODE_ENABLED)) {
+ mRequestIsEmergency = resultData.getBoolean(
+ KEY_EMERGENCY_MODE_ENABLED);
+ } else {
+ loge("KEY_EMERGENCY_MODE_ENABLED does not exist.");
+
+ }
+ }
+ }
+ };
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
logd(TAG + " Setup!");
+ replaceInstance(SatelliteController.class, "sInstance", null,
+ mMockSatelliteController);
replaceInstance(DatagramController.class, "sInstance", null,
mMockDatagramController);
replaceInstance(SatelliteModemInterface.class, "sInstance", null,
@@ -480,7 +560,9 @@
null, mMockTelephonyConfigUpdateInstallReceiver);
replaceInstance(DemoSimulator.class, "sInstance", null, mMockDemoSimulator);
- mServiceState2 = Mockito.mock(ServiceState.class);
+ doNothing().when(mMockSatelliteController).moveSatelliteToOffStateAndCleanUpResources(
+ SATELLITE_RESULT_REQUEST_ABORTED);
+ mServiceState2 = mock(ServiceState.class);
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getSubId()).thenReturn(SUB_ID);
when(mPhone.getPhoneId()).thenReturn(0);
@@ -494,6 +576,12 @@
mContextFixture.putIntResource(
R.integer.config_wait_for_satellite_enabling_response_timeout_millis,
TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS);
+ mContextFixture.putIntResource(
+ R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis,
+ TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS);
+ mContextFixture.putIntArrayResource(
+ R.array.config_foldedDeviceStates,
+ new int[0]);
doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
@@ -521,6 +609,7 @@
.onSatelliteEnabledStateChanged(anyBoolean());
doNothing().when(mMockSatelliteSessionController).onSatelliteModemStateChanged(anyInt());
doNothing().when(mMockSatelliteSessionController).setDemoMode(anyBoolean());
+ doNothing().when(mMockSatelliteSessionController).cleanUpResource();
doNothing().when(mMockControllerMetricsStats).onSatelliteEnabled();
doNothing().when(mMockControllerMetricsStats).reportServiceEnablementSuccessCount();
doNothing().when(mMockControllerMetricsStats).reportServiceEnablementFailCount();
@@ -538,15 +627,20 @@
.when(mMockSessionMetricsStats).setSessionDurationSec(anyInt());
doReturn(mMockSessionMetricsStats)
.when(mMockSessionMetricsStats).setIsDemoMode(anyBoolean());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setCarrierId(anyInt());
doNothing().when(mMockSessionMetricsStats).reportSessionMetrics();
doReturn(mMockProvisionMetricsStats).when(mMockProvisionMetricsStats)
.setResultCode(anyInt());
doReturn(mMockProvisionMetricsStats).when(mMockProvisionMetricsStats)
.setIsProvisionRequest(anyBoolean());
+ doReturn(mMockProvisionMetricsStats).when(mMockProvisionMetricsStats)
+ .setCarrierId(anyInt());
doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics();
doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
doReturn(mSST).when(mPhone).getServiceStateTracker();
doReturn(mSST).when(mPhone2).getServiceStateTracker();
doReturn(mServiceState).when(mSST).getServiceState();
@@ -556,10 +650,6 @@
Context.NOTIFICATION_SERVICE);
mSatelliteControllerUT =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
- verify(mMockSatelliteModemInterface).registerForSatelliteProvisionStateChanged(
- any(Handler.class),
- eq(26) /* EVENT_SATELLITE_PROVISION_STATE_CHANGED */,
- eq(null));
verify(mMockSatelliteModemInterface).registerForPendingDatagrams(
any(Handler.class),
eq(27) /* EVENT_PENDING_DATAGRAMS */,
@@ -571,6 +661,9 @@
doReturn(mMockConfigParser).when(mMockTelephonyConfigUpdateInstallReceiver)
.getConfigParser(ConfigProviderAdaptor.DOMAIN_SATELLITE);
+ doReturn(mSubscriptionInfo).when(mMockSubscriptionManagerService).getSubscriptionInfo(
+ anyInt());
+ doReturn("").when(mSubscriptionInfo).getIccId();
}
@After
@@ -581,18 +674,45 @@
}
@Test
+ public void testShouldTurnOffCarrierSatelliteForEmergencyCall() throws Exception {
+ DatagramController datagramController = mock(DatagramController.class);
+ replaceInstance(SatelliteController.class, "mDatagramController",
+ mSatelliteControllerUT, datagramController);
+
+ // Verify should turn off satellite
+ mCarrierConfigBundle.putBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL, true);
+ doReturn(false).when(datagramController).isEmergencyCommunicationEstablished();
+ invokeCarrierConfigChanged();
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+
+ assertTrue(mSatelliteControllerUT.shouldTurnOffCarrierSatelliteForEmergencyCall());
+
+ // Verify should NOT turn off satellite
+ mCarrierConfigBundle.putBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL, false);
+ doReturn(true).when(datagramController).isEmergencyCommunicationEstablished();
+ invokeCarrierConfigChanged();
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+
+ assertFalse(mSatelliteControllerUT.shouldTurnOffCarrierSatelliteForEmergencyCall());
+ }
+
+ @Test
public void testRequestTimeForNextSatelliteVisibility() {
mSatelliteVisibilityTimeSemaphore.drainPermits();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, mQueriedSatelliteVisibilityTimeResultCode);
resetSatelliteControllerUT();
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
@@ -604,11 +724,11 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestTimeForNextSatelliteVisibility(mSatelliteNextVisibilityTime,
SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
mQueriedSatelliteVisibilityTimeResultCode);
resetSatelliteControllerUT();
@@ -618,7 +738,7 @@
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestTimeForNextSatelliteVisibility(mSatelliteNextVisibilityTime,
SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
@@ -629,7 +749,7 @@
provisionSatelliteService();
setUpResponseForRequestTimeForNextSatelliteVisibility(mSatelliteNextVisibilityTime,
SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
@@ -640,7 +760,7 @@
provisionSatelliteService();
setUpNullResponseForRequestTimeForNextSatelliteVisibility(
SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
@@ -651,7 +771,7 @@
provisionSatelliteService();
setUpNullResponseForRequestTimeForNextSatelliteVisibility(
SATELLITE_RESULT_INVALID_MODEM_STATE);
- mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(SUB_ID,
+ mSatelliteControllerUT.requestTimeForNextSatelliteVisibility(
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
@@ -706,6 +826,87 @@
processAllMessages();
verify(mMockSatelliteModemInterface, times(5))
.requestIsSatelliteSupported(any(Message.class));
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Radio is off during TN -> NTN image switch, SatelliteController should not set radio
+ // state to OFF
+ setRadioPower(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Turn on radio
+ setRadioPower(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // SatelliteController should set the radio state to OFF
+ setRadioPower(false);
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Turn on radio
+ setRadioPower(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Modem fails to power off radio. APM is disabled
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // The timer WaitForCellularModemOff time out
+ moveTimeForward(TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Modem failed to power off the radio
+ mSatelliteControllerUT.onPowerOffCellularRadioFailed();
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
}
@Test
@@ -741,12 +942,13 @@
@Test
public void testRequestSatelliteEnabled() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mIsSatelliteEnabledSemaphore.drainPermits();
// Fail to enable satellite when SatelliteController is not fully loaded yet.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -754,47 +956,61 @@
// Fail to enable satellite when the device does not support satellite.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
// Fail to enable satellite when the device is not provisioned yet.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
resetSatelliteControllerUT();
verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(false));
- verify(mMockSatelliteSessionController, times(1)).setDemoMode(eq(false));
- verify(mMockDatagramController, times(1)).setDemoMode(eq(false));
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
(long) mIIntegerConsumerResults.get(0));
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- // Successfully enable satellite
+ // Fail to enable satellite when the emergency call is in progress
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ doReturn(true).when(mTelecomManager).isInEmergencyCall();
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS,
+ (long) mIIntegerConsumerResults.get(0));
+ doReturn(false).when(mTelecomManager).isInEmergencyCall();
+
+ // Successfully enable satellite
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, true, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, true, mIIntegerConsumer);
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteSessionController, times(1)).onEmergencyModeChanged(eq(true));
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
@@ -806,29 +1022,35 @@
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementSuccessCount();
// Successfully disable satellite when radio is turned off.
+ clearInvocations(mMockSatelliteSessionController);
+ clearInvocations(mMockDatagramController);
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
setRadioPower(false);
- mSatelliteControllerUT.onCellularRadioPowerOffRequested();
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
processAllMessages();
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_OFF, null);
processAllMessages();
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteSessionController, times(1)).onEmergencyModeChanged(eq(false));
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
SATELLITE_MODE_ENABLED_FALSE, mSatelliteControllerUT.satelliteModeSettingValue);
verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(false));
- verify(mMockSatelliteSessionController, times(3)).setDemoMode(eq(false));
- verify(mMockDatagramController, times(3)).setDemoMode(eq(false));
+ verify(mMockSatelliteSessionController, times(2)).setDemoMode(eq(false));
+ verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteDisabled();
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
// Fail to enable satellite when radio is off.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
// Radio is not on, can not enable satellite
@@ -840,13 +1062,13 @@
// Fail to enable satellite with an error response from modem when radio is on.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
clearInvocations(mMockPointingAppController);
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false,
SATELLITE_RESULT_INVALID_MODEM_STATE);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
@@ -859,11 +1081,11 @@
// Successfully enable satellite when radio is on.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -871,16 +1093,16 @@
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
- verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(true));
- verify(mMockSatelliteSessionController, times(4)).setDemoMode(eq(false));
- verify(mMockDatagramController, times(4)).setDemoMode(eq(false));
+ verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(true));
+ verify(mMockSatelliteSessionController, times(3)).setDemoMode(eq(false));
+ verify(mMockDatagramController, times(3)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(2)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(2)).reportServiceEnablementSuccessCount();
// Successfully enable satellite when it is already enabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -888,8 +1110,8 @@
// Fail to enable satellite with a different demo mode when it is already enabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, true, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.requestSatelliteEnabled(true, true, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_ARGUMENTS, (long) mIIntegerConsumerResults.get(0));
@@ -897,9 +1119,9 @@
// Successfully disable satellite.
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -907,8 +1129,8 @@
// Disable satellite when satellite is already disabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -916,8 +1138,8 @@
// Disable satellite with a different demo mode when satellite is already disabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, true, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.requestSatelliteEnabled(false, true, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -925,110 +1147,229 @@
// Send a second request while the first request in progress
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpNoResponseForRequestSatelliteEnabled(true, false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_REQUEST_IN_PROGRESS, (long) mIIntegerConsumerResults.get(0));
mIIntegerConsumerResults.clear();
- resetSatelliteControllerUTToSupportedAndProvisionedState();
- // Should receive callback for the above request when satellite modem is turned off.
+ mIIntegerConsumerSemaphore.drainPermits();
+ resetSatelliteControllerUT();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(false);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(true);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ // The enable request should be aborted when satellite modem move to OFF state.
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
+ assertEquals(SATELLITE_RESULT_REQUEST_ABORTED, (long) mIIntegerConsumerResults.get(0));
+
+ // Successfully enable satellite
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
// Move to satellite-disabling in progress.
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpNoResponseForRequestSatelliteEnabled(false, false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
// Disable is in progress. Thus, a new request to enable satellite will be rejected.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_ERROR, (long) mIIntegerConsumerResults.get(0));
+ assertEquals(SATELLITE_RESULT_DISABLE_IN_PROGRESS, (long) mIIntegerConsumerResults.get(0));
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
resetSatelliteControllerUTToOffAndProvisionedState();
- // Should receive callback for the above request when satellite modem is turned off.
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
-
- verify(mMockSessionMetricsStats, times(15)).setInitializationResult(anyInt());
- verify(mMockSessionMetricsStats, times(15)).setSatelliteTechnology(anyInt());
- verify(mMockSessionMetricsStats, times(3)).setInitializationProcessingTime(anyLong());
- verify(mMockSessionMetricsStats, times(2)).setTerminationResult(anyInt());
- verify(mMockSessionMetricsStats, times(2)).setTerminationProcessingTime(anyLong());
- verify(mMockSessionMetricsStats, times(2)).setSessionDurationSec(anyInt());
- verify(mMockSessionMetricsStats, times(15)).reportSessionMetrics();
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
* will lead to no response for requestSatelliteEnabled.
*/
mSatelliteControllerUT.allRadiosDisabled = false;
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- resetSatelliteControllerUTEnabledState();
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
// We should receive 2 callbacks for the above 2 requests.
assertTrue(waitForIIntegerConsumerResult(2));
+ // Successful result for disable request
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(1));
+ // The enable request should be aborted after getting the successful confirmation of the
+ // disable request.
+ assertEquals(SATELLITE_RESULT_REQUEST_ABORTED, (long) mIIntegerConsumerResults.get(1));
resetSatelliteControllerUTToOffAndProvisionedState();
// Repeat the same test as above but with error response from modem for the second request
mSatelliteControllerUT.allRadiosDisabled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
+ // No response for the enable request because all radios are not disabled yet
assertFalse(waitForIIntegerConsumerResult(1));
- resetSatelliteControllerUTEnabledState();
mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_NO_RESOURCES);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
- // We should receive 2 callbacks for the above 2 requests.
- assertTrue(waitForIIntegerConsumerResult(2));
- assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- assertEquals(SATELLITE_RESULT_NO_RESOURCES, (long) mIIntegerConsumerResults.get(1));
+ // We should receive result for the disable request.
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_NO_RESOURCES, (long) mIIntegerConsumerResults.get(0));
mSatelliteControllerUT.allRadiosDisabled = true;
resetSatelliteControllerUTToOnAndProvisionedState();
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
- mSatelliteControllerUT.onCellularRadioPowerOffRequested();
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
processAllMessages();
// Satellite should not be powered off since the feature flag oemEnabledSatelliteFlag is
// disabled
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Successfully disable satellite.
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ // Fail to enable satellite when radio is being powered off.
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ // Radio is being powered off, can not enable satellite
+ assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
+
+ // Modem failed to power off
+ mSatelliteControllerUT.onPowerOffCellularRadioFailed();
+
+ // Successfully enable satellite when radio is on.
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Clean up all previous resources
+ processAllFutureMessages();
+ mIIntegerConsumerSemaphore.drainPermits();
+
+ // Successfully disable satellite.
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ // Move to satellite-enabling in progress.
+ setUpNoResponseForRequestSatelliteEnabled(true, false, false);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertFalse(waitForIIntegerConsumerResult(1));
+
+ // Successfully disable satellite.
+ mIIntegerConsumerResults.clear();
+ mIIntegerConsumerSemaphore.drainPermits();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(2));
+ // Should get success result for the disable request
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ // The enable request should be aborted
+ assertEquals(SATELLITE_RESULT_REQUEST_ABORTED, (long) mIIntegerConsumerResults.get(1));
+ // All timers waiting for enablement response should be stopped
+ assertFalse(mSatelliteControllerUT.isAnyWaitForSatelliteEnablingResponseTimerStarted());
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ }
+
+ @Test
+ public void testGetRequestIsEmergency() {
+ mIsSatelliteEnabledSemaphore.drainPermits();
+ doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
+
+ // Successfully enable satellite
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+
+ // Set provisioned state
+ setProvisionedState(true);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ // Set response for enabling request
+ setUpResponseForRequestSatelliteEnabled(true, false, true/*emergency*/,
+ SATELLITE_RESULT_SUCCESS);
+ // Request satellite enabling for emergency
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, true /*isEmergency*/,
+ mIIntegerConsumer);
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+ processAllMessages();
+
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Verify satellite enabled for emergency
+ assertTrue(mSatelliteControllerUT.getRequestIsEmergency());
+ mSatelliteControllerUT.requestIsEmergencyModeEnabled(mRequestIsEmergencyReceiver);
+ assertTrue(mRequestIsEmergency);
}
@Test
public void testRequestSatelliteCapabilities() {
mSatelliteCapabilitiesSemaphore.drainPermits();
- mSatelliteControllerUT.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ mSatelliteControllerUT.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -1036,7 +1377,7 @@
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ mSatelliteControllerUT.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, mQueriedSatelliteCapabilitiesResultCode);
@@ -1046,7 +1387,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestSatelliteCapabilities(mSatelliteCapabilities,
SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ mSatelliteControllerUT.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
@@ -1059,7 +1400,7 @@
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpNullResponseForRequestSatelliteCapabilities(SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ mSatelliteControllerUT.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -1069,7 +1410,7 @@
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpNullResponseForRequestSatelliteCapabilities(SATELLITE_RESULT_INVALID_MODEM_STATE);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ mSatelliteControllerUT.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, mQueriedSatelliteCapabilitiesResultCode);
@@ -1079,7 +1420,7 @@
public void testStartSatelliteTransmissionUpdates() {
mIIntegerConsumerSemaphore.drainPermits();
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1089,7 +1430,7 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1099,11 +1440,11 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
(long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
@@ -1113,7 +1454,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
setUpResponseForStartSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1124,7 +1465,7 @@
provisionSatelliteService();
mIIntegerConsumerResults.clear();
setUpResponseForStartSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
verify(mMockPointingAppController).registerForSatelliteTransmissionUpdates(anyInt(),
eq(mStartTransmissionUpdateCallback));
@@ -1138,7 +1479,7 @@
provisionSatelliteService();
mIIntegerConsumerResults.clear();
setUpResponseForStartSatelliteTransmissionUpdates(SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
- mSatelliteControllerUT.startSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.startSatelliteTransmissionUpdates(mIIntegerConsumer,
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1151,54 +1492,11 @@
@Test
public void testStopSatelliteTransmissionUpdates() {
- mIIntegerConsumerSemaphore.drainPermits();
- mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
- mStopTransmissionUpdateCallback);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
- (long) mIIntegerConsumerResults.get(0));
-
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
- mStopTransmissionUpdateCallback);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
-
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
- mStopTransmissionUpdateCallback);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
- (long) mIIntegerConsumerResults.get(0));
-
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForStopSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
- mStopTransmissionUpdateCallback);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
- (long) mIIntegerConsumerResults.get(0));
-
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
provisionSatelliteService();
setUpResponseForStopSatelliteTransmissionUpdates(SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.stopSatelliteTransmissionUpdates(mIIntegerConsumer,
mStopTransmissionUpdateCallback);
verify(mMockPointingAppController).unregisterForSatelliteTransmissionUpdates(anyInt(),
any(), eq(mStopTransmissionUpdateCallback));
@@ -1211,9 +1509,13 @@
provisionSatelliteService();
mIIntegerConsumerResults.clear();
setUpResponseForStopSatelliteTransmissionUpdates(SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
- mSatelliteControllerUT.stopSatelliteTransmissionUpdates(SUB_ID, mIIntegerConsumer,
+ mSatelliteControllerUT.stopSatelliteTransmissionUpdates(mIIntegerConsumer,
mStopTransmissionUpdateCallback);
+ verify(mMockPointingAppController, times(2)).unregisterForSatelliteTransmissionUpdates(
+ anyInt(), any(), eq(mStopTransmissionUpdateCallback));
processAllMessages();
+ verify(mMockPointingAppController, times(2)).stopSatelliteTransmissionUpdates(
+ any(Message.class));
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
(long) mIIntegerConsumerResults.get(0));
@@ -1223,7 +1525,7 @@
public void testRequestIsDemoModeEnabled() {
mIsDemoModeEnabledSemaphore.drainPermits();
resetSatelliteControllerUT();
- mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
+ mSatelliteControllerUT.requestIsDemoModeEnabled(mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedIsDemoModeEnabledResultCode);
assertFalse(mQueriedIsDemoModeEnabled);
@@ -1231,7 +1533,7 @@
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
+ mSatelliteControllerUT.requestIsDemoModeEnabled(mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, mQueriedIsDemoModeEnabledResultCode);
assertFalse(mQueriedIsDemoModeEnabled);
@@ -1239,9 +1541,9 @@
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
+ mSatelliteControllerUT.requestIsDemoModeEnabled(mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedIsDemoModeEnabledResultCode);
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, mQueriedIsDemoModeEnabledResultCode);
assertFalse(mQueriedIsDemoModeEnabled);
resetSatelliteControllerUT();
@@ -1249,7 +1551,7 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
+ mSatelliteControllerUT.requestIsDemoModeEnabled(mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, mQueriedIsDemoModeEnabledResultCode);
assertFalse(mQueriedIsDemoModeEnabled);
@@ -1257,7 +1559,7 @@
resetSatelliteControllerUT();
boolean isDemoModeEnabled = mSatelliteControllerUT.isDemoModeEnabled();
provisionSatelliteService();
- mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
+ mSatelliteControllerUT.requestIsDemoModeEnabled(mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedIsDemoModeEnabledResultCode);
assertEquals(isDemoModeEnabled, mQueriedIsDemoModeEnabled);
@@ -1265,29 +1567,32 @@
@Test
public void testIsSatelliteEnabled() {
+ logd("testIsSatelliteEnabled: starting");
setUpResponseForRequestIsSatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
- assertFalse(mSatelliteControllerUT.isSatelliteEnabled());
+ assertFalse(mSatelliteControllerUT.isSatelliteEnabledOrBeingEnabled());
mIsSatelliteEnabledSemaphore.drainPermits();
- mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
+ mSatelliteControllerUT.requestIsSatelliteEnabled(mIsSatelliteEnabledReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteEnabledResult(1));
assertEquals(
SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedIsSatelliteEnabledResultCode);
+ logd("testIsSatelliteEnabled: setUpResponseForRequestIsSatelliteSupported");
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ logd("testIsSatelliteEnabled: verifySatelliteSupported");
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
+ mSatelliteControllerUT.requestIsSatelliteEnabled(mIsSatelliteEnabledReceiver);
processAllMessages();
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedIsSatelliteEnabledResultCode);
- assertEquals(mSatelliteControllerUT.isSatelliteEnabled(), mQueriedIsSatelliteEnabled);
+ assertEquals(mSatelliteControllerUT.isSatelliteEnabledOrBeingEnabled(),
+ mQueriedIsSatelliteEnabled);
}
@Test
public void testOnSatelliteServiceConnected() {
verifySatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
verifySatelliteEnabled(false, SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
@@ -1299,7 +1604,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -1309,9 +1614,18 @@
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ }
};
- int errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
- SUB_ID, callback);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
verify(mMockSatelliteSessionController, never())
.registerForSatelliteModemStateChanged(callback);
@@ -1319,8 +1633,7 @@
resetSatelliteControllerUTToSupportedAndProvisionedState();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
- SUB_ID, callback);
+ errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
verify(mMockSatelliteSessionController).registerForSatelliteModemStateChanged(callback);
}
@@ -1332,14 +1645,24 @@
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ }
};
- mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForModemStateChanged(callback);
verify(mMockSatelliteSessionController, never())
.unregisterForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForModemStateChanged(callback);
verify(mMockSatelliteSessionController).unregisterForSatelliteModemStateChanged(callback);
}
@@ -1358,31 +1681,46 @@
+ "semaphore, ex=" + ex);
}
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> status) {
+ logd("onSatelliteSubscriptionProvisionStateChanged: " + status);
+ }
};
- int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
- SUB_ID, callback);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
- SUB_ID, callback);
+ errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
- SUB_ID, callback);
+ errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
- sendProvisionedStateChangedEvent(true, null);
+ String mText = "This is test provision data.";
+ byte[] testProvisionData = mText.getBytes();
+ CancellationSignal cancellationSignal = new CancellationSignal();
+ ICancellationSignal cancelRemote = null;
+ mIIntegerConsumerResults.clear();
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
- mSatelliteControllerUT.unregisterForSatelliteProvisionStateChanged(SUB_ID, callback);
- sendProvisionedStateChangedEvent(true, null);
+ mSatelliteControllerUT.unregisterForSatelliteProvisionStateChanged(callback);
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
@@ -1399,11 +1737,11 @@
logd("onSatelliteDatagramReceived");
}
};
- when(mMockDatagramController.registerForSatelliteDatagram(eq(SUB_ID), eq(callback)))
+ when(mMockDatagramController.registerForSatelliteDatagram(anyInt(), eq(callback)))
.thenReturn(SATELLITE_RESULT_SUCCESS);
- int errorCode = mSatelliteControllerUT.registerForIncomingDatagram(SUB_ID, callback);
+ int errorCode = mSatelliteControllerUT.registerForIncomingDatagram(callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
- verify(mMockDatagramController).registerForSatelliteDatagram(eq(SUB_ID), eq(callback));
+ verify(mMockDatagramController).registerForSatelliteDatagram(anyInt(), eq(callback));
}
@Test
@@ -1418,9 +1756,9 @@
}
};
doNothing().when(mMockDatagramController)
- .unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
- mSatelliteControllerUT.unregisterForIncomingDatagram(SUB_ID, callback);
- verify(mMockDatagramController).unregisterForSatelliteDatagram(eq(SUB_ID), eq(callback));
+ .unregisterForSatelliteDatagram(anyInt(), eq(callback));
+ mSatelliteControllerUT.unregisterForIncomingDatagram(callback);
+ verify(mMockDatagramController).unregisterForSatelliteDatagram(anyInt(), eq(callback));
}
@Test
@@ -1439,7 +1777,7 @@
clearInvocations(mMockDatagramController);
clearInvocations(mMockPointingAppController);
- mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mSatelliteControllerUT.sendDatagram(datagramType, datagram, true,
mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1451,10 +1789,10 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(false, null);
+ setProvisionedState(false);
processAllMessages();
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mSatelliteControllerUT.sendDatagram(datagramType, datagram, true,
mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1464,10 +1802,10 @@
eq(datagramType), eq(datagram), eq(true), any());
mIIntegerConsumerResults.clear();
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mSatelliteControllerUT.sendDatagram(datagramType, datagram, true,
mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
@@ -1481,7 +1819,7 @@
@Test
public void testPollPendingSatelliteDatagrams() {
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -1491,10 +1829,10 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(false, null);
+ setProvisionedState(false);
processAllMessages();
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
@@ -1502,10 +1840,10 @@
verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any());
mIIntegerConsumerResults.clear();
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
+ mSatelliteControllerUT.pollPendingDatagrams(mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
verify(mMockDatagramController, times(1)).pollPendingSatelliteDatagrams(anyInt(), any());
@@ -1518,7 +1856,7 @@
CancellationSignal cancellationSignal = new CancellationSignal();
ICancellationSignal cancelRemote = null;
mIIntegerConsumerResults.clear();
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -1531,7 +1869,7 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -1545,9 +1883,7 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -1557,7 +1893,7 @@
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
// Send provision request again after the device is successfully provisioned
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -1565,70 +1901,19 @@
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
assertNull(cancelRemote);
- // Vendor service does not support the request requestIsSatelliteProvisioned. Telephony will
- // make decision itself
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(
- false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
-
- // Vendor service does not support the requests requestIsSatelliteProvisioned and
- // provisionSatelliteService. Telephony will make decision itself
- deprovisionSatelliteService();
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(
- false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
- TEST_SATELLITE_TOKEN,
- testProvisionData, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- assertNotNull(cancelRemote);
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
-
- resetSatelliteControllerUT();
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_NOT_AUTHORIZED);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
- TEST_SATELLITE_TOKEN,
- testProvisionData, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_NOT_AUTHORIZED, (long) mIIntegerConsumerResults.get(0));
- assertNotNull(cancelRemote);
-
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForProvisionSatelliteService(TEST_NEXT_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_NEXT_SATELLITE_TOKEN, testProvisionData, mIIntegerConsumer);
cancellationSignal.setRemote(cancelRemote);
cancellationSignal.cancel();
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- verify(mMockSatelliteModemInterface).deprovisionSatelliteService(
- eq(TEST_NEXT_SATELLITE_TOKEN), any(Message.class));
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
@@ -1636,13 +1921,10 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpNoResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN);
- setUpResponseForProvisionSatelliteService(TEST_NEXT_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_NEXT_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -1657,7 +1939,7 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1665,7 +1947,7 @@
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1676,13 +1958,11 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
- (long) mIIntegerConsumerResults.get(0));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
mIIntegerConsumerResults.clear();
@@ -1690,8 +1970,7 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1700,21 +1979,7 @@
resetSatelliteControllerUT();
provisionSatelliteService();
mIIntegerConsumerResults.clear();
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
- TEST_SATELLITE_TOKEN, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
-
- // Vendor service does not support deprovisionSatelliteService
- resetSatelliteControllerUT();
- provisionSatelliteService();
- mIIntegerConsumerResults.clear();
- setUpResponseForDeprovisionSatelliteService(
- TEST_SATELLITE_TOKEN, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1722,16 +1987,16 @@
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
resetSatelliteControllerUT();
- provisionSatelliteService();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(null);
mIIntegerConsumerResults.clear();
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN,
- SATELLITE_RESULT_INVALID_MODEM_STATE);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -2209,7 +2474,7 @@
TestSatelliteController satelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
mSatelliteCapabilitiesSemaphore.drainPermits();
- satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ satelliteController.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(
@@ -2223,7 +2488,7 @@
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
verifySatelliteSupported(satelliteController, true, SATELLITE_RESULT_SUCCESS);
mSatelliteCapabilitiesSemaphore.drainPermits();
- satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ satelliteController.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
@@ -2240,7 +2505,7 @@
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
verifySatelliteSupported(satelliteController, true, SATELLITE_RESULT_SUCCESS);
mSatelliteCapabilitiesSemaphore.drainPermits();
- satelliteController.requestSatelliteCapabilities(SUB_ID, mSatelliteCapabilitiesReceiver);
+ satelliteController.requestSatelliteCapabilities(mSatelliteCapabilitiesReceiver);
processAllMessages();
assertTrue(waitForRequestSatelliteCapabilitiesResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteCapabilitiesResultCode);
@@ -2269,16 +2534,23 @@
clearInvocations(mMockDatagramController);
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_UNAVAILABLE, null);
processAllMessages();
- verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(false));
- verify(mMockSatelliteSessionController, times(1)).setDemoMode(eq(false));
- verify(mMockDatagramController, times(1)).setDemoMode(eq(false));
+ verify(mMockSatelliteSessionController, times(1)).onSatelliteModemStateChanged(
+ eq(SATELLITE_MODEM_STATE_OFF));
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
- sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_CONNECTED, null);
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
processAllMessages();
verify(mMockSatelliteSessionController, times(1)).onSatelliteModemStateChanged(
- SATELLITE_MODEM_STATE_CONNECTED);
+ SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ clearInvocations(mMockSatelliteSessionController);
+ when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
+ processAllMessages();
+ verify(mMockSatelliteSessionController, never()).onSatelliteModemStateChanged(
+ SATELLITE_MODEM_STATE_NOT_CONNECTED);
}
@Test
@@ -2410,7 +2682,7 @@
assertEquals(expectedLevel, signalStrength[0].getLevel());
verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_POOR, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.unregisterForNtnSignalStrengthChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForNtnSignalStrengthChanged(callback);
sendNtnSignalStrengthChangedEvent(NTN_SIGNAL_STRENGTH_GREAT, null);
processAllMessages();
assertFalse(waitForForEvents(
@@ -2724,21 +2996,18 @@
}
};
- int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
setUpResponseForRequestIsSatelliteSupported(false,
SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
resetSatelliteControllerUT();
provisionSatelliteService();
- errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
SatelliteCapabilities expectedCapabilities = mSatelliteCapabilities;
sendSatelliteCapabilitiesChangedEvent(expectedCapabilities, null);
@@ -2754,7 +3023,7 @@
semaphore, 1, "testRegisterForSatelliteCapabilitiesChanged"));
assertTrue(expectedCapabilities.equals(satelliteCapabilities[0]));
- mSatelliteControllerUT.unregisterForCapabilitiesChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForCapabilitiesChanged(callback);
expectedCapabilities = mSatelliteCapabilities;
sendSatelliteCapabilitiesChangedEvent(expectedCapabilities, null);
processAllMessages();
@@ -2783,22 +3052,19 @@
}
};
- int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
setUpResponseForRequestIsSatelliteSupported(false,
SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
- errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
- errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(SUB_ID,
- callback);
+ errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
SatelliteCapabilities expectedCapabilities = mSatelliteCapabilities;
@@ -2885,8 +3151,8 @@
List<String> barredPlmnList = new ArrayList<>();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
// If the entitlement plmn list and the overlay config plmn list are available and the
// carrier plmn list and the barred plmn list are empty, verify passing to the modem.
@@ -2943,32 +3209,32 @@
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", ""}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
// If the entitlement plmn list is invalid, verify not passing to the modem.
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "123456789"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
// If the entitlement plmn list is invalid, verify not passing to the modem.
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "12"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
// If the entitlement plmn list is invalid, verify not passing to the modem.
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "1234"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
}
private void verifyPassingToModemAfterQueryCompleted(List<String> entitlementPlmnList,
@@ -3334,14 +3600,17 @@
}
@Test
- public void testHandleEventServiceStateChanged() throws Exception {
+ public void testHandleEventServiceStateChanged() {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+ CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
+ invokeCarrierConfigChanged();
+
// Do nothing when the satellite is not connected
doReturn(false).when(mServiceState).isUsingNonTerrestrialNetwork();
sendServiceStateChangedEvent();
processAllMessages();
- assertEquals(false,
- mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
+ assertFalse(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
verify(mMockNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
// Check sending a system notification when the satellite is connected
@@ -3350,13 +3619,14 @@
processAllMessages();
verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
any());
- assertEquals(true,
- mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
+ // Just by showing notification we do not update the pref file , only once user interact
+ // only we will update the pref value to true.
+ assertFalse(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
// Check don't display again after displayed already a system notification.
sendServiceStateChangedEvent();
processAllMessages();
- verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
+ verify(mMockNotificationManager, times(2)).notifyAsUser(anyString(), anyInt(), any(),
any());
}
@@ -3366,38 +3636,44 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
// Successfully disable satellite
mIIntegerConsumerResults.clear();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
// Time out to enable satellite
+ ArgumentCaptor<SatelliteModemEnableRequestAttributes> enableSatelliteRequest =
+ ArgumentCaptor.forClass(SatelliteModemEnableRequestAttributes.class);
ArgumentCaptor<Message> enableSatelliteResponse = ArgumentCaptor.forClass(Message.class);
mIIntegerConsumerResults.clear();
setUpNoResponseForRequestSatelliteEnabled(true, false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ clearInvocations(mMockSatelliteModemInterface);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(true), eq(false), eq(false),
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+ enableSatelliteRequest.capture(),
enableSatelliteResponse.capture());
+ SatelliteModemEnableRequestAttributes request = enableSatelliteRequest.getValue();
+ assertTrue(request.isEnabled());
+ assertFalse(request.isDemoMode());
+ assertFalse(request.isEmergencyMode());
clearInvocations(mMockSatelliteModemInterface);
moveTimeForward(TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_MODEM_TIMEOUT, (long) mIIntegerConsumerResults.get(0));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false),
- eq(false), any(Message.class));
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
// Send the response for the above request to enable satellite. SatelliteController should
@@ -3411,8 +3687,7 @@
// Successfully enable satellite
mIIntegerConsumerResults.clear();
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3423,12 +3698,11 @@
mIIntegerConsumerResults.clear();
clearInvocations(mMockSatelliteModemInterface);
setUpNoResponseForRequestSatelliteEnabled(false, false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false),
- eq(false),
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class),
disableSatelliteResponse.capture());
clearInvocations(mMockSatelliteModemInterface);
@@ -3436,9 +3710,10 @@
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_MODEM_TIMEOUT, (long) mIIntegerConsumerResults.get(0));
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
- verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
+ // Satellite should state at enabled state since satellite disable request failed
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
// Send the response for the above request to disable satellite. SatelliteController should
// ignore the event
@@ -3446,7 +3721,7 @@
AsyncResult.forMessage(response, null, null);
response.sendToTarget();
processAllMessages();
- verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -3462,9 +3737,9 @@
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
@@ -3472,8 +3747,7 @@
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3488,8 +3762,7 @@
// Ignore request ntn signal strength for redundant enable request
reset(mMockSatelliteModemInterface);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3502,8 +3775,7 @@
reset(mMockSatelliteModemInterface);
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3517,8 +3789,7 @@
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
mIIntegerConsumerResults.clear();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(false, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3533,8 +3804,7 @@
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3571,8 +3841,7 @@
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
- SUB_ID, callback);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(callback);
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
sendSatelliteSupportedStateChangedEvent(true, null);
@@ -3606,13 +3875,12 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
// Successfully enable satellite
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
mIIntegerConsumerResults.clear();
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3635,7 +3903,7 @@
// Verify satellite was disabled
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.unregisterForSatelliteSupportedStateChanged(SUB_ID, callback);
+ mSatelliteControllerUT.unregisterForSatelliteSupportedStateChanged(callback);
sendSatelliteSupportedStateChangedEvent(true, null);
processAllMessages();
assertFalse(waitForForEvents(
@@ -3661,7 +3929,7 @@
}
};
int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
- SUB_ID, callback);
+ callback);
assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
}
@@ -3764,17 +4032,777 @@
mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
}
+ @Test
+ public void testIsCarrierRoamingNtnEligible() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ assertFalse(mSatelliteControllerUT.isCarrierRoamingNtnEligible(null));
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+ int[] supportedServices2 = {2};
+ int[] supportedServices3 = {1, 3};
+ PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ "00102", supportedServices2);
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ "00103", supportedServices3);
+ mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ carrierSupportedSatelliteServicesPerProvider);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(true, false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ }
+
+ @Test
+ public void testOverrideCarrierRoamingNtNEligibilityChange() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(true, false);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ clearInvocations(mPhone);
+
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(false, false);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(false));
+ clearInvocations(mPhone);
+
+ mSatelliteControllerUT.overrideCarrierRoamingNtnEligibilityChanged(false, true);
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ clearInvocations(mPhone);
+ }
+
+ @Test
+ public void testNotifyNtnEligibilityHysteresisTimedOut() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+ mCarrierConfigBundle.putInt(
+ KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 1 * 60);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+ int[] supportedServices2 = {2};
+ int[] supportedServices3 = {1, 3};
+ PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ "00102", supportedServices2);
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ "00103", supportedServices3);
+ mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ carrierSupportedSatelliteServicesPerProvider);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ mSatelliteControllerUT.setSatellitePhone(1);
+ mSatelliteControllerUT.isSatelliteAllowedCallback = null;
+ processAllMessages();
+ mSatelliteControllerUT.elapsedRealtime = 0;
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
+ clearInvocations(mPhone);
+
+ // 2 minutes later and hysteresis timeout is 1 minute
+ mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ assertNotNull(mSatelliteControllerUT.isSatelliteAllowedCallback);
+
+ mSatelliteControllerUT.isSatelliteAllowedCallback.onResult(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
+ verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
+ any());
+ clearInvocations(mPhone);
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ sendServiceStateChangedEvent();
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(false));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
+
+ // isSatelliteAllowedCallback.onError() returns error
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ sendServiceStateChangedEvent();
+ processAllMessages();
+ mSatelliteControllerUT.elapsedRealtime = 0;
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
+ clearInvocations(mPhone);
+
+ // 2 minutes later and hysteresis timeout is 1 minute
+ mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ assertNotNull(mSatelliteControllerUT.isSatelliteAllowedCallback);
+
+ mSatelliteControllerUT.isSatelliteAllowedCallback.onError(new SatelliteException(
+ SATELLITE_RESULT_ERROR));
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
+ verify(mMockNotificationManager, times(2)).cancelAsUser(anyString(), anyInt(),
+ any());
+ }
+
+ @Test
+ public void testGetWwanIsInService() {
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(new ArrayList<>());
+ assertFalse(mSatelliteControllerUT.getWwanIsInService(mServiceState));
+
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertTrue(mSatelliteControllerUT.getWwanIsInService(mServiceState));
+
+ nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertTrue(mSatelliteControllerUT.getWwanIsInService(mServiceState));
+
+ nri = new NetworkRegistrationInfo.Builder().setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertFalse(mSatelliteControllerUT.getWwanIsInService(mServiceState));
+ }
+
+ @Test
+ public void testRegistrationFailureCallback() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ Semaphore semaphore = new Semaphore(0);
+ final int[] resultErrorCode = new int[1];
+ ISatelliteModemStateCallback callback = new ISatelliteModemStateCallback.Stub() {
+ @Override
+ public void onSatelliteModemStateChanged(int state) {
+ logd("onSatelliteModemStateChanged: state=" + state);
+ }
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ resultErrorCode[0] = causeCode;
+ semaphore.release();
+ }
+ };
+ resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+
+ int RegisterErrorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, RegisterErrorCode);
+ verify(mMockSatelliteSessionController).registerForSatelliteModemStateChanged(callback);
+
+ int expectedErrorCode = 100;
+ mIIntegerConsumerResults.clear();
+ sendSatelliteRegistrationFailureEvent(100, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegistrationFailureCallback"));
+ assertEquals(expectedErrorCode, resultErrorCode[0]);
+ }
+
+ @RequiresFlagsDisabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
+ @Test
+ public void testDetermineIsFoldable_overlayConfigurationValues() {
+ // isFoldable should return false with the base configuration.
+ assertFalse(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+
+ mContextFixture.putIntArrayResource(R.array.config_foldedDeviceStates, new int[2]);
+ assertTrue(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+ }
+
+ @RequiresFlagsEnabled(FLAG_DEVICE_STATE_PROPERTY_MIGRATION)
+ @Test
+ public void testDetermineIsFoldable_deviceStateManager() {
+ // isFoldable should return false with the base configuration.
+ assertFalse(mSatelliteControllerUT.isFoldable(mContext,
+ mSatelliteControllerUT.getSupportedDeviceStates()));
+
+ DeviceState foldedDeviceState = new DeviceState(new DeviceState.Configuration.Builder(
+ 0 /* identifier */, "FOLDED")
+ .setSystemProperties(Set.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY))
+ .setPhysicalProperties(
+ Set.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED))
+ .build());
+ DeviceState unfoldedDeviceState = new DeviceState(new DeviceState.Configuration.Builder(
+ 1 /* identifier */, "UNFOLDED")
+ .setSystemProperties(Set.of(PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY))
+ .setPhysicalProperties(
+ Set.of(PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN))
+ .build());
+ List<DeviceState> foldableDeviceStateList = List.of(foldedDeviceState, unfoldedDeviceState);
+ assertTrue(mSatelliteControllerUT.isFoldable(mContext, foldableDeviceStateList));
+ }
+
+ private boolean mProvisionState = false;
+ private int mProvisionSateResultCode = -1;
+ private Semaphore mProvisionSateSemaphore = new Semaphore(0);
+ private ResultReceiver mProvisionSatelliteReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mProvisionSateResultCode = resultCode;
+ logd("mProvisionSatelliteReceiver: resultCode=" + resultCode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_PROVISION_SATELLITE_TOKENS)) {
+ mProvisionState = resultData.getBoolean(KEY_PROVISION_SATELLITE_TOKENS);
+ logd("mProvisionSatelliteReceiver: mProvisionState=" + mProvisionState);
+ } else {
+ loge("KEY_PROVISION_SATELLITE_TOKENS does not exist.");
+ mProvisionState = false;
+ }
+ } else {
+ mProvisionState = false;
+ }
+ try {
+ mProvisionSateSemaphore.release();
+ } catch (Exception ex) {
+ loge("mProvisionSatelliteReceiver: Got exception in releasing semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ private List<SatelliteSubscriberProvisionStatus>
+ mRequestSatelliteSubscriberProvisionStatusResultList = new ArrayList<>();
+ private int mRequestSatelliteSubscriberProvisionStatusResultCode = SATELLITE_RESULT_SUCCESS;
+ private Semaphore mRequestSatelliteSubscriberProvisionStatusSemaphore = new Semaphore(0);
+ private ResultReceiver mRequestSatelliteSubscriberProvisionStatusReceiver = new ResultReceiver(
+ null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mRequestSatelliteSubscriberProvisionStatusResultCode = resultCode;
+ logd("mRequestSatelliteSubscriberProvisionStatusReceiver: resultCode=" + resultCode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN)) {
+ mRequestSatelliteSubscriberProvisionStatusResultList =
+ resultData.getParcelableArrayList(
+ KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN,
+ SatelliteSubscriberProvisionStatus.class);
+ } else {
+ loge("KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN does not exist.");
+ mRequestSatelliteSubscriberProvisionStatusResultList = new ArrayList<>();
+ }
+ } else {
+ mRequestSatelliteSubscriberProvisionStatusResultList = new ArrayList<>();
+ }
+ try {
+ mRequestSatelliteSubscriberProvisionStatusSemaphore.release();
+ } catch (Exception ex) {
+ loge("mRequestSatelliteSubscriberProvisionStatusReceiver: Got exception in "
+ + "releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ @Test
+ public void testRequestSatelliteSubscriberProvisionStatus() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ verifyRequestSatelliteSubscriberProvisionStatus();
+ }
+
+ private void verifyRequestSatelliteSubscriberProvisionStatus() throws Exception {
+ setSatelliteSubscriberTesting();
+ List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
+ mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ moveTimeForward(TimeUnit.MINUTES.toMillis(1));
+ processAllMessages();
+
+ // Verify that calling requestSatelliteSubscriberProvisionStatus returns the expected
+ // list of SatelliteSubscriberProvisionStatus.
+ mSatelliteControllerUT.requestSatelliteSubscriberProvisionStatus(
+ mRequestSatelliteSubscriberProvisionStatusReceiver);
+ moveTimeForward(TimeUnit.MINUTES.toMillis(1));
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS,
+ mRequestSatelliteSubscriberProvisionStatusResultCode);
+ assertEquals(list.get(0), mRequestSatelliteSubscriberProvisionStatusResultList.get(
+ 0).getSatelliteSubscriberInfo());
+ }
+
+ @Test
+ public void testProvisionSatellite() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ verifyRequestSatelliteSubscriberProvisionStatus();
+ List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
+ verifyProvisionSatellite(inputList);
+ }
+
+ private void verifyProvisionSatellite(List<SatelliteSubscriberInfo> inputList) {
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[1];
+ AsyncResult.forMessage(message, null, new SatelliteException(SATELLITE_RESULT_SUCCESS));
+ message.sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).updateSatelliteSubscription(anyString(), any());
+
+ mSatelliteControllerUT.provisionSatellite(inputList, mProvisionSatelliteReceiver);
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, mProvisionSateResultCode);
+ assertTrue(mProvisionState);
+ }
+
+ @Test
+ public void testRegisterForSatelliteSubscriptionProvisionStateChanged() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ Semaphore semaphore = new Semaphore(0);
+ SatelliteSubscriberProvisionStatus[] resultArray =
+ new SatelliteSubscriberProvisionStatus[2];
+ ISatelliteProvisionStateCallback callback = new ISatelliteProvisionStateCallback.Stub() {
+ @Override
+ public void onSatelliteProvisionStateChanged(boolean provisioned) {
+ logd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
+ }
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscriberProvisionStatus) {
+ logd("onSatelliteSubscriptionProvisionStateChanged: "
+ + satelliteSubscriberProvisionStatus);
+ for (int i = 0; i < satelliteSubscriberProvisionStatus.size(); i++) {
+ resultArray[i] = satelliteSubscriberProvisionStatus.get(i);
+ }
+ try {
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSatelliteSubscriptionProvisionStateChanged: Got exception in releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+
+ verifyRequestSatelliteSubscriberProvisionStatus();
+
+ // Verify that onSatelliteSubscriptionProvisionStateChanged is called when requesting
+ // provisioning for the first time.
+ List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
+ List<SatelliteSubscriberInfo> inputList = new ArrayList<>();
+ inputList.add(list.get(0));
+ verifyProvisionSatellite(inputList);
+
+ verify(mMockSatelliteModemInterface, times(1)).updateSatelliteSubscription(anyString(),
+ any());
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertTrue(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request provisioning with SatelliteSubscriberInfo that has not been provisioned
+ // before, and verify that onSatelliteSubscriptionProvisionStateChanged is called.
+ inputList = new ArrayList<>();
+ inputList.add(list.get(1));
+ verifyProvisionSatellite(inputList);
+
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertTrue(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request provisioning with the same SatelliteSubscriberInfo that was previously
+ // requested, and verify that onSatelliteSubscriptionProvisionStateChanged is not called.
+ verifyProvisionSatellite(inputList);
+
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+
+ // Request deprovision for subscriberID 2, verify that subscriberID 2 is set to
+ // deprovision and that subscriberID 1 is set to provision.
+ verifyDeprovisionSatellite(inputList);
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertFalse(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertTrue(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request deprovision for subscriberID 1, verify that subscriberID 1 is set to deprovision.
+ inputList = new ArrayList<>();
+ inputList.add(list.get(0));
+ verifyDeprovisionSatellite(inputList);
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertFalse(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertFalse(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+
+ // Request provision for subscriberID 2, verify that subscriberID 2 is set to provision.
+ inputList = new ArrayList<>();
+ inputList.add(list.get(1));
+ verifyProvisionSatellite(inputList);
+
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ assertTrue(resultArray[1].getProvisionStatus());
+ assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
+ assertFalse(resultArray[0].getProvisionStatus());
+ assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
+ }
+
+ private boolean mDeprovisionDone = false;
+ private int mDeprovisionSateResultCode = -1;
+ private Semaphore mDeprovisionSateSemaphore = new Semaphore(0);
+ private ResultReceiver mDeprovisionSatelliteReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mDeprovisionSateResultCode = resultCode;
+ logd("DeprovisionSatelliteReceiver: resultCode=" + resultCode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_DEPROVISION_SATELLITE_TOKENS)) {
+ mDeprovisionDone = resultData.getBoolean(KEY_DEPROVISION_SATELLITE_TOKENS);
+ logd("DeprovisionSatelliteReceiver: deprovision=" + mDeprovisionDone);
+ } else {
+ loge("KEY_DEPROVISION_SATELLITE_TOKENS does not exist.");
+ mDeprovisionDone = false;
+ }
+ } else {
+ mDeprovisionDone = false;
+ }
+ try {
+ mDeprovisionSateSemaphore.release();
+ } catch (Exception ex) {
+ loge("DeprovisionSatelliteReceiver: Got exception in releasing semaphore " + ex);
+ }
+ }
+ };
+
+ @Test
+ public void testDeprovisionSatellite() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ verifyRequestSatelliteSubscriberProvisionStatus();
+ List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
+ verifyProvisionSatellite(inputList);
+ verifyDeprovisionSatellite(inputList);
+ }
+
+ private void verifyDeprovisionSatellite(List<SatelliteSubscriberInfo> inputList) {
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[1];
+ AsyncResult.forMessage(message, null, new SatelliteException(SATELLITE_RESULT_SUCCESS));
+ message.sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).updateSatelliteSubscription(anyString(), any());
+
+ mSatelliteControllerUT.deprovisionSatellite(inputList, mDeprovisionSatelliteReceiver);
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, mDeprovisionSateResultCode);
+ assertTrue(mDeprovisionDone);
+ }
+
+ private void setSatelliteSubscriberTesting() throws Exception {
+ doReturn("123").when(mContext).getAttributionTag();
+ final int carrierId = 0;
+ SubscriptionInfo subscriptionInfo = new SubscriptionInfo.Builder()
+ .setId(SUB_ID).setIccId(mIccId).setSimSlotIndex(0).setOnlyNonTerrestrialNetwork(
+ false).setSatelliteESOSSupported(true).setCarrierId(carrierId).build();
+ SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo.Builder()
+ .setId(SUB_ID1).setIccId(mIccId2).setSimSlotIndex(1).setOnlyNonTerrestrialNetwork(
+ true).setSatelliteESOSSupported(false).setCarrierId(carrierId).build();
+ List<SubscriptionInfo> allSubInfos = new ArrayList<>();
+ allSubInfos.add(subscriptionInfo);
+ allSubInfos.add(subscriptionInfo2);
+ doReturn(allSubInfos).when(mMockSubscriptionManagerService).getAllSubInfoList(
+ anyString(), anyString());
+ SubscriptionInfoInternal subInfoInternal =
+ new SubscriptionInfoInternal.Builder().setCarrierId(0).setImsi(mImsi).setIccId(
+ mIccId).build();
+ SubscriptionInfoInternal subInfoInternal2 =
+ new SubscriptionInfoInternal.Builder().setCarrierId(0).setImsi(mImsi2).setIccId(
+ mIccId2).build();
+ doReturn(subscriptionInfo).when(mMockSubscriptionManagerService).getSubscriptionInfo(
+ eq(SUB_ID));
+ doReturn(subscriptionInfo2).when(mMockSubscriptionManagerService).getSubscriptionInfo(
+ eq(SUB_ID1));
+ Field field = SatelliteController.class.getDeclaredField("mInjectSubscriptionManager");
+ field.setAccessible(true);
+ field.set(mSatelliteControllerUT, mSubscriptionManager);
+ doReturn(mMsisdn).when(mSubscriptionManager).getPhoneNumber(eq(SUB_ID));
+ doReturn(mMsisdn2).when(mSubscriptionManager).getPhoneNumber(eq(SUB_ID1));
+ Field provisionedSubscriberIdField = SatelliteController.class.getDeclaredField(
+ "mProvisionedSubscriberId");
+ provisionedSubscriberIdField.setAccessible(true);
+ provisionedSubscriberIdField.set(mSatelliteControllerUT, new HashMap<>());
+ Field subscriberIdPerSubField = SatelliteController.class.getDeclaredField(
+ "mSubscriberIdPerSub");
+ subscriberIdPerSubField.setAccessible(true);
+ subscriberIdPerSubField.set(mSatelliteControllerUT, new HashMap<>());
+ Field lastConfiguredIccIdField = SatelliteController.class.getDeclaredField(
+ "mLastConfiguredIccId");
+ lastConfiguredIccIdField.setAccessible(true);
+ lastConfiguredIccIdField.set(mSatelliteControllerUT, null);
+ doReturn(subInfoInternal).when(mMockSubscriptionManagerService).getSubscriptionInfoInternal(
+ eq(SUB_ID));
+ doReturn(subInfoInternal2).when(
+ mMockSubscriptionManagerService).getSubscriptionInfoInternal(eq(SUB_ID1));
+ doReturn(mResources).when(mContext).getResources();
+ doReturn("package").when(mResources).getString(
+ eq(R.string.config_satellite_gateway_service_package));
+ doReturn("className").when(mResources).getString(
+ eq(R.string.config_satellite_carrier_roaming_esos_provisioned_class));
+ }
+
+ private List<SatelliteSubscriberInfo> getExpectedSatelliteSubscriberInfoList() {
+ List<SatelliteSubscriberInfo> list = new ArrayList<>();
+ list.add(new SatelliteSubscriberInfo.Builder().setSubscriberId(mSubscriberId).setCarrierId(
+ mCarrierId).setNiddApn(mNiddApn).setSubId(SUB_ID).setSubscriberIdType(
+ SatelliteSubscriberInfo.IMSI_MSISDN).build());
+ list.add(new SatelliteSubscriberInfo.Builder().setSubscriberId(mSubscriberId2).setCarrierId(
+ mCarrierId).setNiddApn(mNiddApn).setSubId(SUB_ID1).setSubscriberIdType(
+ SatelliteSubscriberInfo.ICCID).build());
+ return list;
+ }
+
+ @Test
+ public void testCheckForSubscriberIdChange_noChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ String imsi = "012345";
+ String oldMsisdn = "1234567890";
+ String newMsisdn = "1234567890";
+ List<SubscriptionInfo> allSubInfos = new ArrayList<>();
+ Optional<String> getSubscriberId;
+ SubscriptionInfoInternal subInfoInternal =
+ new SubscriptionInfoInternal.Builder().setCarrierId(0)
+ .setImsi(imsi).build();
+
+ when(mSubscriptionInfo.getSubscriptionId()).thenReturn(SUB_ID);
+ allSubInfos.add(mSubscriptionInfo);
+ doReturn(" ").when(mContext).getOpPackageName();
+ doReturn(" ").when(mContext).getAttributionTag();
+ when(mMockSubscriptionManagerService.getAllSubInfoList(anyString(), anyString()))
+ .thenReturn(allSubInfos);
+ when(mSubscriptionInfo.isSatelliteESOSSupported()).thenReturn(true);
+ when(mMockSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID))
+ .thenReturn(subInfoInternal);
+
+ try {
+ Field field = SatelliteController.class.getDeclaredField("mInjectSubscriptionManager");
+ field.setAccessible(true);
+ field.set(mSatelliteControllerUT, mSubscriptionManager);
+ } catch (Exception e) {
+ loge("Exception InjectSubscriptionManager e: " + e);
+ }
+ when(mSubscriptionManager.getPhoneNumber(SUB_ID)).thenReturn(newMsisdn);
+ when(mSubscriptionInfo.isOnlyNonTerrestrialNetwork()).thenReturn(false);
+ mSatelliteControllerUT.subscriberIdPerSub().put(imsi + oldMsisdn, SUB_ID);
+
+ getSubscriberId = mSatelliteControllerUT.subscriberIdPerSub().entrySet().stream()
+ .filter(entry -> entry.getValue().equals(SUB_ID))
+ .map(Map.Entry::getKey).findFirst();
+ assertEquals(imsi + newMsisdn, getSubscriberId.get());
+
+ setComponentName();
+ mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+ getKeyPriority(mSubscriptionInfo), k -> new ArrayList<>())
+ .add(mSubscriptionInfo);
+ mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
+ // Verify that broadcast has not been sent.
+ verify(mContext, times(0)).sendBroadcast(any(Intent.class));
+ }
+
+ @Test
+ public void testCheckForSubscriberIdChange_changed() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ List<SubscriptionInfo> allSubInfos = new ArrayList<>();
+
+ String imsi = "012345";
+ String oldMsisdn = "1234567890";
+ String newMsisdn = "4567891234";
+
+ Optional<String> getSubscriberId;
+ SubscriptionInfoInternal subInfoInternal =
+ new SubscriptionInfoInternal.Builder().setCarrierId(0).setImsi(imsi).build();
+
+ when(mSubscriptionInfo.getSubscriptionId()).thenReturn(SUB_ID);
+ allSubInfos.add(mSubscriptionInfo);
+ doReturn(" ").when(mContext).getOpPackageName();
+ doReturn(" ").when(mContext).getAttributionTag();
+ when(mMockSubscriptionManagerService.getAllSubInfoList(anyString(), anyString()))
+ .thenReturn(allSubInfos);
+
+ when(mSubscriptionInfo.isSatelliteESOSSupported()).thenReturn(true);
+ when(mMockSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID))
+ .thenReturn(subInfoInternal);
+
+ try {
+ Field field = SatelliteController.class.getDeclaredField("mInjectSubscriptionManager");
+ field.setAccessible(true);
+ field.set(mSatelliteControllerUT, mSubscriptionManager);
+ } catch (Exception e) {
+ loge("Exception InjectSubscriptionManager e: " + e);
+ }
+ when(mSubscriptionManager.getPhoneNumber(SUB_ID)).thenReturn(newMsisdn);
+ when(mSubscriptionInfo.isOnlyNonTerrestrialNetwork()).thenReturn(false);
+ mSatelliteControllerUT.subscriberIdPerSub().put(imsi + oldMsisdn, SUB_ID);
+
+ getSubscriberId = mSatelliteControllerUT.subscriberIdPerSub().entrySet().stream()
+ .filter(entry -> entry.getValue().equals(SUB_ID))
+ .map(Map.Entry::getKey).findFirst();
+ assertNotEquals(imsi + newMsisdn, getSubscriberId.get());
+
+ setComponentName();
+ mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+ getKeyPriority(mSubscriptionInfo), k -> new ArrayList<>())
+ .add(mSubscriptionInfo);
+ mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
+ // Verify that broadcast has been sent.
+ verify(mContext, times(1)).sendBroadcast(any(Intent.class));
+ }
+
+ @Test
+ public void testProvisionStatusPerSubscriberIdGetFromDb() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ setSatelliteSubscriberTesting();
+ // Check if the cache is not updated when the value read from the database is false.
+ verifyProvisionStatusPerSubscriberIdGetFromDb(false);
+
+ // Check if the cache is updated when the value read from the database is true.
+ verifyProvisionStatusPerSubscriberIdGetFromDb(true);
+ }
+
+ @Test
+ public void testProvisionStatusPerSubscriberIdStoreToDb() throws Exception {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ setSatelliteSubscriberTesting();
+ // Check if the cache is not updated when the value read from the database is false.
+ verifyProvisionStatusPerSubscriberIdGetFromDb(false);
+
+ List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
+ verifyProvisionSatellite(inputList);
+ verify(mMockSubscriptionManagerService).setIsSatelliteProvisionedForNonIpDatagram(
+ eq(SUB_ID), eq(true));
+ }
+
+ private void verifyProvisionStatusPerSubscriberIdGetFromDb(boolean provision) {
+ doReturn(provision).when(
+ mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
+ mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ moveTimeForward(TimeUnit.MINUTES.toMillis(1));
+ processAllMessages();
+ mSatelliteControllerUT.requestSatelliteSubscriberProvisionStatus(
+ mRequestSatelliteSubscriberProvisionStatusReceiver);
+ moveTimeForward(TimeUnit.MINUTES.toMillis(1));
+ processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS,
+ mRequestSatelliteSubscriberProvisionStatusResultCode);
+ assertEquals(provision,
+ mRequestSatelliteSubscriberProvisionStatusResultList.get(0).getProvisionStatus());
+ }
+
+ private void setComponentName() {
+ when(mSatelliteControllerUT.getStringFromOverlayConfigTest(
+ R.string.config_satellite_gateway_service_package))
+ .thenReturn("com.example.package");
+ when(mSatelliteControllerUT.getStringFromOverlayConfigTest(
+ R.string.config_satellite_carrier_roaming_esos_provisioned_class))
+ .thenReturn("com.example.class");
+ }
+
+ private int getKeyPriority(SubscriptionInfo subscriptionInfo) {
+ boolean isActive = subscriptionInfo.isActive();
+ boolean isNtnOnly = subscriptionInfo.isOnlyNonTerrestrialNetwork();
+ boolean isESOSSupported = subscriptionInfo.isSatelliteESOSSupported();
+
+ int keyPriority;
+ if (isESOSSupported && isActive) {
+ keyPriority = 1;
+ } else if (isNtnOnly) {
+ keyPriority = 2;
+ } else if (isESOSSupported) {
+ keyPriority = 3;
+ } else {
+ keyPriority = -1;
+ }
+ return keyPriority;
+ }
+
private void resetSatelliteControllerUTEnabledState() {
logd("resetSatelliteControllerUTEnabledState");
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
doNothing().when(mMockSatelliteModemInterface)
.setSatelliteServicePackageName(anyString());
- mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService");
+ mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService", null);
processAllMessages();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(false);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@@ -3789,7 +4817,7 @@
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
doNothing().when(mMockSatelliteModemInterface)
.setSatelliteServicePackageName(anyString());
- mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService");
+ mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService", null);
processAllMessages();
}
@@ -3797,7 +4825,7 @@
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@@ -3806,6 +4834,8 @@
resetSatelliteControllerUTToSupportedAndProvisionedState();
// Clean up pending resources and move satellite controller to OFF state.
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_UNAVAILABLE, null);
+ mSatelliteControllerUT.moveSatelliteToOffStateAndCleanUpResources(
+ SATELLITE_RESULT_REQUEST_ABORTED);
processAllMessages();
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
}
@@ -3815,9 +4845,9 @@
setRadioPower(true);
processAllMessages();
+ mIIntegerConsumerResults.clear();
setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
- mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3878,15 +4908,7 @@
private void setUpResponseForRequestIsSatelliteProvisioned(
boolean isSatelliteProvisioned, @SatelliteManager.SatelliteResult int error) {
- SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
- ? null : new SatelliteException(error);
- int[] provisioned = new int[]{isSatelliteProvisioned ? 1 : 0};
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[0];
- AsyncResult.forMessage(message, provisioned, exception);
- message.sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface).requestIsSatelliteProvisioned(any(Message.class));
+ mSatelliteControllerUT.setSatelliteProvisioned(isSatelliteProvisioned);
}
private void setUpResponseForRequestSatelliteEnabled(
@@ -3898,12 +4920,12 @@
if (exception == null && !enabled) {
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_OFF, null);
}
- Message message = (Message) invocation.getArguments()[3];
+ Message message = (Message) invocation.getArguments()[1];
AsyncResult.forMessage(message, null, exception);
message.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface)
- .requestSatelliteEnabled(eq(enabled), eq(demoMode), eq(emergency),
+ .requestSatelliteEnabled(any(SatelliteModemEnableRequestAttributes.class),
any(Message.class));
}
@@ -3923,41 +4945,13 @@
private void setUpNoResponseForRequestSatelliteEnabled(boolean enabled, boolean demoMode,
boolean emergency) {
doNothing().when(mMockSatelliteModemInterface)
- .requestSatelliteEnabled(eq(enabled), eq(demoMode), eq(emergency),
+ .requestSatelliteEnabled(eq(new SatelliteModemEnableRequestAttributes(
+ enabled, demoMode, emergency,
+ new SatelliteSubscriptionInfo("", "")
+ )),
any(Message.class));
}
- private void setUpResponseForProvisionSatelliteService(
- String token, byte[] provisionData, @SatelliteManager.SatelliteResult int error) {
- SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
- ? null : new SatelliteException(error);
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[2];
- AsyncResult.forMessage(message, null, exception);
- message.sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface)
- .provisionSatelliteService(eq(token), any(byte[].class), any(Message.class));
- }
-
- private void setUpNoResponseForProvisionSatelliteService(String token) {
- doNothing().when(mMockSatelliteModemInterface)
- .provisionSatelliteService(eq(token), any(), any(Message.class));
- }
-
- private void setUpResponseForDeprovisionSatelliteService(String token,
- @SatelliteManager.SatelliteResult int error) {
- SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
- ? null : new SatelliteException(error);
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[1];
- AsyncResult.forMessage(message, null, exception);
- message.sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface)
- .deprovisionSatelliteService(eq(token), any(Message.class));
- }
-
private void setUpResponseForRequestSatelliteCapabilities(
SatelliteCapabilities satelliteCapabilities,
@SatelliteManager.SatelliteResult int error) {
@@ -4186,7 +5180,7 @@
private void verifySatelliteSupported(boolean supported, int expectedErrorCode) {
mSatelliteSupportSemaphore.drainPermits();
- mSatelliteControllerUT.requestIsSatelliteSupported(SUB_ID, mSatelliteSupportReceiver);
+ mSatelliteControllerUT.requestIsSatelliteSupported(mSatelliteSupportReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteSupportedResult(1));
assertEquals(expectedErrorCode, mQueriedSatelliteSupportedResultCode);
@@ -4196,7 +5190,7 @@
private void verifySatelliteSupported(TestSatelliteController satelliteController,
boolean supported, int expectedErrorCode) {
mSatelliteSupportSemaphore.drainPermits();
- satelliteController.requestIsSatelliteSupported(SUB_ID, mSatelliteSupportReceiver);
+ satelliteController.requestIsSatelliteSupported(mSatelliteSupportReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteSupportedResult(1));
assertEquals(expectedErrorCode, mQueriedSatelliteSupportedResultCode);
@@ -4205,7 +5199,7 @@
private void verifySatelliteEnabled(boolean enabled, int expectedErrorCode) {
mIsSatelliteEnabledSemaphore.drainPermits();
- mSatelliteControllerUT.requestIsSatelliteEnabled(SUB_ID, mIsSatelliteEnabledReceiver);
+ mSatelliteControllerUT.requestIsSatelliteEnabled(mIsSatelliteEnabledReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteEnabledResult(1));
assertEquals(expectedErrorCode, mQueriedIsSatelliteEnabledResultCode);
@@ -4214,8 +5208,7 @@
private void verifySatelliteProvisioned(boolean provisioned, int expectedErrorCode) {
mIsSatelliteProvisionedSemaphore.drainPermits();
- mSatelliteControllerUT.requestIsSatelliteProvisioned(
- SUB_ID, mIsSatelliteProvisionedReceiver);
+ mSatelliteControllerUT.requestIsSatelliteProvisioned(mIsSatelliteProvisionedReceiver);
processAllMessages();
assertTrue(waitForRequestIsSatelliteProvisionedResult(1));
assertEquals(expectedErrorCode, mQueriedIsSatelliteProvisionedResultCode);
@@ -4226,18 +5219,15 @@
@NtnSignalStrength.NtnSignalStrengthLevel int signalStrengthLevel,
int expectedErrorCode) {
mRequestNtnSignalStrengthSemaphore.drainPermits();
- mSatelliteControllerUT.requestNtnSignalStrength(SUB_ID, mRequestNtnSignalStrengthReceiver);
+ mSatelliteControllerUT.requestNtnSignalStrength(mRequestNtnSignalStrengthReceiver);
processAllMessages();
assertTrue(waitForRequestNtnSignalStrengthResult(1));
assertEquals(expectedErrorCode, mQueriedNtnSignalStrengthResultCode);
assertEquals(signalStrengthLevel, mQueriedNtnSignalStrengthLevel);
}
- private void sendProvisionedStateChangedEvent(boolean provisioned, Throwable exception) {
- Message msg = mSatelliteControllerUT.obtainMessage(
- 26 /* EVENT_SATELLITE_PROVISION_STATE_CHANGED */);
- msg.obj = new AsyncResult(null, provisioned, exception);
- msg.sendToTarget();
+ private void setProvisionedState(@Nullable Boolean provisioned) {
+ mSatelliteControllerUT.setSatelliteProvisioned(provisioned);
}
private void sendSatelliteModemStateChangedEvent(int state, Throwable exception) {
@@ -4293,6 +5283,13 @@
msg.sendToTarget();
}
+ private void sendSatelliteRegistrationFailureEvent(int errorCode, Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 54 /* EVENT_SATELLITE_REGISTRATION_FAILURE */);
+ msg.obj = new AsyncResult(null, errorCode, exception);
+ msg.sendToTarget();
+ }
+
private void setRadioPower(boolean on) {
mSimulatedCommands.setRadioPower(on, false, false, null);
}
@@ -4301,14 +5298,13 @@
INtnSignalStrengthCallback callback, int expectedError) {
if (expectedError == SATELLITE_RESULT_SUCCESS) {
try {
- mSatelliteControllerUT.registerForNtnSignalStrengthChanged(subId, callback);
+ mSatelliteControllerUT.registerForNtnSignalStrengthChanged(callback);
} catch (RemoteException ex) {
throw new AssertionError();
}
} else {
RemoteException ex = assertThrows(RemoteException.class,
- () -> mSatelliteControllerUT.registerForNtnSignalStrengthChanged(subId,
- callback));
+ () -> mSatelliteControllerUT.registerForNtnSignalStrengthChanged(callback));
assertTrue("The cause is not IllegalStateException",
ex.getCause() instanceof IllegalStateException);
}
@@ -4323,9 +5319,7 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- setUpResponseForProvisionSatelliteService(TEST_SATELLITE_TOKEN, testProvisionData,
- SATELLITE_RESULT_SUCCESS);
- cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
processAllMessages();
@@ -4337,8 +5331,7 @@
private void deprovisionSatelliteService() {
mIIntegerConsumerResults.clear();
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
+ mSatelliteControllerUT.deprovisionSatelliteService(
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -4490,12 +5483,13 @@
}
}
- private static class TestSatelliteController extends SatelliteController {
+ private class TestSatelliteController extends SatelliteController {
public boolean setSettingsKeyForSatelliteModeCalled = false;
public boolean allRadiosDisabled = true;
public long elapsedRealtime = 0;
public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
+ public OutcomeReceiver<Boolean, SatelliteException> isSatelliteAllowedCallback = null;
TestSatelliteController(
Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
@@ -4523,6 +5517,7 @@
@Override
protected boolean areAllRadiosDisabled() {
+ logd("areAllRadiosDisabled: " + allRadiosDisabled);
return allRadiosDisabled;
}
@@ -4541,5 +5536,83 @@
void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
mSatelliteSessionController = satelliteSessionController;
}
+
+ @Override
+ protected void setSatellitePhone(int subId) {
+ logd("setSatellitePhone");
+ synchronized (mSatellitePhoneLock) {
+ mSatellitePhone = mPhone;
+ }
+ }
+
+ @Override
+ protected void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ @NonNull OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> callback) {
+ logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: callback="
+ + callback);
+ isSatelliteAllowedCallback = callback;
+ }
+
+ @Override
+ protected boolean isSubscriptionProvisioned(int subId) {
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone.getSubId() == subId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+
+ void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
+ synchronized (mSatelliteViaOemProvisionLock) {
+ mIsSatelliteViaOemProvisioned = isProvisioned;
+ }
+ }
+
+ public boolean isRadioOn() {
+ synchronized (mIsRadioOnLock) {
+ return mIsRadioOn;
+ }
+ }
+
+ public boolean isRadioOffRequested() {
+ synchronized (mIsRadioOnLock) {
+ return mRadioOffRequested;
+ }
+ }
+
+ public boolean isWaitForCellularModemOffTimerStarted() {
+ return hasMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT);
+ }
+
+ public Map<String, Integer> subscriberIdPerSub() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSubscriberIdPerSub;
+ }
+ }
+
+ public Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return mSubsInfoListPerPriority;
+ }
+ }
+
+ public void evaluateESOSProfilesPrioritizationTest() {
+ evaluateESOSProfilesPrioritization();
+ }
+
+ public String getStringFromOverlayConfigTest(int resourceId) {
+ return getStringFromOverlayConfig(resourceId);
+ }
+
+ public boolean isAnyWaitForSatelliteEnablingResponseTimerStarted() {
+ return hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT);
+ }
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
index f4fa48e..f15ffbd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -29,6 +29,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -39,11 +42,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.hardware.devicestate.DeviceState;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telecom.Connection;
import android.telecom.TelecomManager;
import android.telephony.BinderCacheManager;
@@ -65,9 +70,12 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.metrics.SatelliteStats;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -92,6 +100,7 @@
private static final int TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS = 500;
private static final int PHONE_ID = 0;
private static final int PHONE_ID2 = 1;
+ private static final int SUB_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
private static final String CALL_ID = "CALL_ID";
private static final String WRONG_CALL_ID = "WRONG_CALL_ID";
private static final String DEFAULT_SATELLITE_MESSAGING_PACKAGE = "android.com.google.default";
@@ -108,10 +117,14 @@
private ImsManager.MmTelFeatureConnectionFactory mMmTelFeatureConnectionFactory;
@Mock
private FeatureFlags mFeatureFlags;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private TestConnection mTestConnection;
private Uri mTestConnectionAddress = Uri.parse("tel:1234");
private TestSOSMessageRecommender mTestSOSMessageRecommender;
private ServiceState mServiceState2;
+ @Mock
+ private SatelliteStats mMockSatelliteStats;
@Before
public void setUp() throws Exception {
@@ -127,6 +140,7 @@
R.integer.config_emergency_call_wait_for_connection_timeout_millis))
.thenReturn(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mTestSatelliteController = new TestSatelliteController(mContext,
Looper.myLooper(), mFeatureFlags);
mTestImsManager = new TestImsManager(
@@ -146,6 +160,10 @@
when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mPhone.isImsRegistered()).thenReturn(false);
when(mPhone2.isImsRegistered()).thenReturn(false);
+ replaceInstance(SatelliteStats.class, "sInstance", null,
+ mMockSatelliteStats);
+ doNothing().when(mMockSatelliteStats).onSatelliteSosMessageRecommender(
+ any(SatelliteStats.SatelliteSosMessageRecommenderParams.class));
}
@After
@@ -158,6 +176,8 @@
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
DEFAULT_T911_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -170,6 +190,8 @@
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
"android.com.vendor.message", "android.com.vendor.message.SmsApp",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -181,6 +203,8 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -190,6 +214,8 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
DEFAULT_HANDOVER_INTENT_ACTION);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -197,16 +223,17 @@
when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(null);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(null, false);
processAllMessages();
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
}
private void testTimeoutBeforeEmergencyCallEnd(int expectedHandoverType,
String expectedPackageName, String expectedClassName, String expectedAction) {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -232,6 +259,8 @@
}
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -239,7 +268,7 @@
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.setIsSatelliteViaOemProvisioned(false);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -259,6 +288,8 @@
assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
@@ -266,7 +297,7 @@
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.isOemEnabledSatelliteSupported = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
@@ -295,17 +326,21 @@
@Test
public void testStopTrackingCallBeforeTimeout_ConnectionActive() {
testStopTrackingCallBeforeTimeout(Connection.STATE_ACTIVE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testStopTrackingCallBeforeTimeout_ConnectionDisconnected() {
testStopTrackingCallBeforeTimeout(Connection.STATE_DISCONNECTED);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testNetworkStateChangedBeforeTimeout() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -330,11 +365,13 @@
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testSatelliteProvisionStateChangedBeforeTimeout() {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -350,8 +387,11 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
+ reset(mMockSatelliteStats);
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -380,12 +420,14 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 2);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 2, 2);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testEmergencyCallRedialBeforeTimeout() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -393,7 +435,7 @@
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -419,35 +461,45 @@
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_InServiceToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_IN_SERVICE, STATE_OUT_OF_SERVICE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_InServiceToPowerOff() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_IN_SERVICE, ServiceState.STATE_POWER_OFF);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_EMERGENCY_ONLY, STATE_OUT_OF_SERVICE);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToPowerOff() {
testCellularServiceStateChangedBeforeTimeout(
ServiceState.STATE_EMERGENCY_ONLY, ServiceState.STATE_POWER_OFF);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertTrue(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testOnEmergencyCallConnectionStateChangedWithWrongCallId() {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -464,12 +516,15 @@
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testSatelliteNotAllowedInCurrentLocation() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -491,21 +546,25 @@
assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+ verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+ assertFalse(mTestSOSMessageRecommender.isDialerNotified());
}
@Test
public void testOnEmergencyCallStarted() {
- SatelliteController satelliteController = new SatelliteController(
- mContext, Looper.myLooper(), mFeatureFlags);
+ SatelliteController satelliteController = new MinimalSatelliteControllerWrapper(mContext,
+ Looper.myLooper(), mFeatureFlags);
TestSOSMessageRecommender testSOSMessageRecommender = new TestSOSMessageRecommender(
mContext,
Looper.myLooper(),
satelliteController, mTestImsManager);
- testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertFalse(testSOSMessageRecommender.isTimerStarted());
assertEquals(0, testSOSMessageRecommender.getCountOfTimerStarted());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
}
@Test
@@ -531,30 +590,94 @@
// Both OEM and carrier don't support satellite
mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
mTestSatelliteController.isOemEnabledSatelliteSupported = false;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(0, mTestSOSMessageRecommender.getTimeOutMillis());
// Only OEM support satellite
mTestSatelliteController.isOemEnabledSatelliteSupported = true;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
- // Both OEM and carrier support satellite. Thus, carrier's timeout duration will be used
+ // Both OEM and carrier support satellite, but device is not connected to carrier satellite
+ // within hysteresis time. Thus, OEM timer will be used.
long carrierTimeoutMillis = 1000;
mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = true;
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
carrierTimeoutMillis;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+ processAllMessages();
+ assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+ mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+ // Both OEM and carrier support satellite, and device is connected to carrier satellite
+ // within hysteresis time. Thus, carrier timer will be used.
+ mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = true;
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
+ carrierTimeoutMillis;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+ }
+
+ @Test
+ public void testGetEmergencyCallToSatelliteHandoverType_SatelliteViaCarrierAndOemAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+ }
+
+ @Test
+ public void testGetEmergencyCallToSatelliteHandoverType_OnlySatelliteViaCarrierAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+ }
+
+ @Test
+ public void testGetEmergencyCallToSatelliteHandoverType_OemAndCarrierNotAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+ verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
}
private void testStopTrackingCallBeforeTimeout(
@Connection.ConnectionState int connectionState) {
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -576,7 +699,7 @@
@ServiceState.RegState int availableServiceState,
@ServiceState.RegState int unavailableServiceState) {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
- mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -685,21 +808,21 @@
@Override
@SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
- int subId, @NonNull ISatelliteProvisionStateCallback callback) {
+ @NonNull ISatelliteProvisionStateCallback callback) {
mRegisterForSatelliteProvisionStateChangedCalls++;
Set<ISatelliteProvisionStateCallback> perSubscriptionCallbacks =
- mProvisionStateChangedCallbacks.getOrDefault(subId, new HashSet<>());
+ mProvisionStateChangedCallbacks.getOrDefault(SUB_ID, new HashSet<>());
perSubscriptionCallbacks.add(callback);
- mProvisionStateChangedCallbacks.put(subId, perSubscriptionCallbacks);
+ mProvisionStateChangedCallbacks.put(SUB_ID, perSubscriptionCallbacks);
return SatelliteManager.SATELLITE_RESULT_SUCCESS;
}
@Override
public void unregisterForSatelliteProvisionStateChanged(
- int subId, @NonNull ISatelliteProvisionStateCallback callback) {
+ @NonNull ISatelliteProvisionStateCallback callback) {
mUnregisterForSatelliteProvisionStateChangedCalls++;
Set<ISatelliteProvisionStateCallback> perSubscriptionCallbacks =
- mProvisionStateChangedCallbacks.get(subId);
+ mProvisionStateChangedCallbacks.get(SUB_ID);
if (perSubscriptionCallbacks != null) {
perSubscriptionCallbacks.remove(callback);
}
@@ -725,6 +848,12 @@
return carrierEmergencyCallWaitForConnectionTimeoutMillis;
}
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+
public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
boolean connectedViaCarrier) {
mIsSatelliteConnectedViaCarrierWithinHysteresisTime = connectedViaCarrier;
@@ -745,7 +874,7 @@
public void sendProvisionStateChangedEvent(int subId, boolean provisioned) {
mIsSatelliteViaOemProvisioned = provisioned;
Set<ISatelliteProvisionStateCallback> perSubscriptionCallbacks =
- mProvisionStateChangedCallbacks.get(subId);
+ mProvisionStateChangedCallbacks.get(SUB_ID);
if (perSubscriptionCallbacks != null) {
for (ISatelliteProvisionStateCallback callback : perSubscriptionCallbacks) {
try {
@@ -758,6 +887,26 @@
}
}
+ /**
+ * Now that {@link SatelliteController} uses
+ * {@link android.hardware.devicestate.DeviceStateManager} to determine if a device is a
+ * foldable or not, we have to provide a minimal wrapper for {@link SatelliteController} for
+ * tests that want to use a non-fake {@link SatelliteController}.
+ */
+ private static class MinimalSatelliteControllerWrapper extends SatelliteController {
+
+ protected MinimalSatelliteControllerWrapper(
+ Context context, Looper looper, FeatureFlags featureFlags) {
+ super(context, looper, featureFlags);
+ }
+
+ @Override
+ protected List<DeviceState> getSupportedDeviceStates() {
+ return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
+ "DEFAULT" /* name */).build()));
+ }
+ }
+
private static class TestImsManager extends ImsManager {
private final List<RegistrationManager.RegistrationCallback> mCallbacks;
@@ -831,6 +980,7 @@
isSatelliteAllowedCallback = null;
private ComponentName mSmsAppComponent = new ComponentName(
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS);
+ private boolean mIsDialerNotified;
/**
* Create an instance of SatelliteSOSMessageRecommender.
@@ -859,6 +1009,12 @@
isSatelliteAllowedCallback = callback;
}
+ @Override
+ protected void reportESosRecommenderDecision(boolean isDialerNotified) {
+ super.reportESosRecommenderDecision(isDialerNotified);
+ mIsDialerNotified = isDialerNotified;
+ }
+
public boolean isTimerStarted() {
return hasMessages(EVENT_TIME_OUT);
}
@@ -874,6 +1030,10 @@
public long getTimeOutMillis() {
return mTimeoutMillis;
}
+
+ public boolean isDialerNotified() {
+ return mIsDialerNotified;
+ }
}
private static class TestConnection extends Connection {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
index 0e4adcd..7bf8ab4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
@@ -19,19 +19,28 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -41,12 +50,23 @@
@TestableLooper.RunWithLooper
public class SatelliteServiceUtilsTest extends TelephonyTest {
private static final String TAG = "SatelliteServiceUtilsTest";
+ private static final int SUB_ID = 0;
+ private static final int SUB_ID1 = 1;
+ @Mock private ServiceState mServiceState2;
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
logd(TAG + " Setup!");
+
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mPhone2});
+ when(mPhone.getServiceState()).thenReturn(mServiceState);
+ when(mPhone.getSubId()).thenReturn(SUB_ID);
+ when(mPhone.getPhoneId()).thenReturn(0);
+ when(mPhone2.getServiceState()).thenReturn(mServiceState2);
+ when(mPhone2.getSubId()).thenReturn(SUB_ID1);
+ when(mPhone2.getPhoneId()).thenReturn(1);
}
@After
@@ -119,4 +139,89 @@
mergedList = SatelliteServiceUtils.mergeStrLists(l1, l2, l3);
assertEquals(expectedMergedList, mergedList);
}
+
+ @Test
+ public void testIsCellularAvailable() {
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ assertFalse(SatelliteServiceUtils.isCellularAvailable());
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
+ assertTrue(SatelliteServiceUtils.isCellularAvailable());
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
+ assertTrue(SatelliteServiceUtils.isCellularAvailable());
+
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.isEmergencyOnly()).thenReturn(true);
+ assertTrue(SatelliteServiceUtils.isCellularAvailable());
+ }
+
+ @Test
+ public void testIsSatellitePlmn() {
+ int subId = 1;
+
+ when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId)))
+ .thenReturn(new ArrayList<>());
+ assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+
+ // registered PLMN is null
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegisteredPlmn(null)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+
+ // cell identity is null
+ when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId))).thenReturn(
+ List.of("120260"));
+ nri = new NetworkRegistrationInfo.Builder()
+ .setRegisteredPlmn("123456")
+ .setCellIdentity(null)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+
+ // mcc and mnc are null
+ when(mCellIdentity.getMccString()).thenReturn(null);
+ when(mCellIdentity.getMncString()).thenReturn(null);
+ nri = new NetworkRegistrationInfo.Builder()
+ .setRegisteredPlmn("123456")
+ .setCellIdentity(mCellIdentity)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+
+ // mccmnc equal to satellite PLMN
+ when(mCellIdentity.getMccString()).thenReturn("120");
+ when(mCellIdentity.getMncString()).thenReturn("260");
+ nri = new NetworkRegistrationInfo.Builder()
+ .setRegisteredPlmn("123456")
+ .setCellIdentity(mCellIdentity)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertTrue(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+
+ // registered PLMN equal to satellite PLMN
+ when(mCellIdentity.getMccString()).thenReturn("123");
+ when(mCellIdentity.getMncString()).thenReturn("456");
+ nri = new NetworkRegistrationInfo.Builder()
+ .setRegisteredPlmn("120260")
+ .setCellIdentity(mCellIdentity)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+ eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(List.of(nri));
+ assertTrue(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index 78763d1..d8daa76 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -16,20 +16,35 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -37,20 +52,28 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
+import android.os.AsyncResult;
+import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -58,6 +81,7 @@
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -79,7 +103,9 @@
private static final String STATE_LISTENING = "ListeningState";
private static final String STATE_NOT_CONNECTED = "NotConnectedState";
private static final String STATE_CONNECTED = "ConnectedState";
-
+ private static final int SCREEN_OFF_INACTIVITY_TIMEOUT_SEC = 30;
+ private static final int P2P_SMS_INACTIVITY_TIMEOUT_SEC = 180;
+ private static final int ESOS_INACTIVITY_TIMEOUT_SEC = 600;
private TestSatelliteModemInterface mSatelliteModemInterface;
private TestSatelliteSessionController mTestSatelliteSessionController;
private TestSatelliteModemStateCallback mTestSatelliteModemStateCallback;
@@ -88,6 +114,11 @@
@Mock private DatagramReceiver mMockDatagramReceiver;
@Mock private DatagramDispatcher mMockDatagramDispatcher;
@Mock private DatagramController mMockDatagramController;
+ @Mock private ServiceState mMockServiceState;
+ @Mock private SessionMetricsStats mMockSessionMetricsStats;
+
+ @Captor ArgumentCaptor<Handler> mHandlerCaptor;
+ @Captor ArgumentCaptor<Integer> mMsgCaptor;
@Before
public void setUp() throws Exception {
@@ -102,12 +133,22 @@
mMockSatelliteController);
replaceInstance(DatagramController.class, "sInstance", null,
mMockDatagramController);
+ replaceInstance(SessionMetricsStats.class, "sInstance", null,
+ mMockSessionMetricsStats);
Resources resources = mContext.getResources();
when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(false);
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(false);
+ when(mMockSatelliteController.getSatellitePhone()).thenReturn(mPhone);
+ when(mMockSessionMetricsStats.addCountOfAutoExitDueToScreenOff()).thenReturn(
+ mMockSessionMetricsStats);
+ when(mMockSessionMetricsStats.addCountOfAutoExitDueToTnNetwork()).thenReturn(
+ mMockSessionMetricsStats);
mSatelliteModemInterface = new TestSatelliteModemInterface(
mContext, mMockSatelliteController, Looper.myLooper(), mFeatureFlags);
mTestSatelliteSessionController = new TestSatelliteSessionController(mContext,
@@ -170,6 +211,701 @@
}
@Test
+ public void testScreenOffInactivityTimer() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
+ eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+ when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveToIdleState();
+
+ // SatelliteSessionController should call registerForScreenStateChanged.
+ verify(mDeviceStateMonitor).registerForScreenStateChanged(mHandlerCaptor.capture(),
+ mMsgCaptor.capture(), any());
+
+ // Notify Screen off
+ sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
+ processAllMessages();
+ clearInvocations(mMockSatelliteController);
+
+ // Verify that the screen off inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+
+ // Time shift to cause timeout
+ moveTimeForward(SCREEN_OFF_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that SatelliteController#requestSatelliteEnabled() was called.
+ verify(mMockSatelliteController).requestSatelliteEnabled(
+ eq(false), eq(false), eq(false), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testScreenOffInactivityTimerStop() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
+ eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
+ // Satellite enabling request is for an emergency.
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+ when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveToIdleState();
+
+ // SatelliteSessionController should not call registerForScreenStateChanged.
+ verify(mDeviceStateMonitor, never()).registerForScreenStateChanged(
+ eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
+
+ moveToPowerOffState();
+
+ // Satellite enabling request is not for an emergency.
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+
+ moveToIdleState();
+
+ // SatelliteSessionController should call registerForScreenStateChanged.
+ verify(mDeviceStateMonitor).registerForScreenStateChanged(mHandlerCaptor.capture(),
+ mMsgCaptor.capture(), any());
+
+ // Notify Screen off
+ sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
+ processAllMessages();
+
+ // Verify that the screen off inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+
+ // Notify Screen on
+ sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), true);
+ processAllMessages();
+
+ // Verify that the screen off inactivity timer is stopped
+ assertFalse(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ }
+
+ @Test
+ public void testP2pSmsInactivityTimer() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Verify that the P2P SMS inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
+
+ mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);
+
+ // Verify that the P2P SMS inactivity timer is stopped.
+ assertFalse(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
+
+ mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);
+
+ // Verify that the P2P SMS inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted());
+
+ // Time shift to cause timeout
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state.
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
+
+ @Test
+ public void testEsosInactivityTimer() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Verify that the ESOS inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
+
+ mTestSatelliteSessionController.setDeviceAlignedWithSatellite(true);
+
+ // Verify that the ESOS inactivity timer is stopped.
+ assertFalse(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
+
+ mTestSatelliteSessionController.setDeviceAlignedWithSatellite(false);
+
+ // Verify that the ESOS inactivity timer is started.
+ assertTrue(mTestSatelliteSessionController.isEsosInActivityTimerStarted());
+
+ // Time shift to cause timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state.
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase1() {
+ // Send eSOS and SMS
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift to cause P2P_SMS timeout
+ passedTime = P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000;
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that keep ESOS timer, expired P2P_SMS timer.
+ // NOT_CONNECTED state, satellite disabling not called.
+ verifyEsosP2pSmsInactivityTimer(true, false);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase2() {
+ // Send eSOS and SMS
+ // Send SMS after 3 mins
+ // Send SMS after 1 mins
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS, SMS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+ sendMessage(DATAGRAM_TYPE_SMS);
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS again after 3 mins
+ passedTime = 3 * 60 * 1000;
+ moveTimeForward(3 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Sent SMS again after 1 mins
+ passedTime += 1 * 60 * 1000;
+ moveTimeForward(1 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase3() {
+ // Send eSOS and SMS
+ // Send eSOS after 5 mins
+ // After 15 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent ESOS
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS after 5 mins
+ moveTimeForward(3 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state, not called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase4() {
+ // Send SMS
+ // Send SMS after 2 mins
+ // After 3 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and auto exit
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS, Satellite is not in emergency mode
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(false, true);
+
+ // Sent SMS again after 2 mins
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(false, true);
+
+ // Time shift to cause P2P_SMS timeout
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that expired P2P_SMS timer
+ // reported IDLE state, called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, times(1)).requestSatelliteEnabled(
+ eq(false), eq(false), eq(false), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerCase5() {
+ // Send SMS
+ // Send ESOS after 2 mins
+ // After 12 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don'tauto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+
+ // Notify datagram controller is in WAITING_TO_CONNECT.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // Verify that ESOS, P2P_SMS timer are not started.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+
+ // Sent SMS
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS again after 2 mins
+ passedTime = 2 * 60 * 1000;
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS is not started, P2P_SMS timer is started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+ verifyEsosP2pSmsInactivityTimer(true, false);
+
+ // Time shift
+ moveTimeForward(passedTime);
+ processAllMessages();
+
+ // Verify that expired P2P_SMS timer
+ // reported IDLE state, called satellite disabling.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(true), any(IIntegerConsumer.Stub.class));
+ }
+
+ @Test
+ public void testEsosP2pSmsInactivityTimerInConnectedState() {
+ // Send eSOS and SMS
+ // After 10 minutes SatelliteSessionController moves to idle
+ // TN network reports IN_SERVICE
+ // Report the callback only and don't auto exit
+
+ long passedTime = 0;
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ // Support ESOS
+ when(mMockSatelliteController.isSatelliteEsosSupported(anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+
+ // Setup carrier config for timer values
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ ESOS_INACTIVITY_TIMEOUT_SEC);
+ bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
+ P2P_SMS_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ // Set up Datagram SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE
+ setupDatagramTransferringState(true);
+
+ moveToNotConnectedState();
+ moveNotConnectedToConnectedState();
+
+ // Verify that ESOS, P2P_SMS timer are started.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent ESOS
+ // CONNECTED -> TRANSFERRING -> CONNECTED
+ sendMessage(DATAGRAM_TYPE_SOS_MESSAGE);
+
+ // Verify that ESOS, P2P_SMS timer are restarted.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Sent SMS
+ // CONNECTED -> TRANSFERRING -> CONNECTED
+ sendMessage(DATAGRAM_TYPE_SMS);
+
+ // Verify that ESOS, P2P_SMS timer are restarted.
+ verifyEsosP2pSmsInactivityTimer(true, true);
+
+ // Time shift to cause P2P_SMS timeout
+ passedTime = P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000;
+ moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
+ processAllMessages();
+
+ // Verify that keep ESOS timer, expired P2P_SMS timer.
+ // CONNECTED state
+ verifyEsosP2pSmsInactivityTimer(true, false);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Time shift to cause ESOS timeout
+ moveTimeForward(ESOS_INACTIVITY_TIMEOUT_SEC * 1000 - passedTime);
+ processAllMessages();
+
+ // Verify that expired ESOS and P2P_SMS timer
+ // reported IDLE state.
+ verifyEsosP2pSmsInactivityTimer(false, false);
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
+
+ @Test
+ public void testDisableSatelliteWhenCellularModemEnabledInIdleMode() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
+ eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
+ when(mPhone.getServiceState()).thenReturn(mMockServiceState);
+ setUpResponseForRequestSatelliteEnabled(SATELLITE_RESULT_SUCCESS);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ mTestSatelliteSessionController.setSatelliteEnabledForNtnOnlySubscription(false);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Conditions for operation
+ boolean isEmergency = true;
+ // Cellular network is not IN_SERVICE and emergency only.
+ // Satellite request is emergency and emergency communication was established.
+ // Disabling satellite was not allowed
+ when(mMockServiceState.getVoiceRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mMockServiceState.getDataRegState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mMockServiceState.isEmergencyOnly()).thenReturn(false);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(isEmergency);
+ when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(true);
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(false);
+
+ moveToIdleState();
+
+ // Cellular network is not in STATE_IN_SERVICE or emergency only.
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+
+ // Notify cellular service is in STATE_IN_SERVICE.
+ ServiceState serviceState = new ServiceState();
+ serviceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
+ serviceState.setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
+ serviceState.setEmergencyOnly(false);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Satellite is in emergency mode and emergency communication was established.
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+
+ // Satellite is in emergency mode but emergency communication was not established.
+ // Disabling satellite was not allowed
+ when(mMockDatagramController.isEmergencyCommunicationEstablished()).thenReturn(false);
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(false);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Should not disable satellite
+ verify(mMockSatelliteController, never()).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, never()).addCountOfAutoExitDueToTnNetwork();
+ // Satellite is in emergency mode but emergency communication was not established.
+ // Disabling satellite was allowed
+ when(mMockSatelliteController.turnOffSatelliteSessionForEmergencyCall(
+ anyInt())).thenReturn(true);
+ mTestSatelliteSessionController.onCellularServiceStateChanged(serviceState);
+ processAllMessages();
+
+ // Should disable satellite
+ verify(mMockSatelliteController).requestSatelliteEnabled(
+ eq(false), eq(false), eq(isEmergency), any(IIntegerConsumer.Stub.class));
+ verify(mMockSessionMetricsStats, times(1)).addCountOfAutoExitDueToTnNetwork();
+ }
+
+ @Test
public void testStateTransition() {
/**
* Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
@@ -205,7 +941,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -217,7 +954,8 @@
// Sending datagrams failed
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to IDLE state.
@@ -229,7 +967,8 @@
// Start sending datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -241,7 +980,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -254,7 +994,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -266,7 +1007,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -279,7 +1021,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -292,7 +1035,8 @@
// Receiving datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to IDLE state.
@@ -304,7 +1048,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -315,7 +1060,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -339,7 +1085,8 @@
// Start receiving datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -351,7 +1098,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
@@ -362,7 +1110,8 @@
// Receiving datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
@@ -374,7 +1123,8 @@
// Start receiving datagrams again.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state.
@@ -385,7 +1135,8 @@
// Sending datagrams failed.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at TRANSFERRING state instead of moving to IDLE
@@ -461,7 +1212,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// The datagram sending event should be ignored.
@@ -474,8 +1226,8 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
verify(mMockDatagramController).onSatelliteModemStateChanged(
@@ -484,7 +1236,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -499,7 +1252,8 @@
// Sending datagrams failed
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -514,7 +1268,8 @@
// Start sending datagrams again
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -529,7 +1284,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -544,7 +1300,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -558,7 +1315,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -573,7 +1331,8 @@
// Start receiving datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -587,7 +1346,8 @@
// Receiving datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to CONNECTED state.
@@ -615,7 +1375,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to NOT_CONNECTED state.
@@ -632,8 +1393,8 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -658,8 +1419,8 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -694,8 +1455,8 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
// Wait for timeout
@@ -713,7 +1474,8 @@
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should stay at IDLE state because it failed to disable
@@ -769,7 +1531,8 @@
// Start sending datagrams and the NB-IOT inactivity timer should be stopped.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
processAllMessages();
@@ -781,10 +1544,12 @@
// The NB-IOT inactivity timer should be started.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
@@ -908,7 +1673,7 @@
moveSatelliteToEnablingState();
// Satellite enablement has failed
- mTestSatelliteSessionController.onSatelliteEnablementFailed();
+ mTestSatelliteSessionController.onSatelliteEnablementFailed(true);
processAllMessages();
// Satellite should move back to POWER_OFF state
@@ -936,28 +1701,41 @@
assertNotNull(mTestSatelliteSessionController);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
- // IDLE -> DISABLING
+ // IDLE -> DISABLING request failed -> NOT_CONNECTED
moveToIdleState();
- moveSatelliteToDisablingState();
+ moveSatelliteToDisablingRequestFailed(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
+ STATE_NOT_CONNECTED);
- // DISABLING -> POWER_OFF
+ // NOT_CONNECTED -> DISABLING -> POWER_OFF
+ moveSatelliteToDisablingState();
moveToPowerOffState();
- // TRANSFERRING -> DISABLING
+ // IDLE -> DISABLING -> POWER_OFF
+ moveToIdleState();
+ moveSatelliteToDisablingState();
+ moveToPowerOffState();
+
+ // TRANSFERRING -> DISABLING request failed -> CONNECTED
+ moveToIdleState();
+ moveIdleToTransferringState();
+ moveSatelliteToDisablingRequestFailed(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED, STATE_CONNECTED);
+
+ // CONNECTED -> DISABLING -> POWER_OFF
+ moveSatelliteToDisablingState();
+ moveToPowerOffState();
+
+ // TRANSFERRING -> DISABLING -> POWER_OFF
moveToIdleState();
moveIdleToTransferringState();
moveSatelliteToDisablingState();
-
- // DISABLING -> POWER_OFF
moveToPowerOffState();
- // LISTENING -> DISABLING
+ // LISTENING -> DISABLING -> POWER_OFF
moveToIdleState();
moveIdleToTransferringState();
moveTransferringToListeningState();
moveSatelliteToDisablingState();
-
- // DISABLING -> POWER_OFF
moveToPowerOffState();
}
@@ -986,6 +1764,62 @@
moveToPowerOffState();
}
+ @Test
+ public void testEmergencyModeChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
+
+ // Unregister exist callback
+ mTestSatelliteSessionController.unregisterForSatelliteModemStateChanged(
+ mTestSatelliteModemStateCallback);
+
+ // Register callback
+ mTestSatelliteSessionController.registerForSatelliteModemStateChanged(
+ mTestSatelliteModemStateCallback);
+
+ // Verify initial notification
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertSuccessfulEmergencyModeChangedCallback(
+ mTestSatelliteModemStateCallback, false);
+
+ mTestSatelliteSessionController.onEmergencyModeChanged(true);
+
+ assertSuccessfulEmergencyModeChangedCallback(
+ mTestSatelliteModemStateCallback, true);
+
+ mTestSatelliteSessionController.onEmergencyModeChanged(false);
+
+ assertSuccessfulEmergencyModeChangedCallback(
+ mTestSatelliteModemStateCallback, false);
+
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ mTestSatelliteSessionController.onEmergencyModeChanged(false);
+
+ assertEmergencyModeChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ }
+
+
+ private void verifyEsosP2pSmsInactivityTimer(boolean esosTimer, boolean p2pSmsTimer) {
+ assertEquals(mTestSatelliteSessionController.isEsosInActivityTimerStarted(), esosTimer);
+ assertEquals(mTestSatelliteSessionController.isP2pSmsInActivityTimerStarted(),
+ p2pSmsTimer);
+ }
+
+ private void sendMessage(@SatelliteManager.DatagramType int datagramType) {
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, datagramType);
+
+ processAllMessages();
+ }
+
private void setupDatagramTransferringState(boolean isTransferring) {
when(mMockDatagramController.isSendingInIdleState()).thenReturn(isTransferring);
when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
@@ -1049,7 +1883,8 @@
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
// Start sending datagrams
mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to TRANSFERRING state.
@@ -1064,7 +1899,8 @@
// Sending datagrams is successful and done.
mTestSatelliteSessionController.onDatagramTransferStateChanged(
SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
processAllMessages();
// SatelliteSessionController should move to LISTENING state.
@@ -1080,7 +1916,6 @@
assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
- assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
clearInvocations(mMockDatagramController);
@@ -1093,8 +1928,8 @@
processAllMessages();
// SatelliteSessionController should move to CONNECTED state
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
verify(mMockDatagramController).onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -1112,6 +1947,18 @@
STATE_DISABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
}
+ private void moveSatelliteToDisablingRequestFailed(int state, String stateName) {
+ moveSatelliteToDisablingState();
+
+ // Satellite disabled request failed
+ mTestSatelliteSessionController.onSatelliteEnablementFailed(false);
+ processAllMessages();
+
+ // Satellite should stay in previous state as satellite disable request failed
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback, state);
+ assertEquals(stateName, mTestSatelliteSessionController.getCurrentStateName());
+ }
+
private static class TestSatelliteModemInterface extends SatelliteModemInterface {
private final AtomicInteger mListeningEnabledCount = new AtomicInteger(0);
private final AtomicInteger mListeningDisabledCount = new AtomicInteger(0);
@@ -1164,6 +2011,8 @@
}
private static class TestSatelliteSessionController extends SatelliteSessionController {
+ boolean mSatelliteEnabledForNtnOnlySubscription = true;
+
TestSatelliteSessionController(Context context, Looper looper, FeatureFlags featureFlags,
boolean isSatelliteSupported,
SatelliteModemInterface satelliteModemInterface) {
@@ -1185,12 +2034,26 @@
boolean isEventDeferred(int event) {
return hasDeferredMessages(event);
}
+
+ boolean isScreenOffInActivityTimerStarted() {
+ return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ }
+
+ protected boolean isSatelliteEnabledForNtnOnlySubscription() {
+ return mSatelliteEnabledForNtnOnlySubscription;
+ }
+
+ void setSatelliteEnabledForNtnOnlySubscription(boolean enabled) {
+ mSatelliteEnabledForNtnOnlySubscription = false;
+ }
}
private static class TestSatelliteModemStateCallback extends ISatelliteModemStateCallback.Stub {
private final AtomicInteger mModemState = new AtomicInteger(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
- private final Semaphore mSemaphore = new Semaphore(0);
+ private final AtomicBoolean mIsEmergency = new AtomicBoolean(false);
+ private final Semaphore mSemaphoreForModemStateChanged = new Semaphore(0);
+ private final Semaphore mSemaphoreForEmergencyModeChanged = new Semaphore(0);
private final Object mLock = new Object();
private final List<Integer> mModemStates = new ArrayList<>();
@@ -1202,15 +2065,32 @@
mModemStates.add(state);
}
try {
- mSemaphore.release();
+ mSemaphoreForModemStateChanged.release();
} catch (Exception ex) {
logd("onSatelliteModemStateChanged: Got exception, ex=" + ex);
}
}
- public boolean waitUntilResult() {
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: state=" + isEmergency);
+ mIsEmergency.set(isEmergency);
try {
- if (!mSemaphore.tryAcquire(EVENT_PROCESSING_TIME_MILLIS, TimeUnit.MILLISECONDS)) {
+ mSemaphoreForEmergencyModeChanged.release();
+ } catch (Exception ex) {
+ logd("onEmergencyModeChanged: Got exception, ex=" + ex);
+ }
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ }
+
+ public boolean waitUntilResultForModemStateChanged() {
+ try {
+ if (!mSemaphoreForModemStateChanged.tryAcquire(EVENT_PROCESSING_TIME_MILLIS,
+ TimeUnit.MILLISECONDS)) {
logd("Timeout to receive onSatelliteModemStateChanged");
return false;
}
@@ -1221,6 +2101,20 @@
}
}
+ public boolean waitUntilResultForEmergencyModeChanged() {
+ try {
+ if (!mSemaphoreForEmergencyModeChanged.tryAcquire(EVENT_PROCESSING_TIME_MILLIS,
+ TimeUnit.MILLISECONDS)) {
+ logd("Timeout to receive onEmergencyModeChanged");
+ return false;
+ }
+ return true;
+ } catch (Exception ex) {
+ logd("onEmergencyModeChanged: Got exception=" + ex);
+ return false;
+ }
+ }
+
public int getModemState() {
return mModemState.get();
}
@@ -1243,22 +2137,58 @@
}
}
+ public boolean getEmergencyMode() {
+ return mIsEmergency.get();
+ }
+
public void clearSemaphorePermits() {
- mSemaphore.drainPermits();
+ mSemaphoreForModemStateChanged.drainPermits();
}
}
private static void assertSuccessfulModemStateChangedCallback(
TestSatelliteModemStateCallback callback,
@SatelliteManager.SatelliteModemState int expectedModemState) {
- boolean successful = callback.waitUntilResult();
+ boolean successful = callback.waitUntilResultForModemStateChanged();
assertTrue(successful);
assertEquals(expectedModemState, callback.getModemState());
}
private static void assertModemStateChangedCallbackNotCalled(
TestSatelliteModemStateCallback callback) {
- boolean successful = callback.waitUntilResult();
+ boolean successful = callback.waitUntilResultForModemStateChanged();
assertFalse(successful);
}
+
+ private static void assertSuccessfulEmergencyModeChangedCallback(
+ TestSatelliteModemStateCallback callback,
+ boolean isEmergency) {
+ boolean successful = callback.waitUntilResultForEmergencyModeChanged();
+ assertTrue(successful);
+ assertEquals(isEmergency, callback.getEmergencyMode());
+ }
+
+ private static void assertEmergencyModeChangedCallbackNotCalled(
+ TestSatelliteModemStateCallback callback) {
+ boolean successful = callback.waitUntilResultForEmergencyModeChanged();
+ assertFalse(successful);
+ }
+
+ private void sendScreenStateChanged(Handler h, int what, boolean screenOn) {
+ Message msg = Message.obtain();
+
+ msg.what = what;
+ msg.obj = new AsyncResult(null, screenOn, null);
+ h.sendMessage(msg);
+ }
+
+ private void setUpResponseForRequestSatelliteEnabled(
+ @SatelliteManager.SatelliteResult int expectedResult) {
+ doAnswer(invocation -> {
+ IIntegerConsumer integerConsumer = invocation.getArgument(3);
+ integerConsumer.accept(expectedResult);
+ return null;
+ }).when(mMockSatelliteController).requestSatelliteEnabled(anyBoolean(), anyBoolean(),
+ anyBoolean(), any(IIntegerConsumer.class));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index 62b9def..5e560bc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -122,8 +122,8 @@
static final int FAKE_USER_ID2 = 11;
static final int FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED = 1;
static final int FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED = 0;
- static final int FAKE_SATELLITE_IS_NTN_ENABLED = 1;
- static final int FAKE_SATELLITE_IS_NTN_DISABLED = 0;
+ static final int FAKE_SATELLITE_IS_ONLY_NTN_ENABLED = 1;
+ static final int FAKE_SATELLITE_IS_ONLY_NTN_DISABLED = 0;
static final int FAKE_SERVICE_CAPABILITIES_1 =
SubscriptionManager.SERVICE_CAPABILITY_DATA_BITMASK;
static final int FAKE_SERVICE_CAPABILITIES_2 =
@@ -132,6 +132,8 @@
static final int FAKE_SATELLITE_ENTITLEMENT_STATUS_DISABLED = 0;
static final String FAKE_SATELLITE_ENTITLEMENT_PLMNS1 = "123123,12310";
static final String FAKE_SATELLITE_ENTITLEMENT_PLMNS2 = "";
+ static final int FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED = 1;
+ static final int FAKE_SATELLITE_ESOS_SUPPORTED_DISABLED = 0;
static final String FAKE_MAC_ADDRESS1 = "DC:E5:5B:38:7D:40";
static final String FAKE_MAC_ADDRESS2 = "DC:B5:4F:47:F3:4C";
@@ -141,6 +143,9 @@
static final int FAKE_TRANSFER_STATUS_TRANSFERRED_OUT = 1;
static final int FAKE_TRANSFER_STATUS_CONVERTED = 2;
+ static final int FAKE_SATELLITE_PROVISIONED = 1;
+ static final int FAKE_SATELLITE_NOT_PROVISIONED = 0;
+
static final SubscriptionInfoInternal FAKE_SUBSCRIPTION_INFO1 =
new SubscriptionInfoInternal.Builder()
.setId(1)
@@ -208,12 +213,14 @@
.setSatelliteEnabled(0)
.setSatelliteAttachEnabledForCarrier(
FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED)
- .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_DISABLED)
+ .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_ONLY_NTN_DISABLED)
.setGroupDisabled(false)
.setServiceCapabilities(FAKE_SERVICE_CAPABILITIES_1)
.setTransferStatus(FAKE_TRANSFER_STATUS_TRANSFERRED_OUT)
.setSatelliteEntitlementStatus(FAKE_SATELLITE_ENTITLEMENT_STATUS_DISABLED)
.setSatelliteEntitlementPlmns(FAKE_SATELLITE_ENTITLEMENT_PLMNS2)
+ .setSatelliteESOSSupported(FAKE_SATELLITE_ESOS_SUPPORTED_DISABLED)
+ .setIsSatelliteProvisionedForNonIpDatagram(FAKE_SATELLITE_NOT_PROVISIONED)
.build();
static final SubscriptionInfoInternal FAKE_SUBSCRIPTION_INFO2 =
@@ -283,12 +290,14 @@
.setSatelliteEnabled(1)
.setSatelliteAttachEnabledForCarrier(
FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED)
- .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_ENABLED)
+ .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED)
.setGroupDisabled(false)
.setServiceCapabilities(FAKE_SERVICE_CAPABILITIES_2)
.setTransferStatus(FAKE_TRANSFER_STATUS_CONVERTED)
.setSatelliteEntitlementStatus(FAKE_SATELLITE_ENTITLEMENT_STATUS_ENABLED)
.setSatelliteEntitlementPlmns(FAKE_SATELLITE_ENTITLEMENT_PLMNS1)
+ .setSatelliteESOSSupported(FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
+ .setIsSatelliteProvisionedForNonIpDatagram(FAKE_SATELLITE_PROVISIONED)
.build();
private SubscriptionDatabaseManager mDatabaseManagerUT;
@@ -448,8 +457,8 @@
doReturn(1).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID1));
doReturn(2).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID2));
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- when(mFeatureFlags.dataOnlyCellularService()).thenReturn(true);
when(mFeatureFlags.supportPsimToEsimConversion()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
mFeatureFlags, mSubscriptionDatabaseManagerCallback);
logd("SubscriptionDatabaseManagerTest -Setup!");
@@ -2010,28 +2019,28 @@
// exception is expected if there is nothing in the database.
assertThrows(IllegalArgumentException.class,
() -> mDatabaseManagerUT.setNtn(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- FAKE_SATELLITE_IS_NTN_ENABLED));
+ FAKE_SATELLITE_IS_ONLY_NTN_ENABLED));
SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
mDatabaseManagerUT.setNtn(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- FAKE_SATELLITE_IS_NTN_ENABLED);
+ FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
processAllMessages();
subInfo = new SubscriptionInfoInternal.Builder(subInfo)
- .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_ENABLED)
+ .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED)
.build();
verifySubscription(subInfo);
verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
assertThat(mDatabaseManagerUT.getSubscriptionProperty(
FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- SimInfo.COLUMN_IS_NTN)).isEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+ SimInfo.COLUMN_IS_ONLY_NTN)).isEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- SimInfo.COLUMN_IS_NTN, FAKE_SATELLITE_IS_NTN_DISABLED);
+ SimInfo.COLUMN_IS_ONLY_NTN, FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).getOnlyNonTerrestrialNetwork())
- .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+ .isEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
}
@Test
@@ -2074,13 +2083,13 @@
SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- FAKE_SATELLITE_IS_NTN_DISABLED);
+ FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
processAllMessages();
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
reset(mSubscriptionDatabaseManagerCallback);
subInfo = new SubscriptionInfoInternal.Builder(subInfo)
- .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_NTN_ENABLED)
+ .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED)
.build();
int subId = subInfo.getSubscriptionId();
@@ -2100,13 +2109,13 @@
assertThat(mDatabaseManagerUT.getSubscriptionProperty(
FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- SimInfo.COLUMN_IS_NTN)).isNotEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+ SimInfo.COLUMN_IS_ONLY_NTN)).isNotEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
- SimInfo.COLUMN_IS_NTN, FAKE_SATELLITE_IS_NTN_ENABLED);
+ SimInfo.COLUMN_IS_ONLY_NTN, FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).getOnlyNonTerrestrialNetwork())
- .isNotEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+ .isNotEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
}
@Test
@@ -2357,4 +2366,69 @@
.getSatelliteEntitlementPlmns())
.isEqualTo(FAKE_SATELLITE_ENTITLEMENT_PLMNS2);
}
+
+ @Test
+ public void testUpdateSatelliteESOSSupported() throws Exception {
+ // exception is expected if there is nothing in the database.
+ assertThrows(IllegalArgumentException.class,
+ () -> mDatabaseManagerUT.setSatelliteESOSSupported(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED));
+
+ SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+ mDatabaseManagerUT.setSatelliteESOSSupported(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED);
+ processAllMessages();
+
+ subInfo = new SubscriptionInfoInternal.Builder(subInfo)
+ .setSatelliteESOSSupported(FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
+ .build();
+ verifySubscription(subInfo);
+ verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+ assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED)).isEqualTo(
+ FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED);
+
+ mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED, FAKE_SATELLITE_ESOS_SUPPORTED_DISABLED);
+ assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+ .getSatelliteESOSSupported()).isEqualTo(FAKE_SATELLITE_ESOS_SUPPORTED_DISABLED);
+ }
+
+ @Test
+ public void testUpdateSatelliteProvisionedStatus() throws Exception {
+ // exception is expected if there is nothing in the database.
+ assertThrows(IllegalArgumentException.class,
+ () -> mDatabaseManagerUT.setIsSatelliteProvisionedForNonIpDatagram(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ FAKE_SATELLITE_PROVISIONED));
+
+ SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+ mDatabaseManagerUT.setIsSatelliteProvisionedForNonIpDatagram(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ FAKE_SATELLITE_PROVISIONED);
+ processAllMessages();
+
+ subInfo = new SubscriptionInfoInternal.Builder(subInfo)
+ .setIsSatelliteProvisionedForNonIpDatagram(FAKE_SATELLITE_PROVISIONED)
+ .build();
+ verifySubscription(subInfo);
+ verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+ assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM))
+ .isEqualTo(FAKE_SATELLITE_PROVISIONED);
+
+ mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ FAKE_SATELLITE_NOT_PROVISIONED);
+ assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+ FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+ .getIsSatelliteProvisionedForNonIpDatagram())
+ .isEqualTo(FAKE_SATELLITE_NOT_PROVISIONED);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index de43b85..f639a51 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -24,8 +24,6 @@
import android.telephony.UiccAccessRule;
import android.telephony.ims.ImsMmTelManager;
-import com.android.internal.telephony.flags.Flags;
-
import org.junit.Rule;
import org.junit.Test;
@@ -110,7 +108,7 @@
SubscriptionDatabaseManagerTest
.FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED)
.setOnlyNonTerrestrialNetwork(
- SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED)
+ SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_ONLY_NTN_ENABLED)
.setGroupDisabled(false)
.setOnlyNonTerrestrialNetwork(1)
.setServiceCapabilities(
@@ -122,6 +120,10 @@
.setSatelliteEntitlementPlmns(
SubscriptionDatabaseManagerTest
.FAKE_SATELLITE_ENTITLEMENT_PLMNS1)
+ .setSatelliteESOSSupported(
+ SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
+ .setIsSatelliteProvisionedForNonIpDatagram(
+ SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED)
.build();
private final SubscriptionInfoInternal mSubInfoNull =
@@ -156,7 +158,6 @@
@Test
public void testSubscriptionInfoInternalSetAndGet() {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
assertThat(mSubInfo.getSubscriptionId()).isEqualTo(1);
assertThat(mSubInfo.getIccId()).isEqualTo(SubscriptionDatabaseManagerTest.FAKE_ICCID1);
assertThat(mSubInfo.getSimSlotIndex()).isEqualTo(0);
@@ -240,7 +241,7 @@
.isEqualTo(SubscriptionDatabaseManagerTest
.FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED);
assertThat(mSubInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(
- SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED);
+ SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
assertThat(mSubInfo.isGroupDisabled()).isFalse();
assertThat(mSubInfo.getOnlyNonTerrestrialNetwork()).isEqualTo(1);
assertThat(mSubInfo.getServiceCapabilities()).isEqualTo(
@@ -252,6 +253,10 @@
assertThat(mSubInfo.getSatelliteEntitlementPlmns())
.isEqualTo(SubscriptionDatabaseManagerTest
.FAKE_SATELLITE_ENTITLEMENT_PLMNS1);
+ assertThat(mSubInfo.getSatelliteESOSSupported())
+ .isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED);
+ assertThat(mSubInfo.getIsSatelliteProvisionedForNonIpDatagram())
+ .isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED);
}
@Test
@@ -263,7 +268,6 @@
@Test
public void testConvertToSubscriptionInfo() {
- mSetFlagsRule.enableFlags(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE);
SubscriptionInfo subInfo = mSubInfo.toSubscriptionInfo();
assertThat(subInfo.getSubscriptionId()).isEqualTo(1);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index eb06ff1..65790f8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -44,7 +44,7 @@
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
-import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_DISABLED;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_ONLY_NTN_DISABLED;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_UUID1;
@@ -109,8 +109,6 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.euicc.EuiccController;
-import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback;
import com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.SubscriptionProvider;
import com.android.internal.telephony.subscription.SubscriptionManagerService.BinderWrapper;
import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
@@ -164,7 +162,6 @@
// mocked
private SubscriptionManagerServiceCallback mMockedSubscriptionManagerServiceCallback;
private EuiccController mEuiccController;
- private FeatureFlags mFlags;
private BinderWrapper mBinder;
private Set<Integer> mActiveSubs = new ArraySet<>();
@@ -215,9 +212,13 @@
((MockContentResolver) mContext.getContentResolver()).addProvider(
Telephony.Carriers.CONTENT_URI.getAuthority(), mSubscriptionProvider);
- mFlags = Mockito.mock(FeatureFlags.class);
+ doReturn(true).when(mFeatureFlags).saferGetPhoneNumber();
+ doReturn(true).when(mFeatureFlags).uiccPhoneNumberFix();
+ doReturn(true).when(mFeatureFlags).ddsCallback();
+ doReturn(true).when(mFeatureFlags).oemEnabledSatelliteFlag();
+
mSubscriptionManagerServiceUT = new SubscriptionManagerService(mContext, Looper.myLooper(),
- mFlags);
+ mFeatureFlags);
monitorTestableLooper(new TestableLooper(getBackgroundHandler().getLooper()));
monitorTestableLooper(new TestableLooper(getSubscriptionDatabaseManager().getLooper()));
@@ -240,8 +241,6 @@
doReturn(true).when(mUserManager)
.isManagedProfile(eq(FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier()));
- // Due to affect exist implementation, bypass feature flag.
- doReturn(false).when(mFlags).enforceTelephonyFeatureMappingForPublicApis();
doReturn(true).when(mPackageManager).hasSystemFeature(
eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
logd("SubscriptionManagerServiceTest -Setup!");
@@ -275,12 +274,6 @@
return (SubscriptionDatabaseManager) field.get(mSubscriptionManagerServiceUT);
}
- private SubscriptionDatabaseManagerCallback getSubscriptionDatabaseCallback() throws Exception {
- Field field = SubscriptionDatabaseManager.class.getDeclaredField("mCallback");
- field.setAccessible(true);
- return (SubscriptionDatabaseManagerCallback) field.get(getSubscriptionDatabaseManager());
- }
-
/**
* Insert the subscription info to the database. This is an instant insertion method. For real
* insertion sequence please use {@link #testInsertNewSim()}.
@@ -457,7 +450,7 @@
@Test
@DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
public void testSetPhoneNumber() {
- doReturn(false).when(mFlags).enforceTelephonyFeatureMapping();
+ doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMapping();
doReturn(true).when(mPackageManager).hasSystemFeature(
eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
@@ -517,7 +510,7 @@
mSubscriptionManagerServiceUT, vendorApiLevel);
// Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
- doReturn(true).when(mFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
doReturn(true).when(mPackageManager).hasSystemFeature(
eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
try {
@@ -786,6 +779,8 @@
assertThat(b.containsKey(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX)).isTrue();
assertThat(b.getInt(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX)).isEqualTo(1);
+
+ verify(mMockedSubscriptionManagerServiceCallback).onDefaultDataSubscriptionChanged(eq(1));
}
@Test
@@ -1281,8 +1276,8 @@
@EnableCompatChanges({SubscriptionManagerService.REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID,
SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
public void testIsSubscriptionAssociatedWithUserMultiSubs() {
- doReturn(true).when(mFlags).workProfileApiSplit();
- doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
+ doReturn(true).when(mFeatureFlags).workProfileApiSplit();
+ doReturn(true).when(mFeatureFlags).enforceSubscriptionUserFilter();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -1344,8 +1339,8 @@
public void testSubscriptionAssociationWorkProfileCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
- doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
- doReturn(true).when(mFlags).workProfileApiSplit();
+ doReturn(true).when(mFeatureFlags).enforceSubscriptionUserFilter();
+ doReturn(true).when(mFeatureFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
// Sub 1 is associated with work profile; Sub 2 is unassociated.
@@ -1480,8 +1475,8 @@
public void testSubscriptionAssociationPersonalCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
- doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
- doReturn(true).when(mFlags).workProfileApiSplit();
+ doReturn(true).when(mFeatureFlags).enforceSubscriptionUserFilter();
+ doReturn(true).when(mFeatureFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
// Sub 1 is unassociated; Sub 2 is associated with work profile.
@@ -1832,7 +1827,7 @@
multiNumberSubInfo =
new SubscriptionInfoInternal.Builder(multiNumberSubInfo)
.setNumberFromCarrier("")
- .setNumber(phoneNumberFromUicc)
+ .setNumber("")
.setNumberFromIms(phoneNumberFromIms)
.build();
subId = insertSubscription(multiNumberSubInfo);
@@ -2524,6 +2519,23 @@
}
@Test
+ public void testGetPhoneNumberFromUicc() {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ testSetPhoneNumber();
+ // Number from line1Number should be FAKE_PHONE_NUMBER1 instead of FAKE_PHONE_NUMBER2
+ assertThat(mSubscriptionManagerServiceUT.getPhoneNumber(1,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, CALLING_PACKAGE, CALLING_FEATURE))
+ .isEqualTo(FAKE_PHONE_NUMBER1);
+
+ doReturn("").when(mPhone).getLine1Number();
+
+ // If getLine1Number is empty, then the number should be from the sub info.
+ assertThat(mSubscriptionManagerServiceUT.getPhoneNumber(1,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, CALLING_PACKAGE, CALLING_FEATURE))
+ .isEqualTo(FAKE_PHONE_NUMBER2);
+ }
+
+ @Test
public void testGetPhoneNumberFromInactiveSubscription() {
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
testInactiveSimRemoval();
@@ -2543,8 +2555,6 @@
@Test
public void testGetPhoneNumberFromDefaultSubscription() {
- doReturn(true).when(mFlags).saferGetPhoneNumber();
-
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
int subId = insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -3192,7 +3202,6 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "true");
- doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
.setIccid(FAKE_ICCID1)
@@ -3222,14 +3231,12 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "false");
- doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
@Test
public void testIsSatelliteSpnWithEmptySpn() {
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, ""); // Empty
System.setProperty("persist.radio.allow_mock_modem", "true");
- doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
.setIccid(FAKE_ICCID1)
@@ -3255,7 +3262,7 @@
SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
.getSubscriptionInfoInternal(1);
assertThat(subInfo.getOnlyNonTerrestrialNetwork())
- .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+ .isEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
@@ -3282,10 +3289,9 @@
subInfo = mSubscriptionManagerServiceUT
.getSubscriptionInfoInternal(2);
assertThat(subInfo.getOnlyNonTerrestrialNetwork())
- .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+ .isEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
System.setProperty("persist.radio.allow_mock_modem", "false");
- doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
@Test
@@ -3293,7 +3299,6 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "true");
- doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
.setIccid(FAKE_ICCID1)
@@ -3322,7 +3327,6 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "false");
- doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
@Test
@@ -3330,7 +3334,6 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "true");
- doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
.setIccid(FAKE_ICCID1)
@@ -3360,7 +3363,6 @@
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
System.setProperty("persist.radio.allow_mock_modem", "false");
- doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/IsimUiccRecordsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/IsimUiccRecordsTest.java
index 6f4666c..f33b002 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/IsimUiccRecordsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/IsimUiccRecordsTest.java
@@ -66,7 +66,7 @@
private class IsimUiccRecordsUT extends IsimUiccRecords {
IsimUiccRecordsUT(UiccCardApplication app, Context c,
CommandsInterface ci, IccFileHandler mFhMock) {
- super(app, c, ci);
+ super(app, c, ci, mFeatureFlags);
mFh = mFhMock;
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
index d2490ef..10c51c3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardApplicationTest.java
@@ -74,7 +74,7 @@
mUiccCardAppStatus.pin2 = IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
mUiccCardApplication = new UiccCardApplication(mUiccProfile, mUiccCardAppStatus,
- mContext, mSimulatedCommands);
+ mContext, mSimulatedCommands, mFeatureFlags);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 9265a62..58a8153 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -123,7 +123,7 @@
// (before 1.2) of hal
mIccCardStatus.mSlotPortMapping = new IccSlotPortMapping();
mIccCardStatus.mSlotPortMapping.mPhysicalSlotIndex = 0;
- mUiccControllerUT = UiccController.make(mContext);
+ mUiccControllerUT = UiccController.make(mContext, mFeatureFlags);
// reset sLastSlotStatus so that onGetSlotStatusDone always sees a change in the slot status
mUiccControllerUT.sLastSlotStatus = null;
processAllMessages();
@@ -145,7 +145,7 @@
com.android.internal.R.array.non_removable_euicc_slots,
nonRemovableEuiccSlots);
replaceInstance(UiccController.class, "mInstance", null, null);
- mUiccControllerUT = UiccController.make(mContext);
+ mUiccControllerUT = UiccController.make(mContext, mFeatureFlags);
processAllMessages();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index 5c1993f..a2b42af 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -29,7 +29,6 @@
import static org.mockito.Mockito.verify;
import android.os.Binder;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -38,11 +37,9 @@
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyTest;
-import com.android.internal.telephony.flags.Flags;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,13 +58,9 @@
private int mPhoneId = 0;
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
- mSetFlagsRule.enableFlags(Flags.FLAG_CLEANUP_OPEN_LOGICAL_CHANNEL_RECORD_ON_DISPOSE);
mUiccCard = mock(UiccCard.class);
mIccCardStatus = mock(IccCardStatus.class);
/* initially there are no application available */
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
index 8209dfa..f88bc1e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
@@ -32,6 +32,7 @@
import android.content.res.Resources;
import android.os.Looper;
import android.os.Message;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
@@ -89,7 +90,7 @@
}
UiccStateChangedLauncher uiccLauncher =
- new UiccStateChangedLauncher(mContext, UiccController.getInstance());
+ new UiccStateChangedLauncher(mContext, UiccController.getInstance(), mFeatureFlags);
ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
verify(UiccController.getInstance(), times(1)).registerForIccChanged(eq(uiccLauncher),
integerArgumentCaptor.capture(),
@@ -108,7 +109,8 @@
// Amount of sent broadcasts to the device provisioning package.
int broadcast_count = 1;
- verify(mContext, times(broadcast_count)).sendBroadcast(intentArgumentCaptor.capture());
+ verify(mContext, times(broadcast_count)).sendBroadcastAsUser(intentArgumentCaptor.capture(),
+ eq(UserHandle.ALL));
assertEquals(PROVISIONING_PACKAGE_NAME, intentArgumentCaptor.getValue().getPackage());
assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED,
intentArgumentCaptor.getValue().getAction());
@@ -119,14 +121,16 @@
uiccLauncher.handleMessage(msg);
broadcast_count++;
- verify(mContext, times(broadcast_count)).sendBroadcast(intentArgumentCaptor.capture());
+ verify(mContext, times(broadcast_count)).sendBroadcastAsUser(intentArgumentCaptor.capture(),
+ eq(UserHandle.ALL));
assertEquals(PROVISIONING_PACKAGE_NAME, intentArgumentCaptor.getValue().getPackage());
assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED,
intentArgumentCaptor.getValue().getAction());
// Nothing's changed. Broadcast should not be sent.
uiccLauncher.handleMessage(msg);
- verify(mContext, times(broadcast_count)).sendBroadcast(any(Intent.class));
+ verify(mContext, times(broadcast_count)).sendBroadcastAsUser(any(Intent.class),
+ eq(UserHandle.ALL));
// Card state's changed from restricted. Broadcast should be sent.
card.update(mContext, mSimulatedCommands,
@@ -134,7 +138,8 @@
uiccLauncher.handleMessage(msg);
broadcast_count++;
- verify(mContext, times(broadcast_count)).sendBroadcast(intentArgumentCaptor.capture());
+ verify(mContext, times(broadcast_count)).sendBroadcastAsUser(any(Intent.class),
+ eq(UserHandle.ALL));
assertEquals(PROVISIONING_PACKAGE_NAME, intentArgumentCaptor.getValue().getPackage());
assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED,
intentArgumentCaptor.getValue().getAction());
@@ -151,7 +156,7 @@
}
UiccStateChangedLauncher uiccLauncher =
- new UiccStateChangedLauncher(mContext, UiccController.getInstance());
+ new UiccStateChangedLauncher(mContext, UiccController.getInstance(), mFeatureFlags);
verify(UiccController.getInstance(), never()).registerForIccChanged(eq(uiccLauncher),
anyInt(), anyObject());
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
index c38be60..bcb5c4c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccCardTest.java
@@ -197,7 +197,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi,
"E00582030200009000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, responses);
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
return channel;
}
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
index d140ca8..2fef021 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/EuiccPortTest.java
@@ -1202,7 +1202,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi,
"E00582030200009000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, responses);
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
return channel;
}
@@ -1210,7 +1210,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi,
"E00582030201009000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, responses);
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
return channel;
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
index cf3f900..1252ff8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
@@ -16,37 +16,52 @@
package com.android.internal.telephony.uicc.euicc.apdu;
+import static com.android.internal.telephony.CommandException.Error.RADIO_NOT_AVAILABLE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.os.Handler;
import android.os.Looper;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.preference.PreferenceManager;
+import android.telephony.IccOpenLogicalChannelResponse;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import androidx.test.InstrumentationRegistry;
+
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.euicc.EuiccSession;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
-import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class ApduSenderTest {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private static class ResponseCaptor extends ApduSenderResultCallback {
public byte[] response;
@@ -76,6 +91,13 @@
}
}
+ private static final int PHONE_ID = 0;
+ private static final String SESSION_ID = "TEST";
+ // keep in sync with ApduSender.mChannelKey
+ private static final String SHARED_PREFS_KEY_CHANNEL_ID = "esim-channel_0";
+ // keep in sync with ApduSender.mChannelResponseKey
+ private static final String SHARED_PREFS_KEY_CHANNEL_RESPONSE = "esim-res-id_0";
+
// Mocked classes
private CommandsInterface mMockCi;
@@ -83,20 +105,20 @@
private Handler mHandler;
private ResponseCaptor mResponseCaptor;
private byte[] mSelectResponse;
- private static final String AID = "B2C3D4";
private ApduSender mSender;
@Before
public void setUp() {
- mMockCi = mock(CommandsInterface.class);
- mHandler = new Handler(Looper.myLooper());
+ mSetFlagsRule.enableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER);
+ mMockCi = mock(CommandsInterface.class);
+ mLooper = TestableLooper.get(this);
+ mHandler = new Handler(mLooper.getLooper());
mResponseCaptor = new ResponseCaptor();
mSelectResponse = null;
- mSender = new ApduSender(InstrumentationRegistry.getContext(), 0 /* phoneId= */,
- mMockCi, AID, false /* supportExtendedApdu */);
- mLooper = TestableLooper.get(this);
+ mSender = new ApduSender(InstrumentationRegistry.getContext(), PHONE_ID,
+ mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
}
@After
@@ -107,12 +129,25 @@
mResponseCaptor = null;
mSelectResponse = null;
mSender = null;
+
+ EuiccSession.get().endSession(SESSION_ID);
+ clearSharedPreferences();
+ }
+
+ @Test
+ public void testWrongAid_throwsIllegalArgumentException() {
+ String wrongAid = "-1";
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ new ApduSender(InstrumentationRegistry.getContext(), 0 /* phoneId= */,
+ mMockCi, wrongAid, false /* supportExtendedApdu */);
+ });
}
@Test
public void testSendEmptyCommands() throws InterruptedException {
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "A1A1A19000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mSender.send((selectResponse, requestBuilder) -> mSelectResponse = selectResponse,
mResponseCaptor, mHandler);
@@ -121,7 +156,7 @@
assertEquals("A1A1A19000", IccUtils.bytesToHexString(mSelectResponse));
assertNull(mResponseCaptor.response);
assertNull(mResponseCaptor.exception);
- verify(mMockCi).iccOpenLogicalChannel(eq(AID), anyInt(), any());
+ verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
}
@@ -137,22 +172,25 @@
assertNull("Request provider should not be called when failed to open channel.",
mSelectResponse);
assertTrue(mResponseCaptor.exception instanceof ApduException);
- verify(mMockCi).iccOpenLogicalChannel(eq(AID), anyInt(), any());
+ verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
}
@Test
public void testSend() throws InterruptedException {
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
mLooper.processAllMessages();
assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
- verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10), eq(1), eq(2),
- eq(3), eq(0), eq("a"), anyBoolean(), any());
+ InOrder inOrder = inOrder(mMockCi);
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
+ eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
}
@Test
@@ -160,7 +198,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A19000", "A29000",
"A39000", "A49000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mSender.send((selectResponse, requestBuilder) -> {
requestBuilder.addApdu(10, 1, 2, 3, 0, "a");
@@ -171,14 +209,17 @@
mLooper.processAllMessages();
assertEquals("A4", IccUtils.bytesToHexString(mResponseCaptor.response));
- verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10), eq(1), eq(2),
- eq(3), eq(0), eq("a"), anyBoolean(), any());
- verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10), eq(1), eq(2),
- eq(3), eq(1), eq("ab"), anyBoolean(), any());
- verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10), eq(1), eq(2),
- eq(3), eq(0), eq(""), anyBoolean(), any());
- verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(0x81), eq(0xE2), eq(0x91),
- eq(0), eq(2), eq("abcd"), anyBoolean(), any());
+ InOrder inOrder = inOrder(mMockCi);
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
+ eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
+ eq(1), eq(2), eq(3), eq(1), eq("ab"), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
+ eq(1), eq(2), eq(3), eq(0), eq(""), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(0x81),
+ eq(0xE2), eq(0x91), eq(0), eq(2), eq("abcd"), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
}
@Test
@@ -186,7 +227,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A19000", "A29000",
"A39000", "A49000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mResponseCaptor.stopApduIndex = 2;
mSender.send((selectResponse, requestBuilder) -> {
@@ -211,7 +252,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A16104",
"B2B2B2B26102", "C3C39000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -231,7 +272,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A19000", "9000", "9000",
"B22B6103", "B2222B9000", "C39000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
// Each segment has 0xFF (the limit of a single command) bytes.
String s1 = new String(new char[0xFF]).replace("\0", "AA");
@@ -262,7 +303,7 @@
public void testSendStoreDataLongDataMod0() throws InterruptedException {
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "9000", "B2222B9000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
// Each segment has 0xFF (the limit of a single command) bytes.
String s1 = new String(new char[0xFF]).replace("\0", "AA");
@@ -284,7 +325,7 @@
public void testSendStoreDataLen0() throws InterruptedException {
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "B2222B9000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
mSender.send((selectResponse, requestBuilder) -> {
requestBuilder.addStoreData("");
@@ -301,7 +342,7 @@
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A19000", "9000",
"B22B6103", "6985");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
// Each segment has 0xFF (the limit of a single command) bytes.
String s1 = new String(new char[0xFF]).replace("\0", "AA");
@@ -328,7 +369,7 @@
@Test
public void testChannelAlreadyOpened() throws InterruptedException {
int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
- LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
ResponseCaptor outerResponseCaptor = new ResponseCaptor();
mSender.send(
@@ -341,6 +382,158 @@
assertNull("Should not open channel when another one is already opened.", mSelectResponse);
assertTrue(mResponseCaptor.exception instanceof ApduException);
- verify(mMockCi, times(1)).iccOpenLogicalChannel(eq(AID), anyInt(), any());
+ verify(mMockCi, times(1)).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ }
+
+ @Test
+ public void testConstructor_doNotCloseOpenChannelInSharedPreference()
+ throws InterruptedException {
+ // Open a channel and not close it, by making CI.iccTransmitApduLogicalChannel throw.
+ int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+ doThrow(new RuntimeException()).when(mMockCi).iccTransmitApduLogicalChannel(
+ eq(channel), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), any(),
+ anyBoolean(), any());
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+ // Stub close channel
+ reset(mMockCi);
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+
+ // Call constructor
+ mSender = new ApduSender(InstrumentationRegistry.getContext(), PHONE_ID,
+ mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
+ mLooper.processAllMessages();
+
+ // The constructor should have closed channel
+ verify(mMockCi, times(0)).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
+ assertEquals(1, getChannelIdFromSharedPreferences());
+ }
+
+ @Test
+ public void testSend_OpenChannelFailedNoSuchElement_useChannelInSharedPreference() {
+ // Open a channel but not close, by making CI.iccTransmitApduLogicalChannel throw.
+ int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+ doThrow(new RuntimeException()).when(mMockCi).iccTransmitApduLogicalChannel(
+ eq(channel), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), any(),
+ anyBoolean(), any());
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+ reset(mMockCi);
+ // Constructor fails to close channel
+ LogicalChannelMocker.mockCloseLogicalChannel(
+ mMockCi, channel, new CommandException(RADIO_NOT_AVAILABLE));
+ mSender = new ApduSender(InstrumentationRegistry.getContext(), PHONE_ID,
+ mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
+ mLooper.processAllMessages();
+ reset(mMockCi);
+ // Stub open channel failure NO_SUCH_ELEMENT
+ LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi,
+ new CommandException(CommandException.Error.NO_SUCH_ELEMENT));
+ LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+
+ // open channel would fail, and send/close would succeed because of
+ // previous open response saved in sharedPref
+ InOrder inOrder = inOrder(mMockCi);
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel),
+ eq(channel | 10), eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testSend_euiccSession_shouldNotCloseChannel()
+ throws InterruptedException {
+ int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+ LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+ EuiccSession.get().startSession(SESSION_ID);
+
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+
+ assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
+ InOrder inOrder = inOrder(mMockCi);
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
+ eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ // No iccCloseLogicalChannel
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testSendTwice_euiccSession_shouldOpenChannelOnceNotCloseChannel()
+ throws InterruptedException {
+ int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+ LogicalChannelMocker.mockSendToLogicalChannel(
+ mMockCi, channel, "A1A1A19000", "A1A1A19000");
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+ EuiccSession.get().startSession(SESSION_ID);
+
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+
+ assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
+ InOrder inOrder = inOrder(mMockCi);
+ // iccOpenLogicalChannel once
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ // iccTransmitApduLogicalChannel twice
+ inOrder.verify(mMockCi, times(2)).iccTransmitApduLogicalChannel(eq(channel),
+ eq(channel | 10), eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ // No iccCloseLogicalChannel
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testSendTwice_thenEndSession() throws InterruptedException {
+ int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+ LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel,
+ "A1A1A19000", "A1A1A19000");
+ LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+ EuiccSession.get().startSession(SESSION_ID);
+
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+ mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+ 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+ mLooper.processAllMessages();
+ EuiccSession.get().endSession(SESSION_ID);
+ mLooper.processAllMessages();
+
+ assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
+ InOrder inOrder = inOrder(mMockCi);
+ // iccOpenLogicalChannel once
+ inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
+ // iccTransmitApduLogicalChannel twice
+ inOrder.verify(mMockCi, times(2)).iccTransmitApduLogicalChannel(eq(channel),
+ eq(channel | 10), eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
+ // iccCloseLogicalChannel once
+ inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
+ }
+
+ private int getChannelIdFromSharedPreferences() {
+ return PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getContext())
+ .getInt(SHARED_PREFS_KEY_CHANNEL_ID, -1);
+ }
+
+ private void clearSharedPreferences() {
+ PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getContext())
+ .edit()
+ .remove(SHARED_PREFS_KEY_CHANNEL_ID)
+ .remove(SHARED_PREFS_KEY_CHANNEL_RESPONSE)
+ .apply();
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
index 27f743f..e8aeed1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.uicc.euicc.apdu;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -30,7 +31,6 @@
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
-import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -48,13 +48,12 @@
int[] responseInts = isException ? null : getSelectResponse(responseObject.toString());
Throwable exception = isException ? (Throwable) responseObject : null;
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
doAnswer((Answer<Void>) invocation -> {
- Message msg = response.getValue();
+ Message msg = invocation.getArgument(2);
AsyncResult.forMessage(msg, responseInts, exception);
msg.sendToTarget();
return null;
- }).when(mockCi).iccOpenLogicalChannel(anyString(), anyInt(), response.capture());
+ }).when(mockCi).iccOpenLogicalChannel(anyString(), anyInt(), any());
return LOGICAL_CHANNEL;
}
@@ -64,22 +63,20 @@
*/
public static void mockSendToLogicalChannel(CommandsInterface mockCi, int channel,
Object... responseObjects) {
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
-
doAnswer(new Answer() {
private int mIndex = 0;
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
- Object responseObject = responseObjects[mIndex++];
- mockIccTransmitApduLogicalChannelResponse(response, responseObject);
+ Object response = responseObjects[mIndex++];
+ mockIccTransmitApduLogicalChannelResponse(invocation.getArgument(8), response);
return null;
}
}).when(mockCi).iccTransmitApduLogicalChannel(eq(channel), anyInt(), anyInt(), anyInt(),
- anyInt(), anyInt(), anyString(), anyBoolean(), response.capture());
+ anyInt(), anyInt(), anyString(), anyBoolean(), any());
}
- private static void mockIccTransmitApduLogicalChannelResponse(ArgumentCaptor<Message> response,
+ private static void mockIccTransmitApduLogicalChannelResponse(Message msg,
Object responseObject) throws Throwable {
boolean isException = responseObject instanceof Throwable;
@@ -95,20 +92,22 @@
IccIoResult result = isException ? null : new IccIoResult(sw1, sw2, hex);
Throwable exception = isException ? (Throwable) responseObject : null;
- Message msg = response.getValue();
AsyncResult.forMessage(msg, result, exception);
msg.sendToTarget();
}
- public static void mockCloseLogicalChannel(CommandsInterface mockCi, int channel) {
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
+ /**
+ * @param error can be {@code null} for a success response or an exception for a failure
+ */
+ public static void mockCloseLogicalChannel(
+ CommandsInterface mockCi, int channel, @Nullable Throwable error) {
doAnswer((Answer<Void>) invocation -> {
- Message msg = response.getValue();
- AsyncResult.forMessage(msg);
+ Message msg = invocation.getArgument(2);
+ AsyncResult.forMessage(msg, null, error);
msg.sendToTarget();
return null;
}).when(mockCi).iccCloseLogicalChannel(eq(channel),
- eq(true /*isEs10*/), response.capture());
+ eq(true /*isEs10*/), any());
}
private static int[] getSelectResponse(String responseHex) {