Merge "To notify the ueser "Use mobile data"" into main
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index 2809f79..550340f 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"
@@ -40,3 +39,15 @@
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
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index d956104..a993d51 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,23 @@
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
+ }
+}
+
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 1056ea3..d2401fe 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -126,3 +126,14 @@
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
+ }
+}
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 63f707f..905dc94 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -45,5 +45,5 @@
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: "335820374"
+ bug: "314321617"
}
\ No newline at end of file
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index f663de8..4806789 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -51,3 +51,14 @@
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..dc17a61 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -77,3 +77,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..f41fad3 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -58,3 +58,22 @@
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"
+}
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 48e7b0d..2010ce1 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;
diff --git a/src/java/com/android/internal/telephony/CarrierActionAgent.java b/src/java/com/android/internal/telephony/CarrierActionAgent.java
index 7bb89d0..c4ba77d 100644
--- a/src/java/com/android/internal/telephony/CarrierActionAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierActionAgent.java
@@ -258,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/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 9c7993b..da17f60 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
@@ -324,6 +320,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 e3bf40c..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()
@@ -515,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;
@@ -624,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);
+ }
+ }
}
/**
@@ -815,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/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 93a0c2f..6fe1232 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1119,6 +1119,7 @@
@Override
public GsmCdmaCall getForegroundCall() {
+ if (!hasCalling()) return null;
return mCT.mForegroundCall;
}
@@ -1396,6 +1397,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 +5497,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..c94480e 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -202,9 +202,9 @@
tracker.onSent(mContext);
mTrackers.remove(token);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
+ mSmsDispatchersController.notifySmsSent(
tracker.mDestAddress, tracker.mMessageId, true,
- tracker.isSinglePartOrLastPart());
+ 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 65d113d..37d8aa6 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -1069,7 +1069,7 @@
SmsBroadcastReceiver resultReceiver = tracker.getSmsBroadcastReceiver(this);
- if (!mUserManager.isUserUnlocked()) {
+ if (!isMainUserUnlocked()) {
log("processMessagePart: !isUserUnlocked; calling processMessagePartWithUserLocked. "
+ "Port: " + destPort, tracker.getMessageId());
return processMessagePartWithUserLocked(
@@ -1187,6 +1187,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.
@@ -1210,8 +1219,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) {
@@ -2129,6 +2145,7 @@
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);
if (userManager.isUserUnlocked()) {
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/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index aa62acb..14eed9c 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -4921,6 +4921,14 @@
}
/**
+ * @return The sms dispatchers controller
+ */
+ @Nullable
+ public SmsDispatchersController getSmsDispatchersController() {
+ return null;
+ }
+
+ /**
* @return The data settings manager
*/
@NonNull
@@ -5326,6 +5334,27 @@
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);
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index d9c5c9c..f7ce388 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;
@@ -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..3f388fb 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -156,4 +156,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/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8abebe2..de33753 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -4374,9 +4374,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 9bf9a50..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,21 +514,36 @@
/**
* 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);
@@ -534,6 +551,7 @@
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..3ae13f8 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -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;
@@ -1017,8 +1018,8 @@
*/
protected void notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker,
boolean isOverIms) {
- mSmsDispatchersController.notifySmsSentFailedToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, isOverIms);
+ mSmsDispatchersController.notifySmsSent(tracker.mDestAddress, tracker.mMessageId,
+ isOverIms, true /*isLastSmsPart*/, false /*success*/);
}
/**
@@ -1053,9 +1054,9 @@
}
tracker.onSent(mContext);
mPhone.notifySmsSent(tracker.mDestAddress);
- mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
+ mSmsDispatchersController.notifySmsSent(
tracker.mDestAddress, tracker.mMessageId, false,
- tracker.isSinglePartOrLastPart());
+ tracker.isSinglePartOrLastPart(), true /*success*/);
mPhone.getSmsStats().onOutgoingSms(
tracker.mImsRetry > 0 /* isOverIms */,
@@ -1398,15 +1399,16 @@
* 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) {
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);
@@ -1521,11 +1523,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);
}
/**
@@ -1630,10 +1633,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) {
Rlog.d(TAG, "sendText id: " + SmsController.formatCrossStackMessageId(messageId));
int messageRef = nextMessageRef();
SmsMessageBase.SubmitPduBase pdu = getSubmitPdu(
@@ -1641,8 +1644,8 @@
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);
@@ -1825,8 +1828,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) {
final String fullMessageText = getMultipartMessageText(parts);
int refNumber = getNextConcatenatedRef() & 0x00FF;
int encoding = SmsConstants.ENCODING_UNKNOWN;
@@ -1885,8 +1888,8 @@
}
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);
@@ -1920,9 +1923,9 @@
/**
* 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) {
@@ -1951,11 +1954,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);
} else {
Rlog.e(TAG, "CdmaSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -1969,11 +1972,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);
} else {
Rlog.e(TAG, "GsmSMSDispatcher.getNewSubmitPduTracker(): getSubmitPdu() returned "
+ "null " + SmsController.formatCrossStackMessageId(messageId));
@@ -2812,16 +2816,20 @@
}
}
- 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) {
+ 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 +2841,33 @@
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);
}
- 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) {
+ 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);
}
- 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) {
+ 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);
}
protected HashMap<String, Object> getSmsTrackerMap(String destAddr, String scAddr,
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 72c8cd3..e7500a2 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1164,6 +1164,9 @@
mDesiredPowerState = power;
setPowerStateToDesired(forEmergencyCall, isSelectedPhoneForEmergencyCall, forceApply);
+ if (mDesiredPowerState) {
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(true);
+ }
}
/**
@@ -1325,6 +1328,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
@@ -2803,8 +2812,10 @@
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)
@@ -2897,10 +2908,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
@@ -4979,7 +4988,7 @@
*/
public void powerOffRadioSafely() {
synchronized (this) {
- SatelliteController.getInstance().onCellularRadioPowerOffRequested();
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(false);
if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
EmergencyStateTracker.getInstance().onCellularRadioPowerOffRequested();
}
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/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index 0893b75..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.
*/
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 59184d8..1295f38 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);
@@ -261,6 +266,8 @@
if (callingPackage == null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendTextForSubscriber caller=" + callingPackage);
if (skipFdnCheck || skipShortCodeCheck) {
@@ -306,9 +313,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 +333,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 +351,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 +374,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 +395,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);
@@ -405,6 +415,8 @@
if (getCallingPackage() != null) {
callingPackage = getCallingPackage();
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendMultipartTextForSubscriber caller=" + callingPackage);
// Check if user is associated with the subscription
@@ -426,9 +438,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 +456,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 +477,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 +731,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 +739,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 +752,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 +761,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 +996,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 +1018,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 568cf66..7795955 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,6 +63,8 @@
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;
@@ -115,6 +119,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,7 +215,7 @@
};
/** 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;
@@ -214,6 +224,7 @@
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;
@@ -232,15 +243,16 @@
public final long messageId;
public final boolean skipShortCodeCheck;
- 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;
@@ -386,7 +398,7 @@
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 +537,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 +818,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 +867,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.mDestAddress, tracker.mMessageId,
+ !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
return;
}
String scAddr = (String) map.get("scAddr");
@@ -842,8 +876,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.mDestAddress, tracker.mMessageId,
+ !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
return;
}
@@ -884,8 +918,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.mDestAddress, tracker.mMessageId,
+ !retryUsingImsService, true /*isLastSmsPart*/, false /*success*/);
return;
}
// replace old smsc and pdu with newly encoded ones
@@ -1178,36 +1212,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 String destAddr, long messageId, boolean isOverIms,
+ boolean isLastSmsPart, boolean success) {
+ notifySmsSentToEmergencyStateTracker(
+ destAddr, messageId, isOverIms, isLastSmsPart, success);
+ notifySmsSentToDatagramDispatcher(messageId, 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()) {
+ DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
}
}
@@ -1367,17 +1400,17 @@
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);
} 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);
} 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);
}
}
@@ -1394,22 +1427,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);
} 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);
} 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);
}
}
}
@@ -1427,19 +1463,22 @@
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);
} 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);
} 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);
}
}
}
@@ -1546,31 +1585,33 @@
* 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);
} else if (isCdmaMo()) {
- mCdmaDispatcher.sendData(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
- deliveryIntent, isForVvm);
+ mCdmaDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
+ sentIntent, deliveryIntent, isForVvm);
} else {
- mGsmDispatcher.sendData(callingPackage, destAddr, scAddr, destPort, data, sentIntent,
- deliveryIntent, isForVvm);
+ mGsmDispatcher.sendData(callingPackage, callingUser, destAddr, scAddr, destPort, data,
+ sentIntent, deliveryIntent, isForVvm);
}
}
@@ -1672,11 +1713,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 +1820,61 @@
* @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()) {
+ // 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);
+ 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);
} 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);
} 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);
}
}
}
@@ -1922,37 +1986,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()) {
+ // 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);
} 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);
} 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);
}
}
}
@@ -2081,6 +2163,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/TelephonyCountryDetector.java b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
index 56e8b46..b604431 100644
--- a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
+++ b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
@@ -35,6 +35,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 +43,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 +85,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 +110,10 @@
private Map<String, Long> mOverriddenCachedNetworkCountryCodes = new HashMap<>();
@GuardedBy("mLock")
private boolean mIsCountryCodesOverridden = false;
+ private final RegistrantList mCountryCodeChangedRegistrants = new RegistrantList();
+
+ 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();
+ break;
case EVENT_LOCATION_UPDATE_REQUEST_QUOTA_RESET:
evaluateRequestingLocationUpdates();
break;
@@ -468,6 +482,17 @@
}
}
evaluateRequestingLocationUpdates();
+ if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("mCountryCodeChangedRegistrants.notifyRegistrants()");
+ mCountryCodeChangedRegistrants.notifyRegistrants();
+ } else {
+ logd("mCountryCodeChangedRegistrants.notifyRegistrants() is not called");
+ }
+ }
+
+ private void handleEventWifiConnectivityStateChanged() {
+ mWifiConnectivityStateChangedRegistrantList.notifyResult(isWifiNetworkConnected());
+ evaluateRequestingLocationUpdates();
}
private void setLocationCountryCode(@NonNull Pair<String, Long> countryCodeInfo) {
@@ -543,6 +568,25 @@
}
/**
+ * 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);
+ }
+
+ /**
* Check whether this is a valid country code.
*
* @param countryCode A 2-Character alphanumeric country code.
@@ -558,6 +602,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/cdnr/CarrierDisplayNameResolver.java b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
index 4b5eebc..30e5aa1 100644
--- a/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
+++ b/src/java/com/android/internal/telephony/cdnr/CarrierDisplayNameResolver.java
@@ -477,7 +477,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/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index d9ddde0..89b0fec 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -643,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);
}
@@ -761,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;
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index eaa0962..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;
@@ -591,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
@@ -676,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 =
@@ -815,6 +830,12 @@
private PreciseDataConnectionState mPreciseDataConnectionState;
/**
+ * Callback to listen event from {@link PhoneSwitcher}.
+ */
+ @NonNull
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
+ /**
* The network bandwidth.
*/
public static class NetworkBandwidth {
@@ -1027,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
@@ -1156,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,
@@ -1225,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(),
@@ -1266,21 +1310,19 @@
getHandler(), EVENT_VOICE_CALL_ENDED, null);
}
- if (mFlags.forceIwlanMms()) {
- 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.
@@ -1292,7 +1334,7 @@
@Override
public void exit() {
logv("Unregistering all events.");
- if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) {
+ if (mAccessNetworksManagerCallback != null) {
mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
}
@@ -1318,6 +1360,9 @@
mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler());
mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(
getHandler());
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcher.unregisterCallback(mPhoneSwitcherCallback);
+ }
mDataNetworkController.getDataSettingsManager()
.unregisterCallback(mDataSettingsManagerCallback);
mRil.unregisterForPcoData(getHandler());
@@ -1351,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: {
@@ -1428,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;
@@ -2355,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);
@@ -2490,8 +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)) {
+ 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.
@@ -3314,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.
@@ -3323,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);
}
}
@@ -3360,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)
@@ -4055,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 30172db..89153ab 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);
}
@@ -2647,7 +2678,7 @@
.unregisterImsRegistrationCallback(oldCallback);
}
log("Successfully unregistered " + DataUtils.imsFeatureToString(imsFeature)
- + " registration state. sudId=" + subId);
+ + " registration state. subId=" + subId);
mImsFeatureRegistrationCallbacks.remove(imsFeature);
}
}
@@ -2658,42 +2689,46 @@
* @param subId Subscription index.
*/
private void registerImsStateCallback(int subId) {
- Function<Integer, ImsStateCallback> imsFeatureStateCallbackFactory =
- imsFeature -> new ImsStateCallback() {
- @Override
- public void onUnavailable(int reason) {
- // Unregister registration state update when IMS service is unbound.
- unregisterImsFeatureRegistrationState(subId, imsFeature);
- }
+ if (isImsSupportedOnDevice()) {
+ Function<Integer, ImsStateCallback> imsFeatureStateCallbackFactory =
+ imsFeature -> new ImsStateCallback() {
+ @Override
+ public void onUnavailable(int reason) {
+ // Unregister registration state update when IMS service is unbound.
+ unregisterImsFeatureRegistrationState(subId, imsFeature);
+ }
- @Override
- public void onAvailable() {
- mImsFeaturePackageName.put(imsFeature, ImsResolver.getInstance()
- .getConfiguredImsServicePackageName(mPhone.getPhoneId(),
- imsFeature));
- // Once IMS service is bound, register for registration state update.
- registerImsFeatureRegistrationState(subId, imsFeature);
- }
+ @Override
+ public void onAvailable() {
+ mImsFeaturePackageName.put(imsFeature, ImsResolver.getInstance()
+ .getConfiguredImsServicePackageName(mPhone.getPhoneId(),
+ imsFeature));
+ // Once IMS service is bound, register for registration state update.
+ registerImsFeatureRegistrationState(subId, imsFeature);
+ }
- @Override
- public void onError() {
- }
- };
+ @Override
+ public void onError() {
+ }
+ };
- try {
- ImsStateCallback callback = imsFeatureStateCallbackFactory
- .apply(ImsFeature.FEATURE_MMTEL);
- mImsManager.getImsMmTelManager(subId).registerImsStateCallback(this::post,
- callback);
- mImsStateCallbacks.put(ImsFeature.FEATURE_MMTEL, callback);
- log("Successfully register MMTEL state on sub " + subId);
+ try {
+ ImsStateCallback callback = imsFeatureStateCallbackFactory
+ .apply(ImsFeature.FEATURE_MMTEL);
+ mImsManager.getImsMmTelManager(subId).registerImsStateCallback(this::post,
+ callback);
+ mImsStateCallbacks.put(ImsFeature.FEATURE_MMTEL, callback);
+ log("Successfully register MMTEL state on sub " + subId);
- callback = imsFeatureStateCallbackFactory.apply(ImsFeature.FEATURE_RCS);
- mImsManager.getImsRcsManager(subId).registerImsStateCallback(this::post, callback);
- mImsStateCallbacks.put(ImsFeature.FEATURE_RCS, callback);
- log("Successfully register RCS state on sub " + subId);
- } catch (ImsException e) {
- loge("Exception when registering IMS state callback. " + e);
+ callback = imsFeatureStateCallbackFactory.apply(ImsFeature.FEATURE_RCS);
+ mImsManager.getImsRcsManager(subId).registerImsStateCallback(this::post, callback);
+ mImsStateCallbacks.put(ImsFeature.FEATURE_RCS, callback);
+ log("Successfully register RCS state on sub " + subId);
+ } catch (ImsException e) {
+ loge("Exception when registering IMS state callback. " + e);
+ }
+ } else {
+ log("IMS is not supported on this device, skipping registerImsStateCallback");
}
}
@@ -2703,21 +2738,33 @@
* @param subId Subscription index.
*/
private void unregisterImsStateCallbacks(int subId) {
- ImsStateCallback callback = mImsStateCallbacks.get(ImsFeature.FEATURE_MMTEL);
- if (callback != null) {
- mImsManager.getImsMmTelManager(subId).unregisterImsStateCallback(callback);
- mImsStateCallbacks.remove(ImsFeature.FEATURE_MMTEL);
- log("Unregister MMTEL state on sub " + subId);
- }
+ if (isImsSupportedOnDevice()) {
+ ImsStateCallback callback = mImsStateCallbacks.get(ImsFeature.FEATURE_MMTEL);
+ if (callback != null) {
+ mImsManager.getImsMmTelManager(subId).unregisterImsStateCallback(callback);
+ mImsStateCallbacks.remove(ImsFeature.FEATURE_MMTEL);
+ log("Unregister MMTEL state on sub " + subId);
+ }
- callback = mImsStateCallbacks.get(ImsFeature.FEATURE_RCS);
- if (callback != null) {
- mImsManager.getImsRcsManager(subId).unregisterImsStateCallback(callback);
- mImsStateCallbacks.remove(ImsFeature.FEATURE_RCS);
- log("Unregister RCS state on sub " + subId);
+ callback = mImsStateCallbacks.get(ImsFeature.FEATURE_RCS);
+ if (callback != null) {
+ mImsManager.getImsRcsManager(subId).unregisterImsStateCallback(callback);
+ mImsStateCallbacks.remove(ImsFeature.FEATURE_RCS);
+ log("Unregister RCS state on sub " + subId);
+ }
+ } else {
+ log("IMS is not supported on this device, skipping unregisterImsStateCallbacks");
}
}
+ /**
+ * called to check if FEATURE_TELEPHONY_IMS feature is available
+ */
+ private boolean isImsSupportedOnDevice() {
+ return mPhone.getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS);
+ }
+
/** Called when subscription info changed. */
private void onSubscriptionChanged() {
if (mSubId != mPhone.getSubId()) {
@@ -2853,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.");
@@ -3125,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) {
@@ -3593,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/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 27b4331..1005bb7 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.
@@ -1562,6 +1609,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 +2031,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/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 167062f..f983108 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -1661,7 +1661,8 @@
return phone.getServiceStateTracker().isRadioOn()
&& !satelliteController.isSatelliteEnabled();
}
- }, !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..0d1b625 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,7 +102,8 @@
mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall
&& phone == phoneForEmergencyCall, timeoutCallbackInterval);
}
- powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber);
+ powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber,
+ forNormalRoutingEmergencyCall);
if (SatelliteController.getInstance().isSatelliteEnabled()) {
powerOffSatellite(phoneForEmergencyCall);
}
@@ -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);
}
}
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index fa0610a..c448057 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -148,6 +148,11 @@
public void onSatelliteModemStateChanged(int state) {
mHandler.obtainMessage(MSG_SATELLITE_ENABLED_CHANGED).sendToTarget();
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ Rlog.d(TAG, "onEmergencyModeChanged: ignored " + isEmergency);
+ }
};
private Callback mCallback; // The callback to notify upon completion.
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 1a5b99e..59bc980 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -837,7 +837,7 @@
subscription,
switchAfterDownload,
forceDeactivateSim,
- resolvedBundle,
+ addCallingPackageToBundle(resolvedBundle, callingPackage),
new EuiccConnector.DownloadCommandCallback() {
@Override
public void onDownloadComplete(DownloadSubscriptionResult result) {
@@ -936,6 +936,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}.
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index b2966b6..1b2aee0 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -3268,6 +3268,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;
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index a83cd06..2367ef5 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);
}
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/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 2c9463f..f5d301a 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;
@@ -42,7 +45,9 @@
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 +74,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;
@@ -89,7 +96,7 @@
private long mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
@GuardedBy("mLock")
- private boolean mSendingDatagramInProgress;
+ private boolean mSendingInProgress;
/**
* Map key: datagramId, value: SendSatelliteDatagramArgument to retry sending emergency
@@ -107,6 +114,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 +178,7 @@
}
synchronized (mLock) {
- mSendingDatagramInProgress = false;
+ mSendingInProgress = false;
}
mWaitTimeForDatagramSendingResponse = getWaitForDatagramSendingResponseTimeoutMillis();
mWaitTimeForDatagramSendingForLastMessageResponse =
@@ -289,7 +303,7 @@
}
stopWaitForDatagramSendingResponseTimer();
- mSendingDatagramInProgress = false;
+ mSendingInProgress = false;
// Log metrics about the outgoing datagram
reportSendDatagramCompleted(argument, error);
@@ -304,20 +318,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 +355,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 +364,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 +442,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 +544,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 +581,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 +595,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 +644,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 +671,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) {
@@ -671,13 +757,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,12 +771,12 @@
@GuardedBy("mLock")
private void cleanUpResources() {
plogd("cleanUpResources");
- mSendingDatagramInProgress = false;
- if (getPendingDatagramCount() > 0) {
+ mSendingInProgress = false;
+ if (getPendingMessagesCount() > 0) {
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
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,
mLastSendRequestDatagramType,
@@ -710,15 +796,15 @@
}
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,17 +847,17 @@
}
private void handleEventDatagramWaitForConnectedStateTimedOut(
- @NonNull SendSatelliteDatagramArgument argument) {
+ @SatelliteManager.DatagramType int datagramType) {
plogw("Timed out to wait for satellite connected before sending datagrams");
synchronized (mLock) {
// Update send status
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- argument.datagramType,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
- getPendingDatagramCount(),
+ getPendingMessagesCount(),
SATELLITE_RESULT_NOT_REACHABLE);
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- argument.datagramType,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
@@ -827,12 +913,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 +1020,176 @@
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) {
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendSms: satellitePhone is null.");
+ return;
+ }
+
+ SatelliteController.getInstance().startPointingUI();
+
+ int subId = satellitePhone.getSubId();
+ long messageId = pendingSms.messageId;
+ 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;
+ }
+
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendPendingSms: satellitePhone is null.");
+ return;
+ }
+ int subId = satellitePhone.getSubId();
+
+ 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/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 3b15cfd..0f56973 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -17,7 +17,12 @@
package com.android.internal.telephony.satellite;
import static android.provider.Settings.ACTION_SATELLITE_SETTING;
+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;
@@ -25,6 +30,8 @@
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_NIDD_APN_NAME_STRING;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.SubscriptionManager.isValidSubscriptionId;
@@ -74,6 +81,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;
@@ -85,6 +93,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;
@@ -103,10 +112,13 @@
import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
-import android.telephony.satellite.ProvisionSubscriberId;
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.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -121,6 +133,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;
@@ -209,7 +222,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;
@@ -227,8 +239,12 @@
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 EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43;
- private static final int CMD_PROVISION_SATELLITE_TOKEN_UPDATED = 44;
- private static final int EVENT_PROVISION_SATELLITE_TOKEN_UPDATED = 45;
+ 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;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -242,9 +258,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();
@@ -276,8 +299,6 @@
private boolean mWaitingForDisableSatelliteModemResponse = false;
private boolean mWaitingForSatelliteModemOff = false;
- private final AtomicBoolean mRegisteredForProvisionStateChangedWithSatelliteService =
- new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForPendingDatagramCountWithSatelliteService =
new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteModemStateChangedWithSatelliteService =
@@ -327,12 +348,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();
@@ -391,6 +418,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<>();
@@ -442,6 +480,9 @@
// key : priority, low value is high, value : List<SubscriptionInfo>
@GuardedBy("mSatelliteTokenProvisionedLock")
private Map<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new HashMap<>();
+ // The last ICC ID that framework configured to modem.
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ private String mLastConfiguredIccId;
@NonNull private final Object mSatelliteTokenProvisionedLock = new Object();
private long mWaitTimeForSatelliteEnablingResponse;
private long mDemoPointingAlignedDurationMillis;
@@ -471,6 +512,13 @@
// 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;
/**
* @return The singleton instance of SatelliteController.
@@ -522,6 +570,10 @@
// 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.
@@ -546,7 +598,6 @@
mIsRadioOn = phone.isRadioOn();
}
- registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForServiceStateChanged();
@@ -984,11 +1035,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;
}
@@ -1007,11 +1059,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;
}
@@ -1282,6 +1336,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;
+ }
+ }
}
}
@@ -1308,8 +1370,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;
}
@@ -1318,15 +1382,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() {
@@ -1508,51 +1563,103 @@
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 EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION: {
evaluateESOSProfilesPrioritization();
break;
}
- case CMD_PROVISION_SATELLITE_TOKEN_UPDATED: {
+ case CMD_UPDATE_PROVISION_SATELLITE_TOKEN: {
request = (SatelliteControllerHandlerRequest) msg.obj;
RequestProvisionSatelliteArgument argument =
(RequestProvisionSatelliteArgument) request.argument;
- onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_TOKEN_UPDATED, request);
+ onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request);
// only pass to index 0.
+ // TODO: Select the subscription with highest priority and set it to mSatelliteSubId
int subId = -1;
synchronized (mSatelliteTokenProvisionedLock) {
subId = mSubscriberIdPerSub.getOrDefault(
- argument.mProvisionSubscriberIdList.get(0).getSubscriberId(), -1);
+ argument.mSatelliteSubscriberInfoList.get(0).getSubscriberId(), -1);
}
+ setSatellitePhone(subId);
String iccId = mSubscriptionManagerService.getSubscriptionInfo(subId).getIccId();
- logd("CMD_PROVISION_SATELLITE_TOKEN_UPDATED: subId=" + subId + ", iccId=" + iccId);
- mSatelliteModemInterface.updateSatelliteSubscription(iccId, onCompleted);
- Consumer<Integer> result = new Consumer<Integer>() {
- @Override
- public void accept(Integer integer) {
- logd("invoke CMD_PROVISION_SATELLITE_TOKEN_UPDATED done.");
+ argument.setIccId(iccId);
+ boolean sendResponse = false;
+ synchronized (mSatelliteTokenProvisionedLock) {
+ if (!iccId.equals(mLastConfiguredIccId)) {
+ logd("updateSatelliteSubscription subId=" + subId + ", iccId=" + iccId
+ + " to modem");
+ mSatelliteModemInterface.updateSatelliteSubscription(iccId, onCompleted);
+ } else {
+ sendResponse = true;
}
- };
- ProvisionSatelliteServiceArgument internalArgument =
- new ProvisionSatelliteServiceArgument(iccId, null, result, subId);
- sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE, internalArgument, null);
+ }
+ handleEventSatelliteSubscriptionProvisionStateChanged(
+ argument.mSatelliteSubscriberInfoList, true);
+ if (sendResponse) {
+ // The response is sent immediately because the ICCID has already been
+ // delivered to the modem.
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS, true);
+ argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
break;
}
- case EVENT_PROVISION_SATELLITE_TOKEN_UPDATED: {
+ 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");
- logd("EVENT_PROVISION_SATELLITE_TOKEN_UPDATED =" + error);
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ mLastConfiguredIccId = argument.getIccId();
+ }
+ }
+ logd("updateSatelliteSubscription result=" + error);
Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS, true);
- argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ bundle.putBoolean(SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS,
+ error == SATELLITE_RESULT_SUCCESS);
+ argument.mResult.send(error, bundle);
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;
+ }
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1561,18 +1668,27 @@
}
private static final class RequestProvisionSatelliteArgument {
- public List<ProvisionSubscriberId> mProvisionSubscriberIdList;
+ public List<SatelliteSubscriberInfo> mSatelliteSubscriberInfoList;
@NonNull
public ResultReceiver mResult;
public long mRequestId;
+ public String mIccId;
- RequestProvisionSatelliteArgument(List<ProvisionSubscriberId> provisionSubscriberIdList,
+ RequestProvisionSatelliteArgument(List<SatelliteSubscriberInfo> satelliteSubscriberInfoList,
ResultReceiver result) {
- this.mProvisionSubscriberIdList = provisionSubscriberIdList;
+ this.mSatelliteSubscriberInfoList = satelliteSubscriberInfoList;
this.mResult = result;
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() {
@@ -1625,6 +1741,19 @@
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 */
@@ -1976,12 +2105,7 @@
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;
}
@@ -2008,6 +2132,18 @@
}
mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback);
+
+ boolean isProvisioned = Boolean.TRUE.equals(isSatelliteViaOemProvisioned());
+ try {
+ callback.onSatelliteProvisionStateChanged(isProvisioned);
+ } catch (RemoteException ex) {
+ loge("setSatelliteServicePackageName: " + ex);
+ }
+ synchronized (mSatelliteViaOemProvisionLock) {
+ plogd("registerForSatelliteProvisionStateChanged: report current provisioned "
+ + "state, state=" + isProvisioned);
+ }
+
return SATELLITE_RESULT_SUCCESS;
}
@@ -2397,6 +2533,15 @@
int error = evaluateOemSatelliteRequestAllowed(true);
if (error == SATELLITE_RESULT_SUCCESS) {
mNtnSignalStrengthChangedListeners.put(callback.asBinder(), callback);
+ synchronized (mNtnSignalsStrengthLock) {
+ try {
+ callback.onNtnSignalStrengthChanged(mNtnSignalStrength);
+ plogd("registerForNtnSignalStrengthChanged: " + mNtnSignalStrength);
+ } catch (RemoteException ex) {
+ ploge("registerForNtnSignalStrengthChanged: RemoteException ex="
+ + ex);
+ }
+ }
} else {
throw new RemoteException(new IllegalStateException("registration fails: " + error));
}
@@ -2500,26 +2645,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;
@@ -2784,27 +2931,50 @@
/**
* 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(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ 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();
+ }
}
/**
@@ -3068,6 +3238,31 @@
}
/**
+ * @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;
+ }
+
+ return true;
+ }
+
+ /**
* Return capabilities of carrier roaming satellite network.
*
* @param phone phone object
@@ -3375,38 +3570,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.
*/
@@ -3421,16 +3584,13 @@
if (mIsSatelliteViaOemProvisioned != null) {
return mIsSatelliteViaOemProvisioned;
}
- }
- requestIsSatelliteProvisioned(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- plogd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
- }
- });
- return null;
+ if (mIsSatelliteViaOemProvisioned == null) {
+ mIsSatelliteViaOemProvisioned = getPersistedOemEnabledSatelliteProvisionStatus();
+ }
+
+ return mIsSatelliteViaOemProvisioned;
+ }
}
private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) {
@@ -3451,8 +3611,9 @@
}
Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
- mSatelliteModemInterface.requestSatelliteEnabled(argument.enableSatellite,
- argument.enableDemoMode, argument.isEmergency, onCompleted);
+ mSatelliteModemInterface.requestSatelliteEnabled(
+ createModemEnableRequest(argument),
+ onCompleted);
startWaitForSatelliteEnablingResponseTimer(argument);
// Logs satellite session timestamps for session metrics
if (argument.enableSatellite) {
@@ -3461,6 +3622,21 @@
mSessionProcessingTimeStamp = System.currentTimeMillis();
}
+ /** Get the request attributes that modem needs to enable/disable satellite */
+ private SatelliteModemEnableRequestAttributes createModemEnableRequest(
+ @NonNull RequestSatelliteEnabledArgument arg) {
+ int subId = mSubscriptionManagerService.getDefaultSubId();
+ synchronized (mSatellitePhoneLock) {
+ if (mSatellitePhone != null) subId = mSatellitePhone.getSubId();
+ }
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ String iccid = subInfo != null ? 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 =
@@ -3486,7 +3662,6 @@
+ "changed to " + supported);
if (supported) {
- registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForNtnSignalStrengthChanged();
@@ -3535,16 +3710,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()) {
@@ -3627,6 +3792,48 @@
});
}
+ private void handleEventSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberInfo> newList, boolean provisioned) {
+ logd("handleEventSatelliteSubscriptionProvisionStateChanged: newList=" + 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);
+ }
+ }
+ if (!provisionChanged) {
+ logd("handleEventSatelliteSubscriptionProvisionStateChanged: provision state nothing "
+ + "changed.");
+ return;
+ }
+ List<SatelliteSubscriberProvisionStatus> informList =
+ getPrioritizedSatelliteSubscriberProvisionStatusList();
+ plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
+ notifySatelliteSubscriptionProvisionStateChanged(informList);
+ }
+
+ 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);
@@ -3897,6 +4104,9 @@
&& mWaitingForRadioDisabled) {
plogd("Sending success to callback that sent enable satellite request");
mIsEmergency = mSatelliteEnabledRequest.isEmergency;
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onEmergencyModeChanged(mIsEmergency);
+ }
synchronized (mIsSatelliteEnabledLock) {
mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite;
}
@@ -3904,6 +4114,13 @@
updateSatelliteEnabledState(
mSatelliteEnabledRequest.enableSatellite,
"EVENT_SET_SATELLITE_ENABLED_DONE");
+ if (mSatelliteEnabledRequest.enableSatellite
+ && !mSatelliteEnabledRequest.isEmergency) {
+ plogd("Starting pointingUI needFullscreenPointingUI=" + true
+ + "mIsDemoModeEnabled=" + mIsDemoModeEnabled + ", isEmergency="
+ + mSatelliteEnabledRequest.isEmergency);
+ mPointingAppController.startPointingUI(true, mIsDemoModeEnabled, false);
+ }
mSatelliteEnabledRequest = null;
mWaitingForRadioDisabled = false;
}
@@ -3926,6 +4143,9 @@
setDemoModeEnabled(false);
handlePersistentLoggingOnSessionEnd(mIsEmergency);
mIsEmergency = false;
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onEmergencyModeChanged(mIsEmergency);
+ }
mIsSatelliteEnabled = false;
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
@@ -4106,7 +4326,13 @@
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_ESOS_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_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT
+ );
}
if (config == null || config.isEmpty()) {
config = CarrierConfigManager.getDefaultConfig();
@@ -4129,6 +4355,7 @@
updateSupportedSatelliteServicesForActiveSubscriptions();
processNewCarrierConfigData(subId);
resetCarrierRoamingSatelliteModeParams(subId);
+ handleStateChangedForCarrierRoamingNtnEligibility();
sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
TimeUnit.MINUTES.toMillis(1));
}
@@ -4235,6 +4462,19 @@
.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
}
+ private boolean isSatelliteEsosSupported(int subId) {
+ return getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ESOS_SUPPORTED_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}.
@@ -4486,6 +4726,7 @@
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteProvisioned) {
+ plogd("evaluateOemSatelliteRequestAllowed: satellite service is not provisioned");
return SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
}
}
@@ -4529,8 +4770,8 @@
}
private void handleEventServiceStateChanged() {
+ handleStateChangedForCarrierRoamingNtnEligibility();
handleServiceStateForSatelliteConnectionViaCarrier();
- determineSystemNotification();
}
private void handleServiceStateForSatelliteConnectionViaCarrier() {
@@ -4591,6 +4832,7 @@
updateLastNotifiedNtnModeAndNotify(phone);
}
}
+ determineAutoConnectSystemNotification();
}
private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) {
@@ -4634,37 +4876,164 @@
}
}
+ 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 = mSatellitePhone.getSubId();
+ 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;
+ }
+
+ 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(mSatellitePhone.getSubId(),
+ 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.getOemBasedNonTerrestrialSubscriptionId(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.getOemBasedNonTerrestrialSubscriptionId(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);
+ }
}
}
}
@@ -4685,31 +5054,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() {
@@ -4717,6 +5068,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) {
@@ -4889,7 +5266,7 @@
return true;
}
- private void determineSystemNotification() {
+ private void determineAutoConnectSystemNotification() {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("determineSystemNotification: carrierEnabledSatelliteFlag is disabled");
return;
@@ -4910,15 +5287,32 @@
return;
}
if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) {
- showSatelliteSystemNotification(isNtn.second);
+ updateSatelliteSystemNotification(isNtn.second,
+ CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC,
+ /*visible*/ true);
mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY,
true).apply();
}
}
}
- private void showSatelliteSystemNotification(int subId) {
- plogd("showSatelliteSystemNotification");
+ /**
+ * 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,
@@ -4927,15 +5321,30 @@
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))
@@ -5005,8 +5414,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) {
@@ -5068,12 +5484,15 @@
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()) {
+ if (nri.isInService() || nri.isEmergencyEnabled()) {
logv("getWwanIsInService: return true");
return true;
}
@@ -5243,14 +5662,20 @@
// The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
// subscriberId is the Imsi prefix 6 digit + phone number.
- private @NonNull String getSubscriberId(SubscriptionInfo info) {
+ private Pair<String, Integer> getSubscriberIdAndType(SubscriptionInfo info) {
+ String subscriberId = "";
+ @SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
+ SatelliteSubscriberInfo.ICCID;
if (info.isSatelliteESOSSupported()) {
- return getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
}
if (info.isOnlyNonTerrestrialNetwork()) {
- return info.getIccId();
+ subscriberId = info.getIccId();
}
- return "";
+ logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
+ + subscriberIdType);
+ return new Pair<>(subscriberId, subscriberIdType);
}
private String getPhoneNumberBasedCarrier(int subId) {
@@ -5258,8 +5683,11 @@
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 "";
@@ -5322,73 +5750,82 @@
* @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 requestProvisionSubscriberIds(@NonNull ResultReceiver result) {
+ public void requestSatelliteSubscriberProvisionStatus(@NonNull ResultReceiver result) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
return;
}
-
- List<ProvisionSubscriberId> list = new ArrayList<>();
- synchronized (mSatelliteTokenProvisionedLock) {
- mSubscriberIdPerSub = new HashMap<>();
- for (int priority : mSubsInfoListPerPriority.keySet()) {
- List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
- if (infoList == null) {
- logd("requestProvisionSubscriberIds: no exist this priority " + priority);
- continue;
- }
- for (SubscriptionInfo info : infoList) {
- String subscriberId = getSubscriberId(info);
- int carrierId = info.getCarrierId();
- logd("requestProvisionSubscriberIds: subscriberId:" + subscriberId
- + " , carrierId=" + carrierId);
- if (subscriberId.isEmpty()) {
- logd("requestProvisionSubscriberIds: getSubscriberId failed skip this "
- + "subscriberId.");
- continue;
- }
- list.add(new ProvisionSubscriberId(subscriberId, carrierId, ""));
- mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId());
- }
- }
- }
-
- logd("requestProvisionSubscriberIds: " + list);
+ 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);
}
- /**
- * Request to get provisioned status for given a satellite subscriber id.
- *
- * @param satelliteSubscriberId Satellite subscriber id requiring provisioned status check.
- * @param result The result receiver, which returns the provisioned status of the token if the
- * request is successful or an error code if the request failed.
- */
- public void requestIsProvisioned(@NonNull String satelliteSubscriberId,
- @NonNull ResultReceiver result) {
- if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
- return;
- }
- if (satelliteSubscriberId.isEmpty()) {
- result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
- return;
- }
-
- boolean isProvisioned = false;
+ private List<SatelliteSubscriberProvisionStatus>
+ getPrioritizedSatelliteSubscriberProvisionStatusList() {
+ List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
synchronized (mSatelliteTokenProvisionedLock) {
- if (mProvisionedSubscriberId.getOrDefault(satelliteSubscriberId, false)) {
- isProvisioned = true;
+ 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;
+ }
- logd("requestIsProvisioned: satelliteSubscriberId=" + satelliteSubscriberId
- + " , isProvisioned=" + isProvisioned);
- final Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_IS_SATELLITE_PROVISIONED, isProvisioned);
- result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ @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);
+ }
}
/**
@@ -5397,7 +5834,7 @@
* @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<ProvisionSubscriberId> list,
+ public void provisionSatellite(@NonNull List<SatelliteSubscriberInfo> list,
@NonNull ResultReceiver result) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
@@ -5409,14 +5846,180 @@
}
logd("provisionSatellite:" + list);
- for (ProvisionSubscriberId subscriberId : list) {
- synchronized (mSatelliteTokenProvisionedLock) {
- mProvisionedSubscriberId.put(subscriberId.getSubscriberId(), true);
+ RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
+ result);
+ 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);
+ }
+ }
+
+ /**
+ * 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 (!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 (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;
}
}
- RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
- result);
- sendRequestAsync(CMD_PROVISION_SATELLITE_TOKEN_UPDATED, request, null);
+ 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;
+ }
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index f0a96c2..d644cc1 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 =
@@ -113,11 +112,6 @@
}
@Override
- public void onSatelliteProvisionStateChanged(boolean provisioned) {
- mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned);
- }
-
- @Override
public void onSatelliteDatagramReceived(
android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
if (notifyResultIfExpectedListener()) {
@@ -403,27 +397,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.
@@ -682,17 +655,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 +861,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.
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index c75c001..f24d484 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -45,10 +45,7 @@
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.telecom.Connection;
-import android.telephony.AccessNetworkConstants;
-import android.telephony.CellIdentity;
import android.telephony.DropBoxManagerLoggerBackend;
-import android.telephony.NetworkRegistrationInfo;
import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.ServiceState;
@@ -59,6 +56,7 @@
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;
@@ -71,6 +69,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SmsApplication;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.SatelliteStats;
import java.util.List;
@@ -161,6 +160,13 @@
plogd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscriberProvisionStatus) {
+ plogd("onSatelliteSubscriptionProvisionStateChanged: "
+ + satelliteSubscriberProvisionStatus);
+ }
};
}
@@ -300,7 +306,8 @@
updateSatelliteViaCarrierAvailability();
boolean isDialerNotified = false;
- if (!isCellularAvailable()
+ boolean isCellularAvailable = SatelliteServiceUtils.isCellularAvailable();
+ if (!isCellularAvailable
&& isSatelliteAllowed()
&& (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
&& shouldTrackCall(mEmergencyConnection.getState())) {
@@ -312,7 +319,7 @@
}
plogd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
- + ", isCellularAvailable=" + isCellularAvailable()
+ + ", isCellularAvailable=" + isCellularAvailable
+ ", isSatelliteAllowed=" + isSatelliteAllowed()
+ ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
reportEsosRecommenderDecision(isDialerNotified);
@@ -451,57 +458,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;
- }
-
- /** Check whether device is connected to satellite PLMN */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
- List<String> satellitePlmnList =
- mSatelliteController.getSatellitePlmnsForCarrier(subId);
- if (satellitePlmnList.isEmpty()) {
- plogd("isSatellitePlmn: satellitePlmnList is empty");
- return false;
- }
-
- for (NetworkRegistrationInfo nri :
- serviceState.getNetworkRegistrationInfoListForTransportType(
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
- String registeredPlmn = nri.getRegisteredPlmn();
- if (TextUtils.isEmpty(registeredPlmn)) {
- plogd("isSatellitePlmn: registeredPlmn is empty");
- continue;
- }
-
- String mccmnc = getMccMnc(nri);
- for (String satellitePlmn : satellitePlmnList) {
- if (TextUtils.equals(satellitePlmn, registeredPlmn)
- || TextUtils.equals(satellitePlmn, mccmnc)) {
- plogd("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
- + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
- return true;
- }
- }
- }
-
- plogd("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
@@ -533,7 +489,7 @@
}
private synchronized void handleStateChangedEventForHysteresisTimer() {
- if (!isCellularAvailable() && mEmergencyConnection != null) {
+ if (!SatelliteServiceUtils.isCellularAvailable() && mEmergencyConnection != null) {
startTimer();
} else {
logv("handleStateChangedEventForHysteresisTimer stopTimer");
@@ -712,7 +668,7 @@
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
}
Bundle activityOptions = ActivityOptions.makeBasic()
- .setPendingIntentBackgroundActivityStartMode(
+ .setPendingIntentCreatorBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
.toBundle();
intent.setComponent(new ComponentName(packageName, className));
@@ -756,8 +712,19 @@
return telephonyManager.isMultiSimEnabled();
}
- private int getEmergencyCallToSatelliteHandoverType() {
- if (isSatelliteViaCarrierAvailable()) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public int getEmergencyCallToSatelliteHandoverType() {
+ if (Flags.carrierRoamingNbIotNtn() && isSatelliteViaOemAvailable()
+ && isSatelliteViaCarrierAvailable()) {
+ Phone satellitePhone = mSatelliteController.getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("getEmergencyCallToSatelliteHandoverType: satellitePhone is null");
+ return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
+ }
+ int satelliteSubId = satellitePhone.getSubId();
+ return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
+ satelliteSubId);
+ } else if (isSatelliteViaCarrierAvailable()) {
return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
} else {
return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
@@ -843,24 +810,6 @@
}
}
- @Nullable
- private String getMccMnc(@NonNull NetworkRegistrationInfo nri) {
- CellIdentity cellIdentity = nri.getCellIdentity();
- if (cellIdentity == null) {
- plogd("getMccMnc: cellIdentity is null");
- return null;
- }
-
- String mcc = cellIdentity.getMccString();
- String mnc = cellIdentity.getMncString();
- if (mcc == null || mnc == null) {
- plogd("getMccMnc: mcc or mnc is null. mcc=" + mcc + " mnc=" + mnc);
- return null;
- }
-
- return mcc + mnc;
- }
-
private void plogd(@NonNull String log) {
Rlog.d(TAG, log);
if (mPersistentLogger != null) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index 4dc425d..cd4d433 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.
@@ -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 getOemBasedNonTerrestrialSubscriptionId(@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("getOemBasedNonTerrestrialSubscriptionId: subId=" + subId);
+ return subId;
+ }
+
+ /**
* Expected format of the input dictionary bundle is:
* <ul>
* <li>Key: PLMN string.</li>
@@ -391,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)) {
+ logv("isCellularAvailable true");
+ return true;
+ }
+ }
+ }
+ logv("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);
}
@@ -398,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 ac8f0b3..b820ffe 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
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;
@@ -37,6 +38,7 @@
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;
@@ -51,10 +53,14 @@
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.flags.FeatureFlags;
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;
@@ -105,18 +111,24 @@
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;
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;
+
@NonNull private final ExponentialBackoff mExponentialBackoff;
@NonNull private final Object mLock = new Object();
+ @NonNull private final Phone mPhone;
@Nullable
private ISatelliteGateway mSatelliteGatewayService;
private String mSatelliteGatewayServicePackageName = "";
@Nullable private SatelliteGatewayServiceConnection mSatelliteGatewayServiceConnection;
private boolean mIsBound;
private boolean mIsBinding;
+ private boolean mIsRegisteredScreenStateChanged = false;
@NonNull private static SatelliteSessionController sInstance;
@@ -141,11 +153,16 @@
@SatelliteManager.SatelliteModemState private int mPreviousState;
final boolean mIsSatelliteSupported;
private boolean mIsDemoMode = false;
+ // Interested in screen off, so use default value true
+ boolean mIsScreenOn = true;
@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 FeatureFlags mFeatureFlags;
/**
* @return The singleton instance of SatelliteSessionController.
@@ -172,6 +189,10 @@
@NonNull FeatureFlags featureFlags,
boolean isSatelliteSupported) {
if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
+ if (sInstance != null) {
+ sInstance.cleanUpResource();
+ }
+
sInstance = new SatelliteSessionController(
context,
looper,
@@ -204,6 +225,7 @@
}
mContext = context;
+ mFeatureFlags = featureFlags;
mSatelliteModemInterface = satelliteModemInterface;
mSatelliteController = SatelliteController.getInstance();
mDatagramController = DatagramController.getInstance();
@@ -234,6 +256,9 @@
bindService();
});
+ mPhone = SatelliteServiceUtils.getPhone();
+ mDeviceStateMonitor = mPhone.getDeviceStateMonitor();
+
addState(mUnavailableState);
addState(mPowerOffState);
addState(mEnablingState);
@@ -308,6 +333,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 +370,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);
@@ -422,6 +479,15 @@
return getCurrentState() == mEnablingState;
}
+ /**
+ * Release all resource.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void cleanUpResource() {
+ if (DBG) plogd("cleanUpResource");
+ unregisterForScreenStateChanged();
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -468,6 +534,8 @@
stopNbIotInactivityTimer();
DemoSimulator.getInstance().onSatelliteModeOff();
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+
+ unregisterForScreenStateChanged();
}
@Override
@@ -539,6 +607,8 @@
transitionTo(mIdleState);
}
DemoSimulator.getInstance().onSatelliteModeOn();
+
+ registerForScreenStateChanged();
} else {
/*
* During the state transition from ENABLING to NOT_CONNECTED, modem might be
@@ -560,6 +630,8 @@
mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE);
+
+ unregisterForScreenStateChanged();
}
@Override
@@ -638,6 +710,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;
@@ -732,6 +810,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;
@@ -803,6 +887,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;
@@ -866,6 +956,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;
@@ -932,6 +1028,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;
@@ -984,6 +1086,12 @@
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;
default:
whatString = "UNKNOWN EVENT " + what;
}
@@ -1103,6 +1211,7 @@
mSatelliteGatewayServiceConnection = null;
}
}
+
private class SatelliteGatewayServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -1143,6 +1252,100 @@
}
}
+ private void registerForScreenStateChanged() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Rlog.d(TAG, "registerForScreenStateChanged: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ if (mSatelliteController.getRequestIsEmergency()) {
+ if (DBG) logd("registerScreenOnOffChanged: 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(
+ mPhone.getSubId());
+
+ return config.getInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ DEFAULT_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ }
+
+ private void handleEventScreenOffInactivityTimerTimedOut() {
+ plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite");
+
+ mSatelliteController.requestSatelliteEnabled(mPhone.getSubId(),
+ false /*enableSatellite*/,
+ false /*enableDemoMode*/,
+ mSatelliteController.getRequestIsEmergency() /*isEmergency*/,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("requestSatelliteEnabled result=" + result);
+ }
+ });
+ }
+
private boolean isMockModemAllowed() {
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index cd6e6aa..d835f2d 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -296,7 +296,10 @@
SubscriptionInfoInternal::getSatelliteEntitlementPlmns),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
- SubscriptionInfoInternal::getSatelliteESOSSupported)
+ SubscriptionInfoInternal::getSatelliteESOSSupported),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ SubscriptionInfoInternal::getIsSatelliteProvisionedForNonIpDatagram)
);
/**
@@ -439,7 +442,10 @@
SubscriptionDatabaseManager::setSatelliteEntitlementStatus),
new AbstractMap.SimpleImmutableEntry<>(
SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
- SubscriptionDatabaseManager::setSatelliteESOSSupported)
+ SubscriptionDatabaseManager::setSatelliteESOSSupported),
+ new AbstractMap.SimpleImmutableEntry<>(
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+ SubscriptionDatabaseManager::setIsSatelliteProvisionedForNonIpDatagram)
);
/**
@@ -2185,6 +2191,24 @@
}
/**
+ * 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.
@@ -2422,7 +2446,10 @@
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_ONLY_NTN)));
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index 7684864..92e112d 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -498,6 +498,13 @@
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}.
@@ -577,6 +584,8 @@
this.mIsSatelliteEntitlementStatus = builder.mIsSatelliteEntitlementStatus;
this.mSatelliteEntitlementPlmns = builder.mSatelliteEntitlementPlmns;
this.mIsSatelliteESOSSupported = builder.mIsSatelliteESOSSupported;
+ this.mIsSatelliteProvisionedForNonIpDatagram =
+ builder.mIsSatelliteProvisionedForNonIpDatagram;
}
/**
@@ -1280,6 +1289,16 @@
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() {
@@ -1384,6 +1403,8 @@
+ " satelliteEntitlementStatus=" + mIsSatelliteEntitlementStatus
+ " satelliteEntitlementPlmns=" + mSatelliteEntitlementPlmns
+ " isSatelliteESOSSupported=" + mIsSatelliteESOSSupported
+ + " isSatelliteProvisionedForNonIpDatagram="
+ + mIsSatelliteProvisionedForNonIpDatagram
+ "]";
}
@@ -1447,7 +1468,9 @@
&& mTransferStatus == that.mTransferStatus
&& mIsSatelliteEntitlementStatus == that.mIsSatelliteEntitlementStatus
&& mSatelliteEntitlementPlmns.equals(that.mSatelliteEntitlementPlmns)
- && mIsSatelliteESOSSupported == that.mIsSatelliteESOSSupported;
+ && mIsSatelliteESOSSupported == that.mIsSatelliteESOSSupported
+ && mIsSatelliteProvisionedForNonIpDatagram
+ == that.mIsSatelliteProvisionedForNonIpDatagram;
}
@Override
@@ -1480,7 +1503,8 @@
mIsSatelliteEnabled, mCardId, mIsGroupDisabled,
mIsSatelliteAttachEnabledForCarrier, mIsOnlyNonTerrestrialNetwork,
mServiceCapabilities, mTransferStatus, mIsSatelliteEntitlementStatus,
- mSatelliteEntitlementPlmns, mIsSatelliteESOSSupported);
+ mSatelliteEntitlementPlmns, mIsSatelliteESOSSupported,
+ mIsSatelliteProvisionedForNonIpDatagram);
result = 31 * result + Arrays.hashCode(mNativeAccessRules);
result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
result = 31 * result + Arrays.hashCode(mRcsConfig);
@@ -1894,6 +1918,11 @@
private int mIsSatelliteESOSSupported = 0;
/**
+ * Whether this subscription is provisioned for oem satellite service or not.
+ */
+ private int mIsSatelliteProvisionedForNonIpDatagram = 0;
+
+ /**
* Default constructor.
*/
public Builder() {
@@ -1976,6 +2005,7 @@
mIsSatelliteEntitlementStatus = info.mIsSatelliteEntitlementStatus;
mSatelliteEntitlementPlmns = info.mSatelliteEntitlementPlmns;
mIsSatelliteESOSSupported = info.mIsSatelliteESOSSupported;
+ mIsSatelliteProvisionedForNonIpDatagram = info.mIsSatelliteProvisionedForNonIpDatagram;
}
/**
@@ -2959,6 +2989,20 @@
}
/**
+ * 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 30cf3ad..6ef7328 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -196,7 +196,8 @@
SimInfo.COLUMN_IS_ONLY_NTN,
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS,
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
- SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED
+ SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
+ SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM
);
/**
@@ -457,6 +458,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) {}
}
/**
@@ -592,6 +600,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,
@@ -912,6 +927,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);
@@ -928,6 +945,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);
@@ -999,6 +1018,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);
@@ -1893,7 +1915,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
@@ -2234,7 +2259,7 @@
@Override
public List<SubscriptionInfo> getAccessibleSubscriptionInfoList(
@NonNull String callingPackage) {
- if (!mEuiccManager.isEnabled()) {
+ if (mEuiccManager == null || !mEuiccManager.isEnabled()) {
return null;
}
@@ -3166,6 +3191,11 @@
broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,
subId);
+ if (mFeatureFlags.ddsCallback()) {
+ mSubscriptionManagerServiceCallbacks.forEach(
+ callback -> callback.invokeFromExecutor(
+ () -> callback.onDefaultDataSubscriptionChanged(subId)));
+ }
updateDefaultSubId();
}
@@ -3895,10 +3925,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();
@@ -4006,6 +4046,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.");
}
@@ -4636,6 +4679,24 @@
}
/**
+ * 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.
@@ -4655,6 +4716,20 @@
}
/**
+ * 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.
*
diff --git a/src/java/com/android/internal/telephony/uicc/SIMRecords.java b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
index a97b00b..34b412f 100644
--- a/src/java/com/android/internal/telephony/uicc/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/SIMRecords.java
@@ -48,6 +48,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* {@hide}
@@ -1278,15 +1279,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/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index a22f075..0e4a5ef 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -67,6 +67,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;
@@ -1155,7 +1156,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
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..97fb9ca 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,7 +18,7 @@
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;
@@ -34,7 +34,6 @@
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
@@ -58,7 +57,7 @@
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) {
@@ -88,6 +87,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;
@@ -146,8 +148,7 @@
int channel = openChannelResponse.getChannel();
int status = openChannelResponse.getStatus();
byte[] selectResponse = openChannelResponse.getSelectResponse();
- if (mAid.equals(ISD_R_AID)
- && status == IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT) {
+ if (status == IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT) {
channel = PreferenceManager.getDefaultSharedPreferences(mContext)
.getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
if (channel != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
@@ -173,13 +174,11 @@
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)
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().putInt(mChannelKey, channel).apply();
+ PreferenceManager.getDefaultSharedPreferences(mContext)
.edit().putString(mChannelResponseKey,
- Base64.encodeToString(selectResponse, Base64.DEFAULT)).apply();
- }
+ Base64.encodeToString(selectResponse, Base64.DEFAULT)).apply();
try {
requestProvider.buildRequest(selectResponse, builder);
} catch (Throwable e) {
@@ -304,12 +303,10 @@
@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();
- }
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelKey).apply();
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelResponseKey).apply();
mChannelOpened = false;
mChannelLock.notify();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 8209f92..8dad3ec 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();
@@ -401,4 +384,13 @@
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 4af6f7e..c923f69 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -136,7 +136,9 @@
+ 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_ESOS_SUPPORTED + " INTEGER DEFAULT 0"
+ + 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/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/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index e3da458..1465176 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()
@@ -3082,6 +3085,7 @@
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());
@@ -3245,6 +3249,69 @@
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.updateSpnDisplay();
+
+ // 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.updateSpnDisplay();
+
+ // 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();
+ }
+
private Bundle getExtrasFromLastSpnUpdateIntent() {
// Verify the spn update notification was sent
ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
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..12a119c 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;
@@ -28,6 +29,7 @@
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 +66,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,30 +97,31 @@
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(destAddr, messageId, isOverIms, isLastSmsPart, true/*success*/);
}
public void testNotifySmsSentFailedToEmergencyStateTracker(String destAddr,
long messageId, boolean isOverIms) {
- notifySmsSentFailedToEmergencyStateTracker(destAddr, messageId, isOverIms);
+ notifySmsSent(destAddr, messageId, isOverIms, true/*isLastSmsPart*/, false/*success*/);
}
public void testNotifySmsReceivedViaImsToEmergencyStateTracker(String origAddr) {
@@ -134,10 +138,10 @@
}
@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,
+ public void sendData(String callingPackage, int callingUser, String destAddr,
+ String scAddr, int destPort, byte[] data, PendingIntent sentIntent,
+ PendingIntent deliveryIntent, boolean isForVvm) {
+ super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
data, sentIntent, deliveryIntent, isForVvm);
}
@@ -161,10 +165,10 @@
}
@Override
- public void sendData(String callingPackage, String destAddr, String scAddr, int destPort,
- byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
+ public void sendData(String callingPackage, int callingUser, String destAddr, String scAddr,
+ int destPort, byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent,
boolean isForVvm) {
- super.sendData(callingPackage, destAddr, scAddr, destPort,
+ super.sendData(callingPackage, callingUser, destAddr, scAddr, destPort,
data, sentIntent, deliveryIntent, isForVvm);
}
@@ -191,15 +195,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();
}
@@ -259,7 +269,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 +279,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 +288,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 +363,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 +473,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 +490,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));
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -494,7 +505,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 +523,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 +540,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));
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -703,7 +715,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 +740,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));
}
@Test
@@ -743,7 +755,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 +781,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));
}
@Test
@@ -779,7 +792,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 +803,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 +815,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));
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -819,13 +833,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));
}
@Test
@@ -835,7 +849,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 +887,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 +902,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));
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -904,7 +918,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 +958,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 +973,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));
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
assertEquals(0, holder.getPendingRequests().size());
@@ -991,7 +1005,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 +1016,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));
}
@Test
@@ -1033,7 +1047,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 +1059,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));
}
private void switchImsSmsFormat(int phoneType) {
@@ -1063,6 +1077,42 @@
assertTrue(mSmsDispatchersController.setImsManager(imsManager));
}
+ @Test
+ public void testSendSmsToDatagramDispatcher() {
+ when(mSatelliteController.isInCarrierRoamingNbIotNtn()).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 +1202,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 +1218,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));
} 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));
} 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));
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1188,7 +1238,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 +1255,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));
} 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));
} 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));
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1230,7 +1280,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 +1297,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));
} 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(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(mCallingUserId),
+ eq(false), eq(0),
eq(false), eq(10), eq(1L));
} 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));
}
assertNull(holder.getConnection());
assertFalse(holder.isDomainSelectionRequested());
@@ -1321,4 +1372,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/TelephonyCountryDetectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
index a2763fe..9b3777b 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;
@@ -114,8 +121,9 @@
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);
if (isGeoCoderImplemented()) {
verify(mLocationManager).requestLocationUpdates(anyString(), anyLong(), anyFloat(),
mLocationListenerCaptor.capture());
@@ -137,8 +145,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(),
@@ -322,6 +332,31 @@
verify(mLocationManager).removeUpdates(any(LocationListener.class));
}
+ @Test
+ public void testRegisterUnregisterForWifiConnectivityStateChanged() {
+ 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);
+ mTestableLooper.processAllMessages();
+ assertTrue(listener.getIsWifiConnected());
+
+ // Wi-fi becomes not available
+ clearInvocations(mLocationManager);
+ mNetworkCapabilities.setTransportType(NetworkCapabilities.TRANSPORT_WIFI, false);
+ mNetworkCallbackCaptor.getValue().onUnavailable();
+ mTestableLooper.processAllMessages();
+ assertFalse(listener.getIsWifiConnected());
+
+ mCountryDetectorUT.unregisterForWifiConnectivityStateChanged(listener);
+ }
+
private static boolean isGeoCoderImplemented() {
return Geocoder.isPresent();
}
@@ -357,8 +392,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 +411,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/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index b8dc786..a645439 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,10 +77,12 @@
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;
@@ -94,6 +98,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;
@@ -118,6 +124,7 @@
private int mRegistrationFailReason;
private Set<Integer> mSimultaneousCallingSubscriptions;
private boolean mCarrierRoamingNtnMode;
+ private boolean mCarrierRoamingNtnEligible;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -295,6 +302,12 @@
invocationCount.incrementAndGet();
mCarrierRoamingNtnMode = active;
}
+
+ @Override
+ public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnEligible = eligible;
+ }
}
private void addTelephonyRegistryService() {
@@ -1589,4 +1602,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..36ac992 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -580,6 +580,7 @@
mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
+ doReturn(true).when(mFeatureFlags).supportNetworkProvider();
TelephonyManager.disableServiceHandleCaching();
PropertyInvalidatedCache.disableForTestMode();
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 60dcb59..5dce5c2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -44,6 +44,7 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.InetAddresses;
import android.net.LinkAddress;
@@ -158,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;
@@ -172,6 +172,7 @@
private RegistrationCallback mMmtelRegCallback;
private RegistrationCallback mRcsRegCallback;
private SubscriptionInfo mMockSubInfo;
+ private PackageManager mMockPackageManager;
private int mNetworkRequestId = 0;
@@ -853,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);
@@ -863,6 +863,7 @@
mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class);
mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class);
mMockSubInfo = Mockito.mock(SubscriptionInfo.class);
+ mMockPackageManager = Mockito.mock(PackageManager.class);
when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class),
any(DataNetworkController.class), any(FeatureFlags.class), any(Looper.class),
any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod();
@@ -875,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();
@@ -890,8 +890,8 @@
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
doReturn(true).when(mFeatureFlags).satelliteInternet();
- doReturn(true).when(mFeatureFlags)
- .ignoreExistingNetworksForInternetAllowedChecking();
+ when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
+ doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
List<SubscriptionInfo> infoList = new ArrayList<>();
infoList.add(mMockSubInfo);
@@ -2839,7 +2839,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);
@@ -3896,7 +3895,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
@@ -4903,14 +4901,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();
@@ -4931,7 +4925,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);
@@ -4944,7 +4938,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);
@@ -5470,4 +5464,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 8be0f8b..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,7 +2419,6 @@
@Test
public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
- doReturn(true).when(mFeatureFlags).forceIwlanMms();
setupDataNetwork();
TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
@@ -2662,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/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 0eb5c13..25e9715 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -180,7 +180,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 +239,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 +287,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 +323,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);
@@ -359,7 +359,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));
// isOkToCall() should return true once satellite modem is off
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
@@ -400,7 +400,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 +428,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());
}
@@ -3168,7 +3168,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));
}
/**
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..53e508b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -49,6 +49,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,7 +88,12 @@
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;
@@ -106,6 +112,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 +153,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 +226,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 +586,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 +604,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);
}
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 ed19fd3..e542a41 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -173,6 +173,7 @@
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();
@@ -384,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();
@@ -398,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
@@ -413,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();
@@ -427,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
@@ -1076,14 +1097,21 @@
// user locked
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);
@@ -1094,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();
@@ -1129,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);
@@ -1144,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 */
@@ -1170,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();
@@ -1197,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();
@@ -1215,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..58cc261 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);
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);
}
@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);
waitForMs(150);
ArgumentCaptor<String> pduCaptor = ArgumentCaptor.forClass(String.class);
@@ -568,7 +572,7 @@
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(),
@@ -585,7 +589,7 @@
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/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index a525efa..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));
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..b62d9e1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -1182,12 +1182,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;
@@ -1200,12 +1200,12 @@
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;
@@ -1222,13 +1222,13 @@
};
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;
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;
@@ -1241,7 +1241,7 @@
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;
@@ -1249,7 +1249,7 @@
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;
@@ -1260,14 +1260,14 @@
};
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;
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;
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..97f7935 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
@@ -169,9 +169,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 +212,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 +236,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 +261,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)
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/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index 7094399..e4f9109 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -20,6 +20,7 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.SATELLITE_ALIGN_TIMEOUT;
+import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
import static com.google.common.truth.Truth.assertThat;
@@ -47,6 +48,7 @@
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;
@@ -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,9 @@
mDatagram = new SatelliteDatagram(TEST_MESSAGE.getBytes());
mInOrder = inOrder(mMockDatagramController);
when(mMockDatagramController.isPollingInIdleState()).thenReturn(true);
+ when(mMockSatelliteController.getSatellitePhone()).thenReturn(mPhone);
+ when(mPhone.getSmsDispatchersController()).thenReturn(mMockSmsDispatchersController);
+ mPendingSms = createPendingRequest();
}
@After
@@ -175,6 +188,7 @@
mResultListener = null;
mDatagram = null;
mInOrder = null;
+ mPendingSms = null;
super.tearDown();
}
@@ -766,6 +780,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.messageId, 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.messageId, 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(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ 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(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ 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.messageId, 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.messageId, 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 +1187,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/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index e6d825e..872cc28 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,13 @@
package com.android.internal.telephony.satellite;
+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.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
@@ -28,6 +32,8 @@
import static android.telephony.satellite.SatelliteManager.KEY_DEMO_MODE_ENABLED;
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;
@@ -44,13 +50,13 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_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_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;
@@ -90,9 +96,11 @@
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.SharedPreferences;
+import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -100,14 +108,18 @@
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.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;
@@ -120,6 +132,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;
@@ -138,6 +154,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 org.junit.After;
@@ -149,6 +166,7 @@
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;
@@ -178,6 +196,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>>
@@ -206,6 +226,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() {
@@ -234,6 +257,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;
@@ -512,6 +546,9 @@
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);
doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
@@ -539,6 +576,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();
@@ -565,6 +603,7 @@
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();
@@ -574,10 +613,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 */,
@@ -589,6 +624,9 @@
doReturn(mMockConfigParser).when(mMockTelephonyConfigUpdateInstallReceiver)
.getConfigParser(ConfigProviderAdaptor.DOMAIN_SATELLITE);
+ doReturn(mSubscriptionInfo).when(mMockSubscriptionManagerService).getSubscriptionInfo(
+ anyInt());
+ doReturn("").when(mSubscriptionInfo).getIccId();
}
@After
@@ -626,7 +664,7 @@
mSatelliteVisibilityTimeReceiver);
processAllMessages();
assertTrue(waitForRequestTimeForNextSatelliteVisibilityResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
mQueriedSatelliteVisibilityTimeResultCode);
resetSatelliteControllerUT();
@@ -724,6 +762,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
@@ -797,10 +916,25 @@
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
(long) mIIntegerConsumerResults.get(0));
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ // Fail to enable satellite when the emergency call is in progress
+ mIIntegerConsumerResults.clear();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ doReturn(true).when(mTelecomManager).isInEmergencyCall();
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, 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();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -813,6 +947,7 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteSessionController, times(2)).onEmergencyModeChanged(eq(false));
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
@@ -828,11 +963,12 @@
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(3)).onEmergencyModeChanged(eq(false));
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
@@ -955,7 +1091,13 @@
assertEquals(SATELLITE_RESULT_REQUEST_IN_PROGRESS, (long) mIIntegerConsumerResults.get(0));
mIIntegerConsumerResults.clear();
- resetSatelliteControllerUTToSupportedAndProvisionedState();
+ resetSatelliteControllerUT();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(false);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setProvisionedState(true);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
// 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));
@@ -981,13 +1123,13 @@
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(17)).setInitializationResult(anyInt());
+ verify(mMockSessionMetricsStats, times(17)).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();
+ verify(mMockSessionMetricsStats, times(17)).reportSessionMetrics();
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
@@ -1035,12 +1177,49 @@
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();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ // Fail to enable satellite when radio is being powered off.
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, 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();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -1054,7 +1233,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
// Set provisioned state
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
@@ -1157,7 +1336,7 @@
mStartTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
(long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
@@ -1231,7 +1410,7 @@
mStopTransmissionUpdateCallback);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
(long) mIIntegerConsumerResults.get(0));
resetSatelliteControllerUT();
@@ -1295,7 +1474,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.requestIsDemoModeEnabled(SUB_ID, mIsDemoModeEnabledReceiver);
assertTrue(waitForRequestIsDemoModeEnabledResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedIsDemoModeEnabledResultCode);
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED, mQueriedIsDemoModeEnabledResultCode);
assertFalse(mQueriedIsDemoModeEnabled);
resetSatelliteControllerUT();
@@ -1341,7 +1520,6 @@
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);
@@ -1353,7 +1531,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -1363,6 +1541,11 @@
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
};
int errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
SUB_ID, callback);
@@ -1386,6 +1569,11 @@
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
}
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
};
mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
verify(mMockSatelliteSessionController, never())
@@ -1412,6 +1600,12 @@
+ "semaphore, ex=" + ex);
}
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> status) {
+ logd("onSatelliteSubscriptionProvisionStateChanged: " + status);
+ }
};
int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
SUB_ID, callback);
@@ -1428,15 +1622,27 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
SUB_ID, 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(SUB_ID,
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
mSatelliteControllerUT.unregisterForSatelliteProvisionStateChanged(SUB_ID, callback);
- sendProvisionedStateChangedEvent(true, null);
+ cancelRemote = mSatelliteControllerUT.provisionSatelliteService(SUB_ID,
+ TEST_SATELLITE_TOKEN,
+ testProvisionData, mIIntegerConsumer);
processAllMessages();
assertFalse(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
@@ -1505,7 +1711,7 @@
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,
@@ -1518,7 +1724,7 @@
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,
@@ -1545,7 +1751,7 @@
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);
@@ -1556,7 +1762,7 @@
verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any());
mIIntegerConsumerResults.clear();
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.pollPendingDatagrams(SUB_ID, mIIntegerConsumer);
@@ -1599,8 +1805,6 @@
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,
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -1619,61 +1823,12 @@
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,
TEST_NEXT_SATELLITE_TOKEN, testProvisionData, mIIntegerConsumer);
cancellationSignal.setRemote(cancelRemote);
@@ -1681,8 +1836,6 @@
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();
@@ -1690,9 +1843,6 @@
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,
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -1730,13 +1880,11 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
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();
@@ -1744,7 +1892,6 @@
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,
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
@@ -1754,20 +1901,6 @@
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,
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
@@ -1776,16 +1909,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,
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
@@ -2443,6 +2576,10 @@
verifyRegisterForNtnSignalStrengthChanged(SUB_ID, callback,
SATELLITE_RESULT_SUCCESS);
verifyRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForNtnSignalStrengthChanged"));
+ assertEquals(expectedLevel, signalStrength[0].getLevel());
expectedLevel = NTN_SIGNAL_STRENGTH_GOOD;
sendNtnSignalStrengthChangedEvent(expectedLevel, null);
@@ -2935,8 +3072,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.
@@ -2993,32 +3130,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,
@@ -3384,14 +3521,13 @@
}
@Test
- public void testHandleEventServiceStateChanged() throws Exception {
+ public void testHandleEventServiceStateChanged() {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
// 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
@@ -3400,8 +3536,7 @@
processAllMessages();
verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(),
any());
- assertEquals(true,
- mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
+ assertTrue(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
// Check don't display again after displayed already a system notification.
sendServiceStateChangedEvent();
@@ -3416,7 +3551,7 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
@@ -3431,23 +3566,31 @@
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);
+ clearInvocations(mMockSatelliteModemInterface);
mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, 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
@@ -3477,8 +3620,8 @@
mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false),
- eq(false),
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+ any(SatelliteModemEnableRequestAttributes.class),
disableSatelliteResponse.capture());
clearInvocations(mMockSatelliteModemInterface);
@@ -3486,8 +3629,8 @@
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_MODEM_TIMEOUT, (long) mIIntegerConsumerResults.get(0));
- verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), anyBoolean(), any(Message.class));
+ 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);
@@ -3513,9 +3656,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);
@@ -3657,7 +3800,7 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
// Successfully enable satellite
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
mIIntegerConsumerResults.clear();
@@ -3815,17 +3958,432 @@
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);
+ 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));
+ }
+
+ @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);
+ 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(1)).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()
+ .setEmergencyOnly(true)
+ .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));
+ }
+
+ 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(SUB_ID,
+ 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);
+
+ verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
+ any());
+ 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);
+
+ verify(mMockSatelliteModemInterface, times(2)).updateSatelliteSubscription(anyString(),
+ any());
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
+ }
+
+ 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));
+ doReturn("action").when(mResources).getString(
+ eq(R.string.config_satellite_carrier_roaming_esos_provisioned_intent_action));
+ }
+
+ 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;
+ }
+
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);
}
@@ -3840,7 +4398,7 @@
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
doNothing().when(mMockSatelliteModemInterface)
.setSatelliteServicePackageName(anyString());
- mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService");
+ mSatelliteControllerUT.setSatelliteServicePackageName("TestSatelliteService", null);
processAllMessages();
}
@@ -3848,7 +4406,7 @@
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(true, null);
+ setProvisionedState(true);
processAllMessages();
verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
}
@@ -3929,15 +4487,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(
@@ -3949,12 +4499,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));
}
@@ -3974,41 +4524,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) {
@@ -4284,11 +4806,8 @@
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) {
@@ -4374,8 +4893,6 @@
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,
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -4388,7 +4905,6 @@
private void deprovisionSatelliteService() {
mIIntegerConsumerResults.clear();
- setUpResponseForDeprovisionSatelliteService(TEST_SATELLITE_TOKEN, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.deprovisionSatelliteService(SUB_ID,
TEST_SATELLITE_TOKEN, mIIntegerConsumer);
processAllMessages();
@@ -4541,12 +5057,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) {
@@ -4592,5 +5109,52 @@
void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
mSatelliteSessionController = satelliteSessionController;
}
+
+ @Override
+ protected void setSatellitePhone(int subId) {
+ 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;
+ }
+
+ 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);
+ }
}
}
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 cffb1a9..77a7c0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -29,7 +29,6 @@
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.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -45,11 +44,10 @@
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.AccessNetworkConstants;
import android.telephony.BinderCacheManager;
-import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -68,9 +66,11 @@
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 org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -111,6 +111,8 @@
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;
@@ -130,6 +132,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(
@@ -556,72 +559,48 @@
}
@Test
- public void testIsSatellitePlmn() {
- int subId = 1;
+ public void testGetEmergencyCallToSatelliteHandoverType_SatelliteViaCarrierAndOemAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
- // Satellite PLMN list is empty
- SatelliteSOSMessageRecommender sosMessageRecommender = new TestSOSMessageRecommender(
- mContext, Looper.myLooper(), mSatelliteController, mTestImsManager);
- when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId)))
- .thenReturn(new ArrayList<>());
- assertFalse(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
- // 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(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+ }
- // 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(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ @Test
+ public void testGetEmergencyCallToSatelliteHandoverType_OnlySatelliteViaCarrierAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
- // 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(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
- // 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(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+ }
- // 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(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+ @Test
+ public void testGetEmergencyCallToSatelliteHandoverType_OemAndCarrierNotAvailable() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+ mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+ mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
}
private void testStopTrackingCallBeforeTimeout(
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 fc9579f..571f2b4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
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;
@@ -24,12 +25,18 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
+import static com.android.internal.telephony.satellite.SatelliteSessionController.EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT;
+
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.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -37,13 +44,17 @@
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.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;
@@ -51,6 +62,8 @@
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 +71,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 +93,7 @@
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 TestSatelliteModemInterface mSatelliteModemInterface;
private TestSatelliteSessionController mTestSatelliteSessionController;
private TestSatelliteModemStateCallback mTestSatelliteModemStateCallback;
@@ -89,6 +103,9 @@
@Mock private DatagramDispatcher mMockDatagramDispatcher;
@Mock private DatagramController mMockDatagramController;
+ @Captor ArgumentCaptor<Handler> mHandlerCaptor;
+ @Captor ArgumentCaptor<Integer> mMsgCaptor;
+
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
@@ -170,6 +187,91 @@
}
@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_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // 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();
+
+ // 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(anyInt(),
+ 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_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
+ SCREEN_OFF_INACTIVITY_TIMEOUT_SEC);
+ when(mMockSatelliteController.getPersistableBundle(anyInt())).thenReturn(bundle);
+
+ // 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 testStateTransition() {
/**
* Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
@@ -999,6 +1101,41 @@
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 setupDatagramTransferringState(boolean isTransferring) {
when(mMockDatagramController.isSendingInIdleState()).thenReturn(isTransferring);
when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
@@ -1210,12 +1347,19 @@
boolean isEventDeferred(int event) {
return hasDeferredMessages(event);
}
+
+ boolean isScreenOffInActivityTimerStarted() {
+ return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ }
+
}
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<>();
@@ -1227,15 +1371,27 @@
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);
+ }
+ }
+
+ public boolean waitUntilResultForModemStateChanged() {
+ try {
+ if (!mSemaphoreForModemStateChanged.tryAcquire(EVENT_PROCESSING_TIME_MILLIS,
+ TimeUnit.MILLISECONDS)) {
logd("Timeout to receive onSatelliteModemStateChanged");
return false;
}
@@ -1246,6 +1402,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();
}
@@ -1268,22 +1438,48 @@
}
}
+ 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);
+ }
}
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 5a0d0d8..4b1b4a5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -143,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)
@@ -217,6 +220,7 @@
.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 =
@@ -293,6 +297,7 @@
.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;
@@ -2393,4 +2398,38 @@
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 30a4d8e..925cf71 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -124,6 +124,8 @@
.FAKE_SATELLITE_ENTITLEMENT_PLMNS1)
.setSatelliteESOSSupported(
SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
+ .setIsSatelliteProvisionedForNonIpDatagram(
+ SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED)
.build();
private final SubscriptionInfoInternal mSubInfoNull =
@@ -256,6 +258,8 @@
.FAKE_SATELLITE_ENTITLEMENT_PLMNS1);
assertThat(mSubInfo.getSatelliteESOSSupported())
.isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED);
+ assertThat(mSubInfo.getIsSatelliteProvisionedForNonIpDatagram())
+ .isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED);
}
@Test
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 acbf29b..65790f8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -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)
@@ -3285,7 +3292,6 @@
.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/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..5a07714 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
@@ -18,6 +18,7 @@
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;
@@ -33,11 +34,12 @@
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.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
-import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -83,7 +85,6 @@
private Handler mHandler;
private ResponseCaptor mResponseCaptor;
private byte[] mSelectResponse;
- private static final String AID = "B2C3D4";
private ApduSender mSender;
@Before
@@ -95,7 +96,7 @@
mSelectResponse = null;
mSender = new ApduSender(InstrumentationRegistry.getContext(), 0 /* phoneId= */,
- mMockCi, AID, false /* supportExtendedApdu */);
+ mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
mLooper = TestableLooper.get(this);
}
@@ -110,9 +111,19 @@
}
@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 +132,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,14 +148,14 @@
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);
@@ -160,7 +171,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");
@@ -186,7 +197,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 +222,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 +242,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 +273,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 +295,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 +312,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 +339,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 +352,6 @@
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());
}
}
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) {