Merge "Update CellBroadcastConfigTraker state for cleanupCdma case" into main
diff --git a/Android.bp b/Android.bp
index da32208..a6e526c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -82,14 +82,14 @@
"android.hardware.radio-V1.4-java",
"android.hardware.radio-V1.5-java",
"android.hardware.radio-V1.6-java",
- "android.hardware.radio.config-V3-java",
- "android.hardware.radio.data-V3-java",
- "android.hardware.radio.ims-V2-java",
- "android.hardware.radio.messaging-V3-java",
- "android.hardware.radio.modem-V3-java",
- "android.hardware.radio.network-V3-java",
- "android.hardware.radio.sim-V3-java",
- "android.hardware.radio.voice-V3-java",
+ "android.hardware.radio.config-V4-java",
+ "android.hardware.radio.data-V4-java",
+ "android.hardware.radio.ims-V3-java",
+ "android.hardware.radio.messaging-V4-java",
+ "android.hardware.radio.modem-V4-java",
+ "android.hardware.radio.network-V4-java",
+ "android.hardware.radio.sim-V4-java",
+ "android.hardware.radio.voice-V4-java",
"voip-common",
"ims-common",
"unsupportedappusage",
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index 906abfc..27d3518 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -69,4 +69,16 @@
namespace: "telephony"
description: "Used to notify the emergency callback mode for call/SMS to other applications."
bug:"359064059"
+ is_exported: true
}
+
+# OWNER=sewookseo TARGET=25Q2
+flag {
+ name: "pass_copied_call_state_list"
+ namespace: "telephony"
+ description: "To prevent passing the TelephonyRegistry's original instance to listeners in the same process"
+ bug:"379126049"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
index 265d258..14aedc6 100644
--- a/flags/carrier.aconfig
+++ b/flags/carrier.aconfig
@@ -21,3 +21,12 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=melhuishj TARGET=25Q2
+flag {
+ name: "temporary_failures_in_carrier_messaging_service"
+ is_exported: true
+ namespace: "telephony"
+ description: "Enable temporary failures in CarrierMessagingService"
+ bug:"326610112"
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index ccd5db4..4a90c10 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -121,21 +121,11 @@
}
}
-# OWNER=jackyu TARGET=25Q1
-flag {
- name: "sim_disabled_graceful_tear_down"
- namespace: "telephony"
- description: "Gracefully tear down the networks when SIM is disabled."
- bug: "362372940"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-# OWNER=TBD TARGET=TBD
+# OWNER=jackyu TARGET=25Q2
flag {
name: "oem_paid_private"
namespace: "telephony"
description: "Support OEM_PAID and OEM_PRIVATE networks"
bug: "366194627"
+ is_exported: true
}
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4426933..703440f 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -138,10 +138,31 @@
}
}
+# OWNER=breadley TARGET=25Q1
+flag {
+ name: "ims_resolver_user_aware"
+ namespace: "telephony"
+ description: "When enabled, it makes ImsResolver mult-user aware for configurations like HSUM."
+ bug:"371272669"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
# OWNER=meghapatil TARGET=25Q2
flag {
name: "support_sms_over_ims_apis"
namespace: "telephony"
description: "Used to expose SMS related hidden APIs for SMS over IMS to public API."
bug:"359721349"
+ is_exported: true
+}
+
+# OWNER=jhyoon TARGET=25Q2
+flag {
+ name: "support_ims_mmtel_interface"
+ namespace: "telephony"
+ description: "This flag controls the type of API regarding MmTelFeature, either hidden or system type."
+ bug:"359721349"
+ is_exported: true
}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 2d6992a..ec7b8fa 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -78,6 +78,15 @@
bug: "309896524"
}
+# OWNER=rambowang TARGET=24Q3
+flag {
+ name: "reset_mobile_network_settings"
+ is_exported: true
+ namespace: "telephony"
+ description: "Allows applications to launch Reset Mobile Network Settings page in Settings app."
+ bug:"271921464"
+}
+
# OWNER=sangyun TARGET=24Q3
flag {
name: "roaming_notification_for_single_data_network"
@@ -211,3 +220,29 @@
}
}
+# OWNER=jackyu TARGET=25Q2
+flag {
+ name: "power_down_race_fix"
+ namespace: "telephony"
+ description: "Fixed race condition while powering down"
+ bug:"378616116"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+ name: "deprecate_cdma"
+ namespace: "telephony"
+ description: "Deprecate CDMA and NV APIS"
+ bug: "379356026"
+}
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+ name: "cleanup_cdma"
+ namespace: "telephony"
+ description: "Disable CDMA and NV backing code"
+ bug: "379356026"
+}
diff --git a/flags/network.aconfig b/flags/network.aconfig
index 7c09ba3..be599ea 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -93,3 +93,20 @@
}
}
+# OWNER=yomna TARGET=25Q2
+flag {
+ name: "security_algorithms_update_indications"
+ is_exported: true
+ namespace: "telephony"
+ description: "guard system API onSecurityAlgorithmsChanged"
+ bug: "355062720"
+}
+
+# OWNER=yomna TARGET=25Q2
+flag {
+ name: "cellular_identifier_disclosure_indications"
+ is_exported: true
+ namespace: "telephony"
+ description: "guard system API onCellularIdentifierDisclosedChanged"
+ bug: "355062720"
+}
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 4806789..f043ad9 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -41,6 +41,7 @@
namespace: "telephony"
description: "This flag enables satellite carrier roaming to nb iot ntn."
bug:"348253735"
+ is_exported: true
}
# OWNER=tnd TARGET=24Q4
@@ -61,4 +62,32 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+# OWNER=amallampati TARGET=25Q2
+flag {
+ name: "satellite_system_apis"
+ is_exported: true
+ namespace: "telephony"
+ description: "Convert hidden SatelliteManager APIs to system APIs."
+ bug:"373436320"
+}
+
+# OWNER=rambowang TARGET=25Q2
+flag {
+ name: "satellite_state_change_listener"
+ namespace: "telephony"
+ description: "Introduce SatelliteManager APIs for carrier apps to monitor satellite state change"
+ bug: "357638490"
+ is_exported: true
+}
+
+# OWNER=karthickmj TARGET=25Q4
+flag {
+
+ name: "satellite_25q4_apis"
+ namespace: "telephony"
+ description: "This flag controls the changes for the new satellite APIs"
+ bug: "383254935"
+ is_exported: true
+}
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 543aa20..0522a3c 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -19,6 +19,15 @@
bug: "296076674"
}
+# OWNER=rambowang TARGET=24Q3
+flag {
+ name: "data_only_cellular_service"
+ is_exported: true
+ namespace: "telephony"
+ description: "Supports customized cellular service capabilities per subscription."
+ bug: "296097429"
+}
+
# OWNER=hhshin TARGET=24Q3
flag {
name: "support_psim_to_esim_conversion"
@@ -72,3 +81,12 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=jmattis TARGET=25Q2
+flag {
+ name: "subscription_plan_allow_status_and_end_date"
+ namespace: "telephony"
+ description: "Provide APIs to retrieve the status and recurrence rule info on a subscription plan"
+ bug: "357272015"
+ is_exported: true
+}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index ad0c59f..8561dac 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -49,6 +49,7 @@
namespace: "telephony"
description: "This flag controls the visibility of the setCarrierRestrictionStatus API in carrierRestrictionRules class."
bug:"342411308"
+ is_exported: true
}
# OWNER=arunvoddu TARGET=24Q4
@@ -79,4 +80,49 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+# OWNER=jhyoon TARGET=25Q2
+flag {
+ name: "support_isim_record"
+ namespace: "telephony"
+ description: "This flag controls the type of API that retrieves ISIM records, either hidden or system type."
+ bug:"359721349"
+ is_exported: true
+}
+
+# OWNER=jinjeong TARGET=25Q2
+flag {
+ name: "carrier_id_from_carrier_identifier"
+ namespace: "telephony"
+ description: "This flag controls to get a carrier id using a carrier identifier."
+ bug:"378778278"
+ is_exported: true
+}
+
+# OWNER=arunvoddu TARGET=25Q2
+flag {
+ name: "force_imsi_certificate_delete"
+ namespace: "telephony"
+ description: "This flag controls the IMSI certificate delete with out any condition."
+ bug:"235296888"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=jinjeong TARGET=25Q2
+flag {
+ name: "get_group_id_level2"
+ namespace: "telephony"
+ description: "This flag controls to get a group id level2."
+ bug:"381171540"
+}
+
+# OWNER=jinjeong TARGET=25Q2
+flag {
+ name: "action_sim_preference_settings"
+ namespace: "telephony"
+ description: "This flag controls to launch sim preference page in Setting"
+ bug:"381319469"
+}
diff --git a/src/java/com/android/internal/telephony/CarrierInfoManager.java b/src/java/com/android/internal/telephony/CarrierInfoManager.java
index 8364c0a..206770d 100644
--- a/src/java/com/android/internal/telephony/CarrierInfoManager.java
+++ b/src/java/com/android/internal/telephony/CarrierInfoManager.java
@@ -273,21 +273,25 @@
/**
* Resets the Carrier Keys in the database. This involves 2 steps:
- * 1. Delete the keys from the database.
- * 2. Send an intent to download new Certificates.
- * @param context Context
- * @param mPhoneId phoneId
+ * 1. Delete the keys from the database.
+ * 2. Send an intent to download new Certificates.
*
+ * @param context Context
+ * @param mPhoneId phoneId
+ * @param forceResetAll to skip the check of the RESET_CARRIER_KEY_RATE_LIMIT.
*/
- public void resetCarrierKeysForImsiEncryption(Context context, int mPhoneId) {
- Log.i(LOG_TAG, "resetting carrier key");
+ public void resetCarrierKeysForImsiEncryption(Context context, int mPhoneId,
+ boolean forceResetAll) {
+ Log.i(LOG_TAG, "resetting carrier key, forceResetAll = " +forceResetAll);
// Check rate limit.
long now = System.currentTimeMillis();
- if (now - mLastAccessResetCarrierKey < RESET_CARRIER_KEY_RATE_LIMIT) {
- Log.i(LOG_TAG, "resetCarrierKeysForImsiEncryption: Access rate exceeded");
- return;
+ if (!forceResetAll) {
+ if (now - mLastAccessResetCarrierKey < RESET_CARRIER_KEY_RATE_LIMIT) {
+ Log.i(LOG_TAG, "resetCarrierKeysForImsiEncryption: Access rate exceeded");
+ return;
+ }
+ mLastAccessResetCarrierKey = now;
}
- mLastAccessResetCarrierKey = now;
int subId = SubscriptionManager.getSubscriptionId(mPhoneId);
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index ee7447c..1b19c99 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2952,4 +2952,39 @@
* @param h Handler to be removed from the registrant list.
*/
default void unregisterForSecurityAlgorithmUpdates(Handler h) {}
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+ * supported by user subscription.
+ * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+ * PLMNs that are not supported by the carrier and make sure not to
+ * attach to them.
+ * @param result Callback message to receive the result.
+ */
+ default void setSatellitePlmn(int simSlot,
+ @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList,
+ Message result) {}
+
+ /**
+ * Enable or disable satellite in the cellular modem associated with a carrier.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+ * @param result Callback message to receive the result.
+ */
+ default void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+ Message result) {}
+
+ /**
+ * Check whether satellite is enabled in the cellular modem associated with a carrier.
+ *
+ * @param simSlot Indicates the SIM slot to which this API will be applied.
+ * @param result Callback message to receive the result.
+ */
+ default void isSatelliteEnabledForCarrier(int simSlot, Message result) {}
}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 47c701c..dc05608 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -25,11 +25,14 @@
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager.DataEnabledReason;
@@ -40,6 +43,7 @@
import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.MediaQualityStatus;
+import android.telephony.satellite.NtnSignalStrength;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.telephony.Rlog;
@@ -340,6 +344,37 @@
sender.getSubId(), eligible);
}
+ @Override
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnAvailableServicesChanged(
+ sender.getSubId(), availableServices);
+ }
+
+ @Override
+ public void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
+ @NonNull NtnSignalStrength ntnSignalStrength) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnSignalStrengthChanged(
+ sender.getSubId(), ntnSignalStrength);
+ }
+
+ @Override
+ public void notifySecurityAlgorithmsChanged(Phone sender, SecurityAlgorithmUpdate update) {
+ if (!mFeatureFlags.securityAlgorithmsUpdateIndications()) return;
+
+ mTelephonyRegistryMgr.notifySecurityAlgorithmsChanged(sender.getPhoneId(),
+ sender.getSubId(), update);
+ }
+
+ @Override
+ public void notifyCellularIdentifierDisclosedChanged(Phone sender,
+ CellularIdentifierDisclosure disclosure) {
+ if (!mFeatureFlags.cellularIdentifierDisclosureIndications()) return;
+
+ mTelephonyRegistryMgr.notifyCellularIdentifierDisclosedChanged(sender.getPhoneId(),
+ sender.getSubId(), disclosure);
+ }
+
/**
* 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/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index d3f0264..bb19a31 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -110,7 +110,7 @@
mTelephonyDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
- false);
+ false, false, false);
mNetworkTypeController = new NetworkTypeController(phone, this, featureFlags);
// EVENT_UPDATE will transition from DefaultState to the current state
// and update the TelephonyDisplayInfo based on the current state.
@@ -132,7 +132,9 @@
TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(
mNetworkTypeController.getDataNetworkType(),
mNetworkTypeController.getOverrideNetworkType(),
- isRoaming());
+ isRoaming(),
+ mPhone.getServiceStateTracker().getServiceState().isUsingNonTerrestrialNetwork(),
+ mNetworkTypeController.getSatelliteConstrainedData());
if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) {
logl("TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to "
+ newDisplayInfo);
diff --git a/src/java/com/android/internal/telephony/EventLogTags.logtags b/src/java/com/android/internal/telephony/EventLogTags.logtags
index b5e458b..2f30c33 100644
--- a/src/java/com/android/internal/telephony/EventLogTags.logtags
+++ b/src/java/com/android/internal/telephony/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package com.android.internal.telephony;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 2e1a89f..f190a43 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -42,7 +42,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.database.SQLException;
import android.hardware.radio.modem.ImeiInfo;
import android.net.Uri;
@@ -470,12 +469,6 @@
}
};
- private boolean hasCalling() {
- if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
- return mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY_CALLING);
- }
-
private void initOnce(CommandsInterface ci) {
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
@@ -782,6 +775,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@Override
public int getPhoneType() {
+ if (mFeatureFlags.cleanupCdma()) return PhoneConstants.PHONE_TYPE_GSM;
if (mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM) {
return PhoneConstants.PHONE_TYPE_GSM;
} else {
@@ -1900,8 +1894,15 @@
@Override
public void setRadioPowerForReason(boolean power, boolean forEmergencyCall,
boolean isSelectedPhoneForEmergencyCall, boolean forceApply, int reason) {
- mSST.setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall,
- forceApply, reason);
+ if (mFeatureFlags.powerDownRaceFix()) {
+ // setRadioPowerForReason can be called by the binder thread. We need to move that into
+ // the main thread to prevent race condition.
+ post(() -> mSST.setRadioPowerForReason(power, forEmergencyCall,
+ isSelectedPhoneForEmergencyCall, forceApply, reason));
+ } else {
+ mSST.setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall,
+ forceApply, reason);
+ }
}
@Override
@@ -2189,7 +2190,12 @@
@Override
public void resetCarrierKeysForImsiEncryption() {
- mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId);
+ mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId, false);
+ }
+
+ @Override
+ public void resetCarrierKeysForImsiEncryption(boolean forceResetAll) {
+ mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId, forceResetAll);
}
@Override
@@ -3770,6 +3776,13 @@
&& disclosure != null) {
mIdentifierDisclosureNotifier.addDisclosure(mContext, getSubId(), disclosure);
}
+ if (mFeatureFlags.cellularIdentifierDisclosureIndications()
+ && mIdentifierDisclosureNotifier != null
+ && disclosure != null) {
+ logd("EVENT_CELL_IDENTIFIER_DISCLOSURE for non-Safety Center listeners "
+ + "phoneId = " + getPhoneId());
+ mNotifier.notifyCellularIdentifierDisclosedChanged(this, disclosure);
+ }
break;
case EVENT_SET_IDENTIFIER_DISCLOSURE_ENABLED_DONE:
@@ -3780,13 +3793,21 @@
case EVENT_SECURITY_ALGORITHM_UPDATE:
logd("EVENT_SECURITY_ALGORITHM_UPDATE phoneId = " + getPhoneId());
+
+ ar = (AsyncResult) msg.obj;
+ SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
+
if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()
&& mNullCipherNotifier != null) {
- ar = (AsyncResult) msg.obj;
- SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getPhoneId(),
getSubId(), update);
}
+ if (mFeatureFlags.securityAlgorithmsUpdateIndications()
+ && mNullCipherNotifier != null) {
+ logd("EVENT_SECURITY_ALGORITHM_UPDATE for non-Safety Center listeners "
+ + "phoneId = " + getPhoneId());
+ mNotifier.notifySecurityAlgorithmsChanged(this, update);
+ }
break;
case EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE:
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 3141406..9eebc60 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -48,6 +48,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.uicc.IccConstants;
@@ -1511,8 +1512,7 @@
@VisibleForTesting
public void notifyIfOutgoingEmergencySms(String destAddr) {
Phone[] allPhones = mPhoneFactoryProxy.getPhones();
- EmergencyNumber emergencyNumber = mPhone.getEmergencyNumberTracker().getEmergencyNumber(
- destAddr);
+ EmergencyNumber emergencyNumber = getEmergencyNumber(mPhone, destAddr);
if (emergencyNumber != null) {
mPhone.notifyOutgoingEmergencySms(emergencyNumber);
} else if (allPhones.length > 1) {
@@ -1522,8 +1522,7 @@
if (phone.getPhoneId() == mPhone.getPhoneId()) {
continue;
}
- emergencyNumber = phone.getEmergencyNumberTracker()
- .getEmergencyNumber(destAddr);
+ emergencyNumber = getEmergencyNumber(phone, destAddr);
if (emergencyNumber != null) {
mPhone.notifyOutgoingEmergencySms(emergencyNumber);
break;
@@ -1532,6 +1531,13 @@
}
}
+ private EmergencyNumber getEmergencyNumber(Phone phone, String number) {
+ if (!phone.hasCalling()) return null;
+ EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
+ if (tracker == null) return null;
+ return tracker.getEmergencyNumber(number);
+ }
+
private void returnUnspecifiedFailure(PendingIntent pi) {
if (pi != null) {
try {
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 0106516..52ceda5 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -66,6 +66,7 @@
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Pair;
@@ -691,11 +692,10 @@
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
if (result == Intents.RESULT_SMS_HANDLED) {
SatelliteController satelliteController = SatelliteController.getInstance();
- if (satelliteController == null) {
- log("SatelliteController is not initialized");
- return;
+ if (satelliteController != null
+ && satelliteController.shouldSendSmsToDatagramDispatcher(mPhone)) {
+ satelliteController.onSmsReceived(mPhone.getSubId());
}
- satelliteController.onSmsReceived(mPhone.getSubId());
}
}
@@ -759,6 +759,20 @@
return Intents.RESULT_SMS_HANDLED;
}
+ if (isMtSmsPollingMessage(smsb)) {
+ log("Received MT SMS polling message. Ignored.");
+ return Intents.RESULT_SMS_HANDLED;
+ }
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ if (satelliteController != null
+ && satelliteController.shouldDropSms(mPhone)) {
+ log("SMS not supported during satellite session.");
+ return Intents.RESULT_SMS_HANDLED;
+ }
+ }
+
int result = dispatchMessageRadioSpecific(smsb, smsSource, token);
// In case of error, add to metrics. This is not required in case of success, as the
@@ -766,8 +780,7 @@
if (result != Intents.RESULT_SMS_HANDLED && result != Activity.RESULT_OK) {
mMetrics.writeIncomingSmsError(mPhone.getPhoneId(), is3gpp2(), smsSource, result);
mPhone.getSmsStats().onIncomingSmsError(is3gpp2(), smsSource, result,
- TelephonyManager.from(mContext)
- .isEmergencyNumber(smsb.getOriginatingAddress()));
+ isEmergencyNumber(smsb.getOriginatingAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1046,7 +1059,7 @@
logeWithLocalLog(errorMsg, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsError(
is3gpp2(), tracker.getSource(), RESULT_SMS_NULL_PDU,
- TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1076,8 +1089,7 @@
tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(),
messageCount, RESULT_SMS_NULL_MESSAGE, tracker.getMessageId(),
- TelephonyManager.from(mContext)
- .isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
return false;
}
}
@@ -1112,8 +1124,7 @@
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), tracker.getSource(),
format, timestamps, wapPushResult, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(), messageCount,
- result, tracker.getMessageId(), TelephonyManager.from(mContext)
- .isEmergencyNumber(tracker.getAddress()));
+ result, tracker.getMessageId(), isEmergencyNumber(tracker.getAddress()));
// result is Activity.RESULT_OK if an ordered broadcast was sent
if (result == Activity.RESULT_OK) {
return true;
@@ -1134,7 +1145,7 @@
format, timestamps, block, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsSuccess(is3gpp2(), tracker.getSource(),
messageCount, block, tracker.getMessageId(),
- TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
+ isEmergencyNumber(tracker.getAddress()));
CarrierRoamingSatelliteSessionStats sessionStats =
CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId());
sessionStats.onIncomingSms(mPhone.getSubId());
@@ -1172,6 +1183,13 @@
return true;
}
+ private boolean isEmergencyNumber(String number) {
+ if (!mPhone.hasCalling()) return false;
+ TelephonyManager manager = TelephonyManager.from(mContext);
+ if (manager == null) return false;
+ return manager.isEmergencyNumber(number);
+ }
+
/**
* Processes the message part while the credential-encrypted storage is still locked.
*
@@ -1982,6 +2000,17 @@
sendMessage(EVENT_BROADCAST_COMPLETE);
}
+ private boolean isMtSmsPollingMessage(@NonNull SmsMessageBase smsb) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()
+ || !mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling)) {
+ return false;
+ }
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ return !TextUtils.isEmpty(mtSmsPollingText)
+ && mtSmsPollingText.equals(smsb.getMessageBody());
+ }
+
/** Checks whether the flag to skip new message notification is set in the bitmask returned
* from the carrier app.
*/
diff --git a/src/java/com/android/internal/telephony/NetworkResponse.java b/src/java/com/android/internal/telephony/NetworkResponse.java
index b4a37b3..ccf066f 100644
--- a/src/java/com/android/internal/telephony/NetworkResponse.java
+++ b/src/java/com/android/internal/telephony/NetworkResponse.java
@@ -551,6 +551,36 @@
}
}
+ /**
+ * @param responseInfo Response info struct containing response type, serial no. and error
+ */
+ public void setSatellitePlmnResponse(RadioResponseInfo responseInfo) {
+ RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+ }
+
+ /**
+ * @param responseInfo Response info struct containing response type, serial no. and error
+ */
+ public void setSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo) {
+ RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+ }
+
+ /**
+ * @param responseInfo Response info struct containing response type, serial no. and error.
+ * @param isEnabled Indicates whether satellite is enabled for carrier or not.
+ */
+ public void isSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo,
+ boolean isEnabled) {
+ RILRequest rr = mRil.processResponse(HAL_SERVICE_NETWORK, responseInfo);
+
+ if (rr != null) {
+ if (responseInfo.error == RadioError.NONE) {
+ RadioResponse.sendMessageResponse(rr.mResult, isEnabled);
+ }
+ mRil.processResponseDone(rr, responseInfo, isEnabled);
+ }
+ }
+
@Override
public String getInterfaceHash() {
return IRadioNetworkResponse.HASH;
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 081a5c8..b12a3df 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -22,7 +22,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+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.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
@@ -233,6 +239,72 @@
private boolean mDoesPccListIndicateIdle = false;
private boolean mInVoiceCall = false;
+ private boolean mIsSatelliteConstrainedData = false;
+ private boolean mIsSatelliteNetworkCallbackRegistered = false;
+ private ConnectivityManager mConnectivityManager;
+
+ private final ConnectivityManager.NetworkCallback mNetworkCallback =
+ new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ log("On Available: " + network);
+ if (network != null) {
+ if (mConnectivityManager != null) {
+ NetworkCapabilities capabilities =
+ mConnectivityManager.getNetworkCapabilities(network);
+ updateBandwidthConstrainedStatus(capabilities);
+ } else {
+ log("network is null");
+ }
+ }
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network,
+ NetworkCapabilities networkCapabilities) {
+ log("onCapabilitiesChanged: " + network);
+ if (network != null) {
+ updateBandwidthConstrainedStatus(networkCapabilities);
+ } else {
+ log("network is null");
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ log("Network Lost");
+ if (mIsSatelliteConstrainedData) {
+ mIsSatelliteConstrainedData = false;
+ mDisplayInfoController.updateTelephonyDisplayInfo();
+ }
+ }
+ };
+
+ private boolean isBandwidthConstrainedCapabilitySupported(NetworkCapabilities
+ capabilities) {
+ // TODO (b/382002908: Remove try catch exception for
+ // NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED & replace datautils with
+ // NetworkCapabilities on api availability at mainline module)
+ try {
+ return capabilities.hasTransport(
+ NetworkCapabilities.TRANSPORT_SATELLITE) &&
+ !capabilities.hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+ } catch (Exception ignored) {
+ log("NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED not supported ");
+ return false;
+ }
+ }
+
+ private void updateBandwidthConstrainedStatus(NetworkCapabilities capabilities) {
+ if (capabilities != null) {
+ mIsSatelliteConstrainedData
+ = isBandwidthConstrainedCapabilitySupported(capabilities);
+ log("satellite constrained data status : " + mIsSatelliteConstrainedData);
+ mDisplayInfoController.updateTelephonyDisplayInfo();
+ } else {
+ log("capabilities is null");
+ }
+ }
/**
* NetworkTypeController constructor.
@@ -266,9 +338,42 @@
mServiceState = mPhone.getServiceStateTracker().getServiceState();
mPhysicalChannelConfigs = mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
+ if(mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ registerForSatelliteNetwork();
+ }
+
sendMessage(EVENT_INITIALIZE);
}
+ public synchronized void registerForSatelliteNetwork() {
+ if (!mIsSatelliteNetworkCallbackRegistered) {
+ mIsSatelliteNetworkCallbackRegistered = true;
+ HandlerThread handlerThread = new HandlerThread("SatelliteDataUsageThread");
+ handlerThread.start();
+ Handler handler = new Handler(handlerThread.getLooper());
+
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ // TODO (b/382002908: Remove try catch exception for
+ // NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED & replace datautils with
+ // NetworkCapabilities on api availability at mainline module)
+ try {
+ builder.removeCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+ } catch (Exception ignored) {
+ log("NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED not supported ");
+ }
+ mConnectivityManager =
+ (ConnectivityManager) mPhone.getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (mConnectivityManager != null) {
+ mConnectivityManager.registerBestMatchingNetworkCallback(
+ builder.build(), mNetworkCallback, handler);
+ } else {
+ loge("network callback not registered");
+ }
+ }
+ }
+
/**
* @return The current override network type, used to create TelephonyDisplayInfo in
* DisplayInfoController.
@@ -289,6 +394,15 @@
}
/**
+ * @return satellite bandwidth constrained connection status, used to create
+ * TelephonyDisplayInfo in DisplayInfoController.
+ *
+ */
+ public boolean getSatelliteConstrainedData() {
+ return mIsSatelliteConstrainedData;
+ }
+
+ /**
* @return {@code true} if either the primary or secondary 5G icon timers are active,
* and {@code false} if neither are.
*/
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 61f1d45..0c645a0 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -74,6 +74,7 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.NtnSignalStrength;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -126,6 +127,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -659,7 +661,7 @@
mSmsStorageMonitor = mTelephonyComponentFactory.inject(SmsStorageMonitor.class.getName())
.makeSmsStorageMonitor(this, mFeatureFlags);
mSmsUsageMonitor = mTelephonyComponentFactory.inject(SmsUsageMonitor.class.getName())
- .makeSmsUsageMonitor(context);
+ .makeSmsUsageMonitor(context, mFeatureFlags);
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
mSimActivationTracker = mTelephonyComponentFactory
@@ -1965,6 +1967,13 @@
}
/**
+ * @return true if this device supports calling, false otherwise.
+ */
+ public boolean hasCalling() {
+ return TelephonyCapabilities.supportsTelephonyCalling(mFeatureFlags, mContext);
+ }
+
+ /**
* Retrieves the EmergencyNumberTracker of the phone instance.
*/
public EmergencyNumberTracker getEmergencyNumberTracker() {
@@ -2275,6 +2284,7 @@
* @param response is callback message to report one of TelephonyManager#CDMA_ROAMING_MODE_*
*/
public void queryCdmaRoamingPreference(Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.queryCdmaRoamingPreference(response);
}
@@ -2284,6 +2294,7 @@
* @param response is callback message to report one of TelephonyManager#CDMA_SUBSCRIPTION_*
*/
public void queryCdmaSubscriptionMode(Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.getCdmaSubscriptionSource(response);
}
@@ -2321,6 +2332,7 @@
* @param response is callback message
*/
public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.setCdmaRoamingPreference(cdmaRoamingType, response);
}
@@ -2330,6 +2342,7 @@
* @param response is callback message
*/
public void setCdmaSubscriptionMode(int cdmaSubscriptionType, Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
}
@@ -2766,6 +2779,7 @@
* @param workSource calling WorkSource
*/
public void nvReadItem(int itemID, Message response, WorkSource workSource) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.nvReadItem(itemID, response, workSource);
}
@@ -2780,6 +2794,7 @@
*/
public void nvWriteItem(int itemID, String itemValue, Message response,
WorkSource workSource) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.nvWriteItem(itemID, itemValue, response, workSource);
}
@@ -2791,6 +2806,7 @@
* @param response Callback message.
*/
public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.nvWriteCdmaPrl(preferredRoamingList, response);
}
@@ -2812,6 +2828,7 @@
* @param response Callback message.
*/
public void resetModemConfig(Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.nvResetConfig(3 /* factory NV reset */, response);
}
@@ -2821,6 +2838,7 @@
* @param response Callback message.
*/
public void eraseModemConfig(Message response) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.nvResetConfig(2 /* erase NV */, response);
}
@@ -3502,6 +3520,7 @@
* @param obj User object.
*/
public void registerForNumberInfo(Handler h, int what, Object obj) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.registerForNumberInfo(h, what, obj);
}
@@ -3512,6 +3531,7 @@
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForNumberInfo(Handler h) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.unregisterForNumberInfo(h);
}
@@ -3527,6 +3547,7 @@
* @param obj User object.
*/
public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.registerForRedirectedNumberInfo(h, what, obj);
}
@@ -3537,6 +3558,7 @@
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForRedirectedNumberInfo(Handler h) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.unregisterForRedirectedNumberInfo(h);
}
@@ -3552,6 +3574,7 @@
* @param obj User object.
*/
public void registerForLineControlInfo(Handler h, int what, Object obj) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.registerForLineControlInfo(h, what, obj);
}
@@ -3562,6 +3585,7 @@
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForLineControlInfo(Handler h) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.unregisterForLineControlInfo(h);
}
@@ -3577,6 +3601,7 @@
* @param obj User object.
*/
public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.registerFoT53ClirlInfo(h, what, obj);
}
@@ -3587,6 +3612,7 @@
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForT53ClirInfo(Handler h) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.unregisterForT53ClirInfo(h);
}
@@ -3602,6 +3628,7 @@
* @param obj User object.
*/
public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.registerForT53AudioControlInfo(h, what, obj);
}
@@ -3612,6 +3639,7 @@
* @param h Handler to be removed from the registrant list.
*/
public void unregisterForT53AudioControlInfo(Handler h) {
+ if (mFeatureFlags.cleanupCdma()) return;
mCi.unregisterForT53AudioControlInfo(h);
}
@@ -4067,6 +4095,16 @@
}
/**
+ * Resets the Carrier Keys in the database. This involves 2 steps:
+ * 1. Delete the keys from the database.
+ * 2. Send an intent to download new Certificates.
+ *
+ * @param forceResetAll : Force delete the downloaded key if any.
+ */
+ public void resetCarrierKeysForImsiEncryption(boolean forceResetAll) {
+ }
+
+ /**
* Return if UT capability of ImsPhone is enabled or not
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -4140,8 +4178,11 @@
setRoamingOverrideHelper(gsmRoamingList, GSM_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
setRoamingOverrideHelper(gsmNonRoamingList, GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
- setRoamingOverrideHelper(cdmaRoamingList, CDMA_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
- setRoamingOverrideHelper(cdmaNonRoamingList, CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
+ if (!mFeatureFlags.cleanupCdma()) {
+ setRoamingOverrideHelper(cdmaRoamingList, CDMA_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
+ setRoamingOverrideHelper(cdmaNonRoamingList, CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX,
+ iccId);
+ }
// Refresh.
ServiceStateTracker tracker = getServiceStateTracker();
@@ -5368,6 +5409,29 @@
mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
}
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial available services changed.
+ * @param availableServices The list of the supported services.
+ */
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ logd("notifyCarrierRoamingNtnAvailableServicesChanged availableServices:"
+ + Arrays.toString(availableServices));
+ mNotifier.notifyCarrierRoamingNtnAvailableServicesChanged(this, availableServices);
+ }
+
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial network
+ * signal strength changed.
+ * @param ntnSignalStrength non-terrestrial network signal strength.
+ */
+ public void notifyCarrierRoamingNtnSignalStrengthChanged(
+ @NonNull NtnSignalStrength ntnSignalStrength) {
+ logd("notifyCarrierRoamingNtnSignalStrengthChanged: ntnSignalStrength="
+ + ntnSignalStrength.getLevel());
+ mNotifier.notifyCarrierRoamingNtnSignalStrengthChanged(this, ntnSignalStrength);
+ }
+
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/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index a43ff72..6c8b222 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -25,10 +25,13 @@
import android.telephony.CallQuality;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.LinkCapacityEstimate;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager.DataEnabledReason;
@@ -37,6 +40,7 @@
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.MediaQualityStatus;
+import android.telephony.satellite.NtnSignalStrength;
import java.util.List;
import java.util.Set;
@@ -164,4 +168,19 @@
/** Notify eligibility to connect to carrier roaming non-terrestrial network changed. */
void notifyCarrierRoamingNtnEligibleStateChanged(Phone sender, boolean eligible);
+
+ /** Notify carrier roaming non-terrestrial available services changed. */
+ void notifyCarrierRoamingNtnAvailableServicesChanged(
+ Phone sender, @NetworkRegistrationInfo.ServiceType int[] availableServices);
+
+ /** Notify carrier roaming non-terrestrial network signal strength changed. */
+ void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
+ @NonNull NtnSignalStrength ntnSignalStrength);
+
+ /** Notify of a cellular identifier disclosure change. */
+ void notifyCellularIdentifierDisclosedChanged(Phone sender,
+ CellularIdentifierDisclosure disclosure);
+
+ /** Notify of a security algorithm update change. */
+ void notifySecurityAlgorithmsChanged(Phone sender, SecurityAlgorithmUpdate update);
}
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 7ee3de2..9801542 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -53,7 +53,9 @@
import com.android.telephony.Rlog;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
private static final String TAG = "PhoneSubInfoController";
@@ -477,39 +479,37 @@
*
* @param subId subscriptionId
* @param callingPackage package name of the caller
- * @param callingFeatureId feature Id of the caller
* @return List of public user identities of type android.net.Uri or empty list if
* EF_IMPU is not available.
* @throws IllegalArgumentException if the subscriptionId is not valid
* @throws IllegalStateException in case the ISIM hasn’t been loaded.
* @throws SecurityException if the caller does not have the required permission
*/
- public List<Uri> getImsPublicUserIdentities(int subId, String callingPackage,
- String callingFeatureId) {
- if (TelephonyPermissions.
- checkCallingOrSelfReadPrivilegedPhoneStatePermissionOrReadPhoneNumber(
- mContext, subId, callingPackage, callingFeatureId, "getImsPublicUserIdentities")) {
-
- enforceTelephonyFeatureWithException(callingPackage,
- PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPublicUserIdentities");
-
- Phone phone = getPhone(subId);
- assert phone != null;
- IsimRecords isimRecords = phone.getIsimRecords();
- if (isimRecords != null) {
- String[] impus = isimRecords.getIsimImpu();
- List<Uri> impuList = new ArrayList<>();
- for (String impu : impus) {
- if (impu != null && impu.trim().length() > 0) {
- impuList.add(Uri.parse(impu));
- }
- }
- return impuList;
- }
- throw new IllegalStateException("ISIM is not loaded");
- } else {
- throw new IllegalArgumentException("Invalid SubscriptionID = " + subId);
+ public List<Uri> getImsPublicUserIdentities(int subId, String callingPackage) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription: " + subId);
}
+
+ TelephonyPermissions
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mContext, subId, "getImsPublicUserIdentities");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPublicUserIdentities");
+
+ Phone phone = getPhone(subId);
+ assert phone != null;
+ IsimRecords isimRecords = phone.getIsimRecords();
+ if (isimRecords != null) {
+ String[] impus = isimRecords.getIsimImpu();
+ List<Uri> impuList = new ArrayList<>();
+ for (String impu : impus) {
+ if (impu != null && impu.trim().length() > 0) {
+ impuList.add(Uri.parse(impu));
+ }
+ }
+ return impuList;
+ }
+ throw new IllegalStateException("ISIM is not loaded");
}
/**
@@ -546,6 +546,45 @@
}
/**
+ * Fetches the IMS Proxy Call Session Control Function(P-CSCF) based on the subscription.
+ *
+ * @param subId subscriptionId
+ * @param callingPackage package name of the caller
+ * @return List of IMS Proxy Call Session Control Function strings.
+ * @throws IllegalArgumentException if the subscriptionId is not valid
+ * @throws IllegalStateException in case the ISIM hasn’t been loaded.
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ public List<String> getImsPcscfAddresses(int subId, String callingPackage) {
+ if (!mFeatureFlags.supportIsimRecord()) {
+ return new ArrayList<>();
+ }
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription: " + subId);
+ }
+
+ TelephonyPermissions
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ mContext, subId, "getImsPcscfAddresses");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getImsPcscfAddresses");
+
+ Phone phone = getPhone(subId);
+ assert phone != null;
+ IsimRecords isimRecords = phone.getIsimRecords();
+ if (isimRecords != null) {
+ String[] pcscfs = isimRecords.getIsimPcscf();
+ List<String> pcscfList = Arrays.stream(pcscfs)
+ .filter(u -> u != null)
+ .map(u -> u.trim())
+ .filter(u -> u.length() > 0)
+ .collect(Collectors.toList());
+ return pcscfList;
+ }
+ throw new IllegalStateException("ISIM is not loaded");
+ }
+
+ /**
* Returns the USIM service table that fetched from EFUST elementary field that are loaded
* based on the appType.
*/
@@ -620,6 +659,20 @@
});
}
+ /**
+ * Return GroupIdLevel2 for the subscriber
+ */
+ public String getGroupIdLevel2ForSubscriber(int subId, String callingPackage,
+ String callingFeatureId) {
+ return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
+ "getGroupIdLevel2", (phone)-> {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getGroupIdLevel2ForSubscriber");
+ return phone.getGroupIdLevel2();
+ });
+ }
+
/** Below are utility methods that abstracts the flow that many public methods use:
* 1. Check permission: pass, throw exception, or fails (returns false).
* 2. clearCallingIdentity.
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 88ead6f..b2550a2 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -178,6 +178,12 @@
/** @hide */
public static final HalVersion RADIO_HAL_VERSION_2_2 = new HalVersion(2, 2);
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_2_3 = new HalVersion(2, 3);
+
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_2_4 = new HalVersion(2, 4);
+
// Hal version
private final Map<Integer, HalVersion> mHalVersion = new HashMap<>();
@@ -1119,6 +1125,9 @@
SparseArray<RadioServiceProxy> proxies, @NonNull FeatureFlags flags) {
super(context);
mFeatureFlags = flags;
+ if (mFeatureFlags.cleanupCdma()) {
+ cdmaSubscription = TelephonyManager.CDMA_SUBSCRIPTION_UNKNOWN;
+ }
if (RILJ_LOGD) {
riljLog("RIL: init allowedNetworkTypes=" + allowedNetworkTypes
+ " cdmaSubscription=" + cdmaSubscription + ")");
@@ -3212,6 +3221,8 @@
@Override
public void setCdmaSubscriptionSource(int cdmaSubscription, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioSimProxy simProxy = getRadioServiceProxy(RadioSimProxy.class);
if (!canMakeRequest("setCdmaSubscriptionSource", simProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -3232,6 +3243,8 @@
@Override
public void queryCdmaRoamingPreference(Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
if (!canMakeRequest("queryCdmaRoamingPreference", networkProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3252,6 +3265,8 @@
@Override
public void setCdmaRoamingPreference(int cdmaRoamingType, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
if (!canMakeRequest("setCdmaRoamingPreference", networkProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3351,6 +3366,8 @@
@Override
public void sendCDMAFeatureCode(String featureCode, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioVoiceProxy voiceProxy = getRadioServiceProxy(RadioVoiceProxy.class);
if (!canMakeRequest("sendCDMAFeatureCode", voiceProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -3391,6 +3408,8 @@
@Override
public void sendCdmaSMSExpectMore(byte[] pdu, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("sendCdmaSMSExpectMore", messagingProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3417,6 +3436,8 @@
@Override
public void sendCdmaSms(byte[] pdu, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("sendCdmaSms", messagingProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -3438,6 +3459,8 @@
@Override
public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("acknowledgeLastIncomingCdmaSms", messagingProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3525,6 +3548,8 @@
@Override
public void getCdmaBroadcastConfig(Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("getCdmaBroadcastConfig", messagingProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3545,6 +3570,8 @@
@Override
public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("setCdmaBroadcastConfig", messagingProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3569,6 +3596,8 @@
@Override
public void setCdmaBroadcastActivation(boolean activate, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("setCdmaBroadcastActivation", messagingProxy, result,
RADIO_HAL_VERSION_1_4)) {
@@ -3590,6 +3619,8 @@
@Override
public void getCDMASubscription(Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioSimProxy simProxy = getRadioServiceProxy(RadioSimProxy.class);
if (!canMakeRequest("getCDMASubscription", simProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -3628,6 +3659,8 @@
@Override
public void deleteSmsOnRuim(int index, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioMessagingProxy messagingProxy = getRadioServiceProxy(RadioMessagingProxy.class);
if (!canMakeRequest("deleteSmsOnRuim", messagingProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -3781,6 +3814,8 @@
@Override
public void getCdmaSubscriptionSource(Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioSimProxy simProxy = getRadioServiceProxy(RadioSimProxy.class);
if (!canMakeRequest("getCdmaSubscriptionSource", simProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -4068,6 +4103,8 @@
@Override
public void nvReadItem(int itemID, Message result, WorkSource workSource) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
if (!canMakeRequest("nvReadItem", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -4088,6 +4125,8 @@
@Override
public void nvWriteItem(int itemId, String itemValue, Message result, WorkSource workSource) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
if (!canMakeRequest("nvWriteItem", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -4109,6 +4148,8 @@
@Override
public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message result) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
if (!canMakeRequest("nvWriteCdmaPrl", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -4129,6 +4170,9 @@
@Override
public void nvResetConfig(int resetType, Message result) {
+ // Disable all NV reset functions except modem restart.
+ if (mFeatureFlags.cleanupCdma() && resetType != 1) return;
+
RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
if (!canMakeRequest("nvResetConfig", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
return;
@@ -5349,6 +5393,102 @@
});
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setSatellitePlmn(int simSlot, @NonNull List<String> carrierPlmnList,
+ @NonNull List<String> allSatellitePlmnList, Message result) {
+ RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+ if (!canMakeRequest(
+ "setSatellitePlmn",
+ networkProxy,
+ result,
+ RADIO_HAL_VERSION_2_4)) {
+ return;
+ }
+
+ RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_PLMN, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ + " simSlot=" + simSlot + " carrierPlmnList=" + carrierPlmnList
+ + " allSatellitePlmnList=" + allSatellitePlmnList);
+ }
+
+ radioServiceInvokeHelper(
+ HAL_SERVICE_NETWORK,
+ rr,
+ "setSatellitePlmn",
+ () -> {
+ networkProxy.setSatellitePlmn(rr.mSerial, simSlot, carrierPlmnList,
+ allSatellitePlmnList);
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+ Message result) {
+ RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+ if (!canMakeRequest(
+ "setSatelliteEnabledForCarrier",
+ networkProxy,
+ result,
+ RADIO_HAL_VERSION_2_4)) {
+ return;
+ }
+
+ RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ + " simSlot=" + simSlot + " satelliteEnabled=" + satelliteEnabled);
+ }
+
+ radioServiceInvokeHelper(
+ HAL_SERVICE_NETWORK,
+ rr,
+ "setSatelliteEnabledForCarrier",
+ () -> {
+ networkProxy.setSatelliteEnabledForCarrier(rr.mSerial, simSlot,
+ satelliteEnabled);
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void isSatelliteEnabledForCarrier(int simSlot, Message result) {
+ RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+ if (!canMakeRequest(
+ "isSatelliteEnabledForCarrier",
+ networkProxy,
+ result,
+ RADIO_HAL_VERSION_2_4)) {
+ return;
+ }
+
+ RILRequest rr = obtainRequest(RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER, result,
+ mRILDefaultWorkSource);
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ + " simSlot=" + simSlot);
+ }
+
+ radioServiceInvokeHelper(
+ HAL_SERVICE_NETWORK, rr, "isSatelliteEnabledForCarrier", () -> {
+ networkProxy.isSatelliteEnabledForCarrier(rr.mSerial, simSlot);
+ });
+ }
+
+
//***** Private Methods
/**
* This is a helper function to be called when an indication callback is called for any radio
@@ -6016,6 +6156,8 @@
@UnsupportedAppUsage
void notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) {
+ if (mFeatureFlags.cleanupCdma()) return;
+
int response = RIL_UNSOL_CDMA_INFO_REC;
if (infoRec.record instanceof CdmaInformationRecords.CdmaDisplayInfoRec) {
if (mDisplayInfoRegistrants != null) {
@@ -6212,6 +6354,8 @@
case 1: return RADIO_HAL_VERSION_2_0;
case 2: return RADIO_HAL_VERSION_2_1;
case 3: return RADIO_HAL_VERSION_2_2;
+ case 4: return RADIO_HAL_VERSION_2_3;
+ case 5: return RADIO_HAL_VERSION_2_4;
default: return RADIO_HAL_VERSION_UNKNOWN;
}
}
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index a81dbc8..fb07fb3 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -121,6 +121,7 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_N1_MODE_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SECURITY_ALGORITHMS_UPDATED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_VONR_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
@@ -180,6 +181,8 @@
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_PLMN;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
@@ -384,6 +387,7 @@
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.telephony.data.KeepaliveStatus;
import com.android.internal.telephony.data.KeepaliveStatus.KeepaliveStatusCode;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.imsphone.ImsCallInfo;
import com.android.internal.telephony.uicc.AdnCapacity;
import com.android.internal.telephony.uicc.IccCardApplicationStatus;
@@ -394,6 +398,7 @@
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.PortUtils;
import com.android.internal.telephony.uicc.SimPhonebookRecord;
+import com.android.internal.telephony.uicc.SimTypeInfo;
import com.android.telephony.Rlog;
import java.io.ByteArrayInputStream;
@@ -1169,6 +1174,10 @@
* 2 - erase NV reset (SCRTN)
* 3 - factory reset (RTN)
*/
+ if (Flags.cleanupCdma()) {
+ if (resetType == 1) return android.hardware.radio.V1_0.ResetNvType.RELOAD;
+ return -1;
+ }
switch (resetType) {
case 1: return android.hardware.radio.V1_0.ResetNvType.RELOAD;
case 2: return android.hardware.radio.V1_0.ResetNvType.ERASE;
@@ -1189,6 +1198,10 @@
* 2 - erase NV reset (SCRTN)
* 3 - factory reset (RTN)
*/
+ if (Flags.cleanupCdma()) {
+ if (resetType == 1) return android.hardware.radio.modem.ResetNvType.RELOAD;
+ return -1;
+ }
switch (resetType) {
case 1: return android.hardware.radio.modem.ResetNvType.RELOAD;
case 2: return android.hardware.radio.modem.ResetNvType.ERASE;
@@ -2913,6 +2926,7 @@
*/
public static CellSignalStrengthGsm convertHalGsmSignalStrength(
android.hardware.radio.V1_0.GsmSignalStrength ss) {
+ if (ss == null) return new CellSignalStrengthGsm();
CellSignalStrengthGsm ret = new CellSignalStrengthGsm(
CellSignalStrength.getRssiDbmFromAsu(ss.signalStrength), ss.bitErrorRate,
ss.timingAdvance);
@@ -2930,6 +2944,7 @@
*/
public static CellSignalStrengthGsm convertHalGsmSignalStrength(
android.hardware.radio.network.GsmSignalStrength ss) {
+ if (ss == null) return new CellSignalStrengthGsm();
CellSignalStrengthGsm ret = new CellSignalStrengthGsm(
CellSignalStrength.getRssiDbmFromAsu(ss.signalStrength), ss.bitErrorRate,
ss.timingAdvance);
@@ -2950,6 +2965,7 @@
public static CellSignalStrengthCdma convertHalCdmaSignalStrength(
android.hardware.radio.V1_0.CdmaSignalStrength cdma,
android.hardware.radio.V1_0.EvdoSignalStrength evdo) {
+ if (cdma == null || evdo == null) return new CellSignalStrengthCdma();
return new CellSignalStrengthCdma(-cdma.dbm, -cdma.ecio, -evdo.dbm, -evdo.ecio,
evdo.signalNoiseRatio);
}
@@ -2964,6 +2980,7 @@
public static CellSignalStrengthCdma convertHalCdmaSignalStrength(
android.hardware.radio.network.CdmaSignalStrength cdma,
android.hardware.radio.network.EvdoSignalStrength evdo) {
+ if (cdma == null || evdo == null) return new CellSignalStrengthCdma();
return new CellSignalStrengthCdma(-cdma.dbm, -cdma.ecio, -evdo.dbm, -evdo.ecio,
evdo.signalNoiseRatio);
}
@@ -3427,9 +3444,11 @@
android.hardware.radio.data.SetupDataCallResult result) {
if (result == null) return null;
List<LinkAddress> laList = new ArrayList<>();
- for (android.hardware.radio.data.LinkAddress la : result.addresses) {
- laList.add(convertToLinkAddress(la.address, la.addressProperties,
- la.deprecationTime, la.expirationTime));
+ if (result.addresses != null) {
+ for (android.hardware.radio.data.LinkAddress la : result.addresses) {
+ laList.add(convertToLinkAddress(la.address, la.addressProperties,
+ la.deprecationTime, la.expirationTime));
+ }
}
List<InetAddress> dnsList = new ArrayList<>();
if (result.dnses != null) {
@@ -3471,15 +3490,19 @@
}
}
List<QosBearerSession> qosSessions = new ArrayList<>();
- for (android.hardware.radio.data.QosSession session : result.qosSessions) {
- qosSessions.add(convertHalQosBearerSession(session));
+ if (result.qosSessions != null) {
+ for (android.hardware.radio.data.QosSession session : result.qosSessions) {
+ qosSessions.add(convertHalQosBearerSession(session));
+ }
}
List<TrafficDescriptor> trafficDescriptors = new ArrayList<>();
- for (android.hardware.radio.data.TrafficDescriptor td : result.trafficDescriptors) {
- try {
- trafficDescriptors.add(convertHalTrafficDescriptor(td));
- } catch (IllegalArgumentException e) {
- loge("convertHalDataCallResult: Failed to convert traffic descriptor. e=" + e);
+ if (result.trafficDescriptors != null) {
+ for (android.hardware.radio.data.TrafficDescriptor td : result.trafficDescriptors) {
+ try {
+ trafficDescriptors.add(convertHalTrafficDescriptor(td));
+ } catch (IllegalArgumentException e) {
+ loge("convertHalDataCallResult: Failed to convert traffic descriptor. e=" + e);
+ }
}
}
@@ -3659,6 +3682,7 @@
}
private static Qos convertHalQos(android.hardware.radio.V1_6.Qos qos) {
+ if (qos == null) return null;
switch (qos.getDiscriminator()) {
case android.hardware.radio.V1_6.Qos.hidl_discriminator.eps:
android.hardware.radio.V1_6.EpsQos eps = qos.eps();
@@ -3674,6 +3698,7 @@
}
private static Qos convertHalQos(android.hardware.radio.data.Qos qos) {
+ if (qos == null) return null;
switch (qos.getTag()) {
case android.hardware.radio.data.Qos.eps:
android.hardware.radio.data.EpsQos eps = qos.getEps();
@@ -4132,6 +4157,34 @@
}
/**
+ * This API is for fallback to support getAllowedCarriers too.
+ *
+ * Convert an array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl to a list of CarrierIdentifiers.
+ *
+ * @param carrierInfos array of CarrierInfo defined in
+ * radio/aidl/android/hardware/radio/sim/CarrierInfo.aidl
+ * @return The converted list of CarrierIdentifiers
+ */
+ public static List<CarrierIdentifier> convertAidlCarrierInfoListToHalCarrierList(
+ android.hardware.radio.sim.CarrierInfo[] carrierInfos) {
+ List<CarrierIdentifier> ret = new ArrayList<>();
+ if (carrierInfos == null) {
+ return ret;
+ }
+ for (android.hardware.radio.sim.CarrierInfo carrierInfo : carrierInfos) {
+ String mcc = carrierInfo.mcc;
+ String mnc = carrierInfo.mnc;
+ String spn = carrierInfo.spn;
+ String imsi = carrierInfo.imsiPrefix;
+ String gid1 = carrierInfo.gid1;
+ String gid2 = carrierInfo.gid2;
+ ret.add(new CarrierIdentifier(mcc, mnc, spn, imsi, gid1, gid2));
+ }
+ return ret;
+ }
+
+ /**
* Convert the sim policy defined in
* radio/aidl/android/hardware/radio/sim/SimLockMultiSimPolicy.aidl to the equivalent sim
* policy defined in android.telephony/CarrierRestrictionRules.MultiSimPolicy
@@ -4191,7 +4244,8 @@
iccCardStatus.setCardState(cardStatus10.cardState);
iccCardStatus.setUniversalPinState(cardStatus10.universalPinState);
iccCardStatus.mGsmUmtsSubscriptionAppIndex = cardStatus10.gsmUmtsSubscriptionAppIndex;
- iccCardStatus.mCdmaSubscriptionAppIndex = cardStatus10.cdmaSubscriptionAppIndex;
+ iccCardStatus.mCdmaSubscriptionAppIndex =
+ Flags.cleanupCdma() ? -1 : cardStatus10.cdmaSubscriptionAppIndex;
iccCardStatus.mImsSubscriptionAppIndex = cardStatus10.imsSubscriptionAppIndex;
int numApplications = cardStatus10.applications.size();
@@ -4261,7 +4315,8 @@
iccCardStatus.setMultipleEnabledProfilesMode(cardStatus.supportedMepMode);
iccCardStatus.setUniversalPinState(cardStatus.universalPinState);
iccCardStatus.mGsmUmtsSubscriptionAppIndex = cardStatus.gsmUmtsSubscriptionAppIndex;
- iccCardStatus.mCdmaSubscriptionAppIndex = cardStatus.cdmaSubscriptionAppIndex;
+ iccCardStatus.mCdmaSubscriptionAppIndex =
+ Flags.cleanupCdma() ? -1 : cardStatus.cdmaSubscriptionAppIndex;
iccCardStatus.mImsSubscriptionAppIndex = cardStatus.imsSubscriptionAppIndex;
iccCardStatus.atr = cardStatus.atr;
iccCardStatus.iccid = cardStatus.iccid;
@@ -5260,6 +5315,12 @@
return "IS_SECURITY_ALGORITHMS_UPDATED_ENABLED";
case RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT:
return "GET_SIMULTANEOUS_CALLING_SUPPORT";
+ case RIL_REQUEST_SET_SATELLITE_PLMN:
+ return "SET_SATELLITE_PLMN";
+ case RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER:
+ return "SET_SATELLITE_ENABLED_FOR_CARRIER";
+ case RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER:
+ return "IS_SATELLITE_ENABLED_FOR_CARRIER";
default:
return "<unknown request " + request + ">";
}
@@ -5842,6 +5903,23 @@
securityAlgorithmUpdate.isUnprotectedEmergency);
}
+ /** Convert an AIDL-based SimTypeInfo to its Java wrapper. */
+ public static ArrayList<SimTypeInfo> convertAidlSimTypeInfo(
+ android.hardware.radio.config.SimTypeInfo[] simTypeInfos) {
+ ArrayList<SimTypeInfo> response = new ArrayList<>();
+ if (simTypeInfos == null) {
+ loge("convertAidlSimTypeInfo received NULL simTypeInfos");
+ return response;
+ }
+ for (android.hardware.radio.config.SimTypeInfo simTypeInfo : simTypeInfos) {
+ SimTypeInfo info = new SimTypeInfo();
+ info.mSupportedSimTypes = simTypeInfo.supportedSimTypes;
+ info.setCurrentSimType(simTypeInfo.currentSimType);
+ response.add(info);
+ }
+ return response;
+ }
+
private static void logd(String log) {
Rlog.d("RILUtils", log);
}
diff --git a/src/java/com/android/internal/telephony/RadioConfigProxy.java b/src/java/com/android/internal/telephony/RadioConfigProxy.java
index 9f34e29..153747b 100644
--- a/src/java/com/android/internal/telephony/RadioConfigProxy.java
+++ b/src/java/com/android/internal/telephony/RadioConfigProxy.java
@@ -281,7 +281,11 @@
}
public void linkToDeath(long cookie) throws RemoteException {
- mService.linkToDeath(this, cookie);
+ if (mService != null) {
+ mService.linkToDeath(this, cookie);
+ } else {
+ Rlog.w(TAG, "linkToDeath: skipping since mService is null");
+ }
}
public void clear() {
@@ -316,7 +320,11 @@
}
public void linkToDeath(int cookie) throws RemoteException {
- mService.linkToDeath(this, cookie);
+ if (mService != null) {
+ mService.linkToDeath(this, cookie);
+ } else {
+ Rlog.w(TAG, "linkToDeath: skipping since mService is null");
+ }
}
public void clear() {
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
index 0a41b11..6142fc2 100644
--- a/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
+++ b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
@@ -21,10 +21,10 @@
import android.telephony.PhoneCapability;
import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.internal.telephony.uicc.SimTypeInfo;
import com.android.telephony.Rlog;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Set;
/**
@@ -47,8 +47,7 @@
*/
@Override
public void getHalDeviceCapabilitiesResponse(
- android.hardware.radio.RadioResponseInfo info,
- boolean modemReducedFeatureSet1) throws RemoteException {
+ RadioResponseInfo info, boolean modemReducedFeatureSet1) throws RemoteException {
// convert hal device capabilities to RadioInterfaceCapabilities
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
@@ -71,8 +70,7 @@
*/
@Override
public void getNumOfLiveModemsResponse(
- android.hardware.radio.RadioResponseInfo info, byte numOfLiveModems)
- throws RemoteException {
+ RadioResponseInfo info, byte numOfLiveModems) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
if (info.error == android.hardware.radio.RadioError.NONE) {
@@ -93,9 +91,8 @@
*/
@Override
public void getPhoneCapabilityResponse(
- android.hardware.radio.RadioResponseInfo info,
- android.hardware.radio.config.PhoneCapability phoneCapability)
- throws RemoteException {
+ RadioResponseInfo info,
+ android.hardware.radio.config.PhoneCapability phoneCapability) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
PhoneCapability ret = RILUtils.convertHalPhoneCapability(
@@ -118,9 +115,7 @@
*/
@Override
public void getSimultaneousCallingSupportResponse(
- android.hardware.radio.RadioResponseInfo info,
- int[] enabledLogicalSlots)
- throws RemoteException {
+ RadioResponseInfo info, int[] enabledLogicalSlots) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
ArrayList<Integer> ret = RILUtils.primitiveArrayToArrayList(enabledLogicalSlots);
@@ -142,7 +137,7 @@
*/
@Override
public void getSimSlotsStatusResponse(
- android.hardware.radio.RadioResponseInfo info,
+ RadioResponseInfo info,
android.hardware.radio.config.SimSlotStatus[] slotStatus)
throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
@@ -166,8 +161,7 @@
* Currently this is being used as the callback for RadioConfig.setNumOfLiveModems() method
*/
@Override
- public void setNumOfLiveModemsResponse(
- android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+ public void setNumOfLiveModemsResponse(RadioResponseInfo info) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
if (info.error == android.hardware.radio.RadioError.NONE) {
@@ -187,8 +181,7 @@
* Response function for IRadioConfig.setPreferredDataModem().
*/
@Override
- public void setPreferredDataModemResponse(
- android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+ public void setPreferredDataModemResponse(RadioResponseInfo info) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
if (info.error == android.hardware.radio.RadioError.NONE) {
@@ -208,8 +201,7 @@
* Response function for IRadioConfig.setSimSlotsMapping().
*/
@Override
- public void setSimSlotsMappingResponse(
- android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+ public void setSimSlotsMappingResponse(RadioResponseInfo info) throws RemoteException {
RILRequest rr = mRadioConfig.processResponse(info);
if (rr != null) {
if (info.error == android.hardware.radio.RadioError.NONE) {
@@ -225,6 +217,48 @@
}
}
+ /**
+ * Response function for IRadioConfig.getSimTypeInfo().
+ */
+ @Override
+ public void getSimTypeInfoResponse(
+ RadioResponseInfo info,
+ android.hardware.radio.config.SimTypeInfo[] simTypeInfo) throws RemoteException {
+ RILRequest rr = mRadioConfig.processResponse(info);
+ if (rr != null) {
+ ArrayList<SimTypeInfo> ret = RILUtils.convertAidlSimTypeInfo(simTypeInfo);
+ if (info.error == android.hardware.radio.RadioError.NONE) {
+ // send response
+ RadioResponse.sendMessageResponse(rr.mResult, ret);
+ logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+ } else {
+ rr.onError(info.error, null);
+ loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+ }
+ } else {
+ loge("getSimTypeInfoResponse: Error " + info.toString());
+ }
+ }
+
+ /**
+ * Response function for IRadioConfig.setSimTypeResponse().
+ */
+ @Override
+ public void setSimTypeResponse(RadioResponseInfo info) throws RemoteException {
+ RILRequest rr = mRadioConfig.processResponse(info);
+ if (rr != null) {
+ if (info.error == android.hardware.radio.RadioError.NONE) {
+ // send response
+ RadioResponse.sendMessageResponse(rr.mResult, null);
+ logd(rr, RILUtils.requestToString(rr.mRequest));
+ } else {
+ rr.onError(info.error, null);
+ loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+ }
+ } else {
+ loge("setSimTypeResponse: Error " + info.toString());
+ }
+ }
private static void logd(String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/RadioMessagingProxy.java b/src/java/com/android/internal/telephony/RadioMessagingProxy.java
index c652284..624c82d 100644
--- a/src/java/com/android/internal/telephony/RadioMessagingProxy.java
+++ b/src/java/com/android/internal/telephony/RadioMessagingProxy.java
@@ -20,6 +20,7 @@
import android.telephony.Rlog;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import java.util.ArrayList;
@@ -107,6 +108,7 @@
*/
public void acknowledgeLastIncomingCdmaSms(int serial, boolean success, int cause)
throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
android.hardware.radio.messaging.CdmaSmsAck msg =
@@ -147,6 +149,7 @@
* @throws RemoteException
*/
public void deleteSmsOnRuim(int serial, int index) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mMessagingProxy.deleteSmsOnRuim(serial, index);
@@ -176,6 +179,7 @@
* @throws RemoteException
*/
public void getCdmaBroadcastConfig(int serial) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mMessagingProxy.getCdmaBroadcastConfig(serial);
@@ -248,6 +252,7 @@
* @throws RemoteException
*/
public void sendCdmaSms(int serial, byte[] pdu) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mMessagingProxy.sendCdmaSms(serial, RILUtils.convertToHalCdmaSmsMessageAidl(pdu));
@@ -266,6 +271,7 @@
* @throws RemoteException
*/
public void sendCdmaSmsExpectMore(int serial, byte[] pdu) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mMessagingProxy.sendCdmaSmsExpectMore(
@@ -378,6 +384,7 @@
* @throws RemoteException
*/
public void setCdmaBroadcastActivation(int serial, boolean activate) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mMessagingProxy.setCdmaBroadcastActivation(serial, activate);
@@ -394,6 +401,7 @@
*/
public void setCdmaBroadcastConfig(int serial, CdmaSmsBroadcastConfigInfo[] configs)
throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
ArrayList<android.hardware.radio.messaging.CdmaBroadcastSmsConfigInfo> halConfigs =
@@ -513,6 +521,7 @@
* @throws RemoteException
*/
public void writeSmsToRuim(int serial, int status, byte[] pdu) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
android.hardware.radio.messaging.CdmaSmsWriteArgs args =
diff --git a/src/java/com/android/internal/telephony/RadioModemProxy.java b/src/java/com/android/internal/telephony/RadioModemProxy.java
index cdcbcc0..bc19d55 100644
--- a/src/java/com/android/internal/telephony/RadioModemProxy.java
+++ b/src/java/com/android/internal/telephony/RadioModemProxy.java
@@ -19,6 +19,8 @@
import android.os.RemoteException;
import android.telephony.Rlog;
+import com.android.internal.telephony.flags.Flags;
+
/**
* A holder for IRadioModem.
* Use getAidl to get IRadioModem and call the AIDL implementations of the HAL APIs.
@@ -195,6 +197,7 @@
* @throws RemoteException
*/
public void nvReadItem(int serial, int itemId) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mModemProxy.nvReadItem(serial, itemId);
@@ -210,6 +213,7 @@
* @throws RemoteException
*/
public void nvResetConfig(int serial, int resetType) throws RemoteException {
+ if (Flags.cleanupCdma() && resetType != 1) return;
if (isEmpty()) return;
if (isAidl()) {
mModemProxy.nvResetConfig(serial, RILUtils.convertToHalResetNvTypeAidl(resetType));
@@ -225,6 +229,7 @@
* @throws RemoteException
*/
public void nvWriteCdmaPrl(int serial, byte[] prl) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mModemProxy.nvWriteCdmaPrl(serial, prl);
@@ -241,6 +246,7 @@
* @throws RemoteException
*/
public void nvWriteItem(int serial, int itemId, String itemValue) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
android.hardware.radio.modem.NvWriteItem item =
diff --git a/src/java/com/android/internal/telephony/RadioNetworkProxy.java b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
index 4acc71a..6748462 100644
--- a/src/java/com/android/internal/telephony/RadioNetworkProxy.java
+++ b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
@@ -28,6 +28,8 @@
import android.telephony.Rlog;
import android.telephony.SignalThresholdInfo;
+import com.android.internal.telephony.flags.Flags;
+
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -130,6 +132,7 @@
* @throws RemoteException
*/
public void getAvailableBandModes(int serial) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.getAvailableBandModes(serial);
@@ -172,6 +175,7 @@
* @throws RemoteException
*/
public void getCdmaRoamingPreference(int serial) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.getCdmaRoamingPreference(serial);
@@ -398,6 +402,7 @@
* @throws RemoteException
*/
public void setBandMode(int serial, int bandMode) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.setBandMode(serial, bandMode);
@@ -431,6 +436,7 @@
* @throws RemoteException
*/
public void setCdmaRoamingPreference(int serial, int cdmaRoamingType) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.setCdmaRoamingPreference(serial, cdmaRoamingType);
@@ -521,6 +527,7 @@
* @throws RemoteException
*/
public void setLocationUpdates(int serial, boolean enable) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.setLocationUpdates(serial, enable);
@@ -625,6 +632,7 @@
* @throws RemoteException
*/
public void setSuppServiceNotifications(int serial, boolean enable) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mNetworkProxy.setSuppServiceNotifications(serial, enable);
@@ -979,4 +987,60 @@
}
// Only supported on AIDL.
}
+
+ /**
+ * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+ *
+ * @param serial Serial number of request.
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+ * supported by user subscription.
+ * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+ * PLMNs that are not supported by the carrier and make sure not to
+ * attach to them.
+ */
+ public void setSatellitePlmn(int serial, int simSlot, List<String> carrierPlmnList,
+ List<String> allSatellitePlmnList) throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ String[] carrierPlmnArray = carrierPlmnList.toArray(new String[0]);
+ String[] allSatellitePlmnArray = allSatellitePlmnList.toArray(new String[0]);
+ mNetworkProxy.setSatellitePlmn(serial, simSlot, carrierPlmnArray,
+ allSatellitePlmnArray);
+ }
+ // Only supported on AIDL.
+ }
+
+ /**
+ * Enable or disable satellite in the cellular modem associated with a carrier.
+ *
+ * @param serial Serial number of request.
+ * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+ * this information to determine the relevant carrier.
+ * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+ */
+ public void setSatelliteEnabledForCarrier(int serial, int simSlot,
+ boolean satelliteEnabled) throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mNetworkProxy.setSatelliteEnabledForCarrier(serial, simSlot, satelliteEnabled);
+ }
+ // Only supported on AIDL.
+ }
+
+ /**
+ * Check whether satellite is enabled in the cellular modem associated with a carrier.
+ *
+ * @param serial Serial number of request.
+ * @param simSlot Indicates the SIM slot to which this API will be applied.
+ */
+ public void isSatelliteEnabledForCarrier(int serial, int simSlot)
+ throws RemoteException {
+ if (isEmpty()) return;
+ if (isAidl()) {
+ mNetworkProxy.isSatelliteEnabledForCarrier(serial, simSlot);
+ }
+ // Only supported on AIDL.
+ }
}
diff --git a/src/java/com/android/internal/telephony/RadioSimProxy.java b/src/java/com/android/internal/telephony/RadioSimProxy.java
index 1c864fe..65fbfa4 100644
--- a/src/java/com/android/internal/telephony/RadioSimProxy.java
+++ b/src/java/com/android/internal/telephony/RadioSimProxy.java
@@ -21,6 +21,7 @@
import android.telephony.ImsiEncryptionInfo;
import android.telephony.Rlog;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
import com.android.internal.telephony.uicc.SimPhonebookRecord;
@@ -168,6 +169,7 @@
* @throws RemoteException
*/
public void getCdmaSubscription(int serial) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mSimProxy.getCdmaSubscription(serial);
@@ -182,6 +184,7 @@
* @throws RemoteException
*/
public void getCdmaSubscriptionSource(int serial) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mSimProxy.getCdmaSubscriptionSource(serial);
@@ -631,6 +634,7 @@
* @throws RemoteException
*/
public void setCdmaSubscriptionSource(int serial, int cdmaSub) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mSimProxy.setCdmaSubscriptionSource(serial, cdmaSub);
@@ -689,6 +693,7 @@
*/
public void setUiccSubscription(int serial, int slotId, int appIndex, int subId, int subStatus)
throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
android.hardware.radio.sim.SelectUiccSub info =
diff --git a/src/java/com/android/internal/telephony/RadioVoiceProxy.java b/src/java/com/android/internal/telephony/RadioVoiceProxy.java
index e57a61d..d85017b 100644
--- a/src/java/com/android/internal/telephony/RadioVoiceProxy.java
+++ b/src/java/com/android/internal/telephony/RadioVoiceProxy.java
@@ -21,6 +21,8 @@
import android.telephony.Rlog;
import android.telephony.emergency.EmergencyNumber;
+import com.android.internal.telephony.flags.Flags;
+
import java.util.ArrayList;
/**
@@ -488,6 +490,7 @@
* @throws RemoteException
*/
public void sendCdmaFeatureCode(int serial, String featureCode) throws RemoteException {
+ if (Flags.cleanupCdma()) return;
if (isEmpty()) return;
if (isAidl()) {
mVoiceProxy.sendCdmaFeatureCode(serial, featureCode);
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 8a2d5bf..88b9958 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -825,6 +825,9 @@
SmsResponse smsResponse = new SmsResponse(messageRef, null /* ackPdu */, NO_ERROR_CODE,
tracker.mMessageId);
+ if (Flags.temporaryFailuresInCarrierMessagingService()) {
+ tracker.mResultCodeFromCarrierMessagingService = result;
+ }
switch (result) {
case CarrierMessagingService.SEND_STATUS_OK:
@@ -836,10 +839,34 @@
smsResponse,
null /* exception*/)));
break;
- case CarrierMessagingService.SEND_STATUS_ERROR:
- Rlog.d(TAG, "processSendSmsResponse: Sending SMS by CarrierMessagingService"
- + " failed. "
- + SmsController.formatCrossStackMessageId(tracker.mMessageId));
+ case CarrierMessagingService.SEND_STATUS_ERROR: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_GENERIC_FAILURE: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NULL_PDU: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_LIMIT_EXCEEDED: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_FDN_CHECK_FAILURE: // fall through
+ case CarrierMessagingService
+ .SEND_STATUS_RESULT_ERROR_SHORT_CODE_NOT_ALLOWED: // fall through
+ case CarrierMessagingService
+ .SEND_STATUS_RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_REJECT: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_ARGUMENTS: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_STATE: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMS_FORMAT: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_ERROR: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_ENCODING_ERROR: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMSC_ADDRESS: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_OPERATION_NOT_ALLOWED: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_CANCELLED: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_REQUEST_NOT_SUPPORTED: // fall through
+ case CarrierMessagingService
+ .SEND_STATUS_RESULT_SMS_BLOCKED_DURING_EMERGENCY: // fall through
+ case CarrierMessagingService.SEND_STATUS_RESULT_SMS_SEND_RETRY_FAILED: // fall through
+ Rlog.d(
+ TAG,
+ "processSendSmsResponse: Sending SMS by CarrierMessagingService"
+ + " failed. "
+ + SmsController.formatCrossStackMessageId(tracker.mMessageId));
sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
new AsyncResult(tracker, smsResponse,
new CommandException(CommandException.Error.GENERIC_FAILURE))));
@@ -858,6 +885,55 @@
}
}
+ private int toSmsManagerResultForSendSms(int carrierMessagingServiceResult) {
+ switch (carrierMessagingServiceResult) {
+ case CarrierMessagingService.SEND_STATUS_OK:
+ return Activity.RESULT_OK;
+ case CarrierMessagingService.SEND_STATUS_ERROR:
+ return SmsManager.RESULT_RIL_GENERIC_ERROR;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_GENERIC_FAILURE:
+ return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NULL_PDU:
+ return SmsManager.RESULT_ERROR_NULL_PDU;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE:
+ return SmsManager.RESULT_ERROR_NO_SERVICE;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_LIMIT_EXCEEDED:
+ return SmsManager.RESULT_ERROR_LIMIT_EXCEEDED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_FDN_CHECK_FAILURE:
+ return SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_SHORT_CODE_NOT_ALLOWED:
+ return SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED:
+ return SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_REJECT:
+ return SmsManager.RESULT_NETWORK_REJECT;
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_ARGUMENTS:
+ return SmsManager.RESULT_INVALID_ARGUMENTS;
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_STATE:
+ return SmsManager.RESULT_INVALID_STATE;
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMS_FORMAT:
+ return SmsManager.RESULT_INVALID_SMS_FORMAT;
+ case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_ERROR:
+ return SmsManager.RESULT_NETWORK_ERROR;
+ case CarrierMessagingService.SEND_STATUS_RESULT_ENCODING_ERROR:
+ return SmsManager.RESULT_ENCODING_ERROR;
+ case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMSC_ADDRESS:
+ return SmsManager.RESULT_INVALID_SMSC_ADDRESS;
+ case CarrierMessagingService.SEND_STATUS_RESULT_OPERATION_NOT_ALLOWED:
+ return SmsManager.RESULT_OPERATION_NOT_ALLOWED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_CANCELLED:
+ return SmsManager.RESULT_CANCELLED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_REQUEST_NOT_SUPPORTED:
+ return SmsManager.RESULT_REQUEST_NOT_SUPPORTED;
+ case CarrierMessagingService.SEND_STATUS_RESULT_SMS_BLOCKED_DURING_EMERGENCY:
+ return SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY;
+ case CarrierMessagingService.SEND_STATUS_RESULT_SMS_SEND_RETRY_FAILED:
+ return SmsManager.RESULT_SMS_SEND_RETRY_FAILED;
+ default:
+ return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+ }
+ }
+
/**
* Use the carrier messaging service to send a multipart text SMS.
*/
@@ -1084,10 +1160,20 @@
+ SmsController.formatCrossStackMessageId(tracker.mMessageId));
}
- int ss = mPhone.getServiceState().getState();
- int error = rilErrorToSmsManagerResult(
- ((CommandException) (ar.exception)).getCommandError(), tracker);
+ int error;
+ if (Flags.temporaryFailuresInCarrierMessagingService()
+ && tracker.mResultCodeFromCarrierMessagingService
+ != CarrierMessagingService.SEND_STATUS_OK) {
+ error =
+ toSmsManagerResultForSendSms(
+ tracker.mResultCodeFromCarrierMessagingService);
+ } else {
+ error =
+ rilErrorToSmsManagerResult(
+ ((CommandException) (ar.exception)).getCommandError(), tracker);
+ }
+ int ss = mPhone.getServiceState().getState();
if (tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
// This is retry after failure over IMS but voice is not available.
// Set retry to max allowed, so no retry is sent and cause
@@ -2120,7 +2206,7 @@
}
}
- if (mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress)) {
+ if (mPhone.hasCalling() && mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress)) {
new AsyncEmergencyContactNotifier(mContext).execute();
}
}
@@ -2489,6 +2575,9 @@
public final long mMessageId;
+ // A CarrierMessagingService result code to be returned to the caller.
+ public int mResultCodeFromCarrierMessagingService;
+
private Boolean mIsFromDefaultSmsApplication;
private int mCarrierId;
@@ -2533,6 +2622,7 @@
mCarrierId = carrierId;
mSkipShortCodeDestAddrCheck = skipShortCodeDestAddrCheck;
mUniqueMessageId = uniqueMessageId;
+ mResultCodeFromCarrierMessagingService = CarrierMessagingService.SEND_STATUS_OK;
}
@VisibleForTesting
@@ -2552,6 +2642,7 @@
mCarrierId = 0;
mSkipShortCodeDestAddrCheck = false;
mUniqueMessageId = 0;
+ mResultCodeFromCarrierMessagingService = CarrierMessagingService.SEND_STATUS_OK;
}
public HashMap<String, Object> getData() {
@@ -2647,6 +2738,14 @@
}
/**
+ * Returns the flag specifying whether any part of this {@link SmsTracker} failed to send
+ * or not.
+ */
+ protected boolean isAnyPartFailed() {
+ return mAnyPartFailed != null && mAnyPartFailed.get();
+ }
+
+ /**
* Persist a sent SMS if required:
* 1. It is a text message
* 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 3309d21..d0b2527 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -76,6 +76,8 @@
import android.telephony.TelephonyManager;
import android.telephony.VoiceSpecificRegistrationInfo;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatelliteModemStateCallback;
+import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.LocalLog;
@@ -619,6 +621,83 @@
*/
private AccessNetworksManagerCallback mAccessNetworksManagerCallback = null;
+ /**
+ * Listens status of nb iot satellite modem.
+ */
+ private SatelliteModemStateListener mSatelliteModemStateListener = null;
+
+ /**
+ * SatelliteModemStateListener class
+ */
+ protected class SatelliteModemStateListener extends ISatelliteModemStateCallback.Stub {
+
+ /**
+ * Satellite Modem Connection Status. True when satellite is connected
+ */
+ private boolean mSatelliteNbIotConnected = false;
+
+ /**
+ * Marks the satellite display change as true.
+ */
+ private boolean mUpdateSatelliteCarrierDisplay = false;
+
+ @Override
+ public void onSatelliteModemStateChanged(int state) {
+ boolean isConnected = isInConnectedState();
+ if (isConnected != mSatelliteNbIotConnected) {
+ log("Satellite connection state is changed to " + isConnected);
+ mSatelliteNbIotConnected = isConnected;
+ mUpdateSatelliteCarrierDisplay = true;
+ // trigger pollStats() because the service state is already OOO in demo mode.
+ pollState();
+ }
+ }
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {}
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {}
+
+ /**
+ * Returns true when statellite is connected.
+ *
+ * Note that this connection state is only applicable carrier roaming nb iot satellite.
+ */
+ public boolean isInConnectedState() {
+ SatelliteController sc = SatelliteController.getInstance();
+ if (sc == null) {
+ return false;
+ }
+ int subId = sc.getSelectedSatelliteSubId();
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ || subId != mPhone.getSubId()
+ || subId == sc.getNtnOnlySubscriptionId()) {
+ return false;
+ }
+ return sc.isInConnectedState();
+ }
+
+ /**
+ * Returns true if the satellite connection has changed and the satellite display needs
+ * to be updated.
+ */
+ public boolean needToUpdateSatelliteCarrierDisplay() {
+ return mUpdateSatelliteCarrierDisplay;
+ }
+
+ /**
+ * The satellite carrier display update is complete and is marked to not be updated any
+ * further.
+ */
+ public void doneForUpdateSatelliteCarrierDisplay() {
+ mUpdateSatelliteCarrierDisplay = false;
+ }
+ }
+
public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci,
FeatureFlags featureFlags) {
mNitzState = TelephonyComponentFactory.getInstance()
@@ -2912,6 +2991,17 @@
crossSimSpnFormat = crossSimSpnFormats[crossSimSpnFormatIdx];
}
+ String satellitePlmn = null;
+ SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+ if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE
+ && satelliteModemStateListener != null
+ && satelliteModemStateListener.isInConnectedState()) {
+ // If device is connected to the nb-iot satellite,
+ // 1) No service but nb-iot satellite is connected ->
+ // expected to show "Satellite" for demo mode.
+ satellitePlmn = getSatelliteDisplayName();
+ }
+
if (mPhone.isPhoneTypeGsm()) {
// The values of plmn/showPlmn change in different scenarios.
// 1) No service but emergency call allowed -> expected
@@ -2981,7 +3071,12 @@
&& ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN)
== CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN);
if (DBG) log("updateCarrierDisplayName: rawSpn = " + spn);
- if (!TextUtils.isEmpty(crossSimSpnFormat)) {
+ if (!TextUtils.isEmpty(satellitePlmn)) {
+ plmn = satellitePlmn;
+ showPlmn = true;
+ showSpn = false;
+ log("updateCarrierDisplayName: Update satellite network name:" + plmn);
+ } else if (!TextUtils.isEmpty(crossSimSpnFormat)) {
if (!TextUtils.isEmpty(spn)) {
// Show SPN + Cross-SIM Calling If SIM has SPN and SPN display condition
// is satisfied or SPN override is enabled for this carrier.
@@ -3077,6 +3172,46 @@
.build();
}
+ private void updateSatelliteDisplayOverride() {
+ String satelliteDisplayName = getSatelliteDisplayName();
+ if (TextUtils.isEmpty(satelliteDisplayName)) {
+ // Return, if there is no value to override.
+ return;
+ }
+
+ SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+ if (satelliteModemStateListener != null
+ && satelliteModemStateListener.isInConnectedState()) {
+ // override satellite display name.
+ mNewSS.setOperatorName(
+ satelliteDisplayName, satelliteDisplayName, mNewSS.getOperatorNumeric());
+ log("Override satellite display name to " + satelliteDisplayName);
+ }
+ }
+
+ @Nullable
+ private SatelliteModemStateListener getSatelliteModemStateListener() {
+ if (mSatelliteModemStateListener != null) {
+ return mSatelliteModemStateListener;
+ }
+
+ SatelliteController sc = SatelliteController.getInstance();
+ if (sc != null) {
+ SatelliteModemStateListener listener = new SatelliteModemStateListener();
+ if (sc.registerForSatelliteModemStateChanged(listener)
+ == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ mSatelliteModemStateListener = listener;
+ log("created SatelliteModemStateListener");
+ }
+ }
+ return mSatelliteModemStateListener;
+ }
+
+ private String getSatelliteDisplayName() {
+ return mCarrierConfig.getString(
+ CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING);
+ }
+
/**
* Returns whether out-of-service will be displayed as "no service" to the user.
*/
@@ -3431,6 +3566,19 @@
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
+ boolean hasSatelliteConnectionChanged = false;
+ SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+ if (satelliteModemStateListener != null) {
+ hasSatelliteConnectionChanged =
+ satelliteModemStateListener.needToUpdateSatelliteCarrierDisplay();
+ if (hasSatelliteConnectionChanged) {
+ log("Poll ServiceState done : hasSatelliteConnectionChanged="
+ + hasSatelliteConnectionChanged);
+ satelliteModemStateListener.doneForUpdateSatelliteCarrierDisplay();
+ updateSatelliteDisplayOverride();
+ }
+ }
+
if (DBG) {
log("Poll ServiceState done: oldSS=" + mSS);
log("Poll ServiceState done: newSS=" + mNewSS);
@@ -3700,7 +3848,8 @@
// Trigger updateCarrierDisplayName when
// 1. Service state is changed.
// 2. phone type is Cdma or CdmaLte and ERI text has changed.
- if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)) {
+ if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)
+ || hasSatelliteConnectionChanged) {
updateCarrierDisplayName();
}
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 97692a0..12c9a3c 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -123,19 +123,34 @@
if (!carrierRestrictions.allowedCarriersPrioritized) {
carrierRestrictionDefault = CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED;
}
-
- CarrierRestrictionRules ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.allowedCarriers)).setExcludedCarriers(
- RILUtils.convertHalCarrierList(
- carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
- carrierRestrictionDefault).setMultiSimPolicy(policy).setCarrierRestrictionStatus(
- carrierRestrictions.status).setAllowedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
- RILUtils.convertAidlCarrierInfoList(
- carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
- carrierLockInfoSupported).build();
+ CarrierRestrictionRules ret = null;
+ if (carrierLockInfoSupported) {
+ // In order to support the old API { @link TelephonyManager#getAllowedCarriers() } we
+ // are parsing the allowedCarrierInfoList to CarrierIdentifier List also along with
+ // CarrierInfo List
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarriers(
+ RILUtils.convertAidlCarrierInfoListToHalCarrierList(
+ carrierRestrictions.excludedCarrierInfoList)).
+ setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).setCarrierRestrictionStatus(
+ carrierRestrictions.status).setAllowedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.allowedCarrierInfoList)).setExcludedCarrierInfo(
+ RILUtils.convertAidlCarrierInfoList(
+ carrierRestrictions.excludedCarrierInfoList)).setCarrierLockInfoFeature(
+ true).build();
+ } else {
+ ret = CarrierRestrictionRules.newBuilder().setAllowedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.allowedCarriers)).setExcludedCarriers(
+ RILUtils.convertHalCarrierList(
+ carrierRestrictions.excludedCarriers)).setDefaultCarrierRestriction(
+ carrierRestrictionDefault).setMultiSimPolicy(
+ policy).build();
+ }
if (responseInfo.error == RadioError.NONE) {
RadioResponse.sendMessageResponse(rr.mResult, ret);
}
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index e3c409d..051fbbd 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -276,6 +276,7 @@
}
UserHandle callingUser = Binder.getCallingUserHandle();
+
Rlog.d(LOG_TAG, "sendTextForSubscriber caller=" + callingPackage);
if (skipFdnCheck || skipShortCodeCheck) {
@@ -1194,8 +1195,9 @@
}
// Skip FDN check for emergency numbers
+ if (!TelephonyCapabilities.supportsTelephonyCalling(mFlags, mContext)) return false;
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(destAddr)) {
+ if (tm != null && tm.isEmergencyNumber(destAddr)) {
return false;
}
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index b60ded5..373ee4a 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -45,12 +45,14 @@
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import com.android.ims.ImsManager;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
@@ -70,12 +72,12 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicLong;
/**
*
@@ -137,12 +139,12 @@
/** Time at which the current PARTIAL_SEGMENT_WAIT_DURATION timer was started */
private long mCurrentWaitStartTime = INVALID_TIME;
- private SMSDispatcher mCdmaDispatcher;
+ private SMSDispatcher mCdmaDispatcher = null;
private SMSDispatcher mGsmDispatcher;
private ImsSmsDispatcher mImsSmsDispatcher;
private GsmInboundSmsHandler mGsmInboundSmsHandler;
- private CdmaInboundSmsHandler mCdmaInboundSmsHandler;
+ private CdmaInboundSmsHandler mCdmaInboundSmsHandler = null;
private Phone mPhone;
/** Outgoing message counter. Shared by all dispatchers. */
@@ -245,13 +247,15 @@
public final long messageId;
public final boolean skipShortCodeCheck;
public final long uniqueMessageId;
+ public final boolean isMtSmsPolling;
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) {
+ int validityPeriod, long messageId, boolean skipShortCodeCheck,
+ boolean isMtSmsPolling) {
this.type = type;
this.tracker = tracker;
this.callingPackage = callingPackage;
@@ -278,6 +282,7 @@
} else {
this.uniqueMessageId = getNextUniqueMessageId();
}
+ this.isMtSmsPolling = isMtSmsPolling;
}
public static long getNextUniqueMessageId() {
@@ -404,11 +409,14 @@
// Create dispatchers, inbound SMS handlers and
// broadcast undelivered messages in raw table.
mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, ImsManager::getConnector);
- mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
storageMonitor, phone, looper, mFeatureFlags);
- mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
- storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper, mFeatureFlags);
+ if (!mFeatureFlags.cleanupCdma()) {
+ mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
+ mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
+ storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper,
+ mFeatureFlags);
+ }
mGsmDispatcher = new GsmSMSDispatcher(phone, this, mGsmInboundSmsHandler);
SmsBroadcastUndelivered.initialize(phone.getContext(),
mGsmInboundSmsHandler, mCdmaInboundSmsHandler, mFeatureFlags);
@@ -450,9 +458,9 @@
mCi.unregisterForImsNetworkStateChanged(this);
mPhone.unregisterForServiceStateChanged(this);
mGsmDispatcher.dispose();
- mCdmaDispatcher.dispose();
+ if (mCdmaDispatcher != null) mCdmaDispatcher.dispose();
mGsmInboundSmsHandler.dispose();
- mCdmaInboundSmsHandler.dispose();
+ if (mCdmaInboundSmsHandler != null) mCdmaInboundSmsHandler.dispose();
// Cancels the domain selection request if it's still in progress.
finishDomainSelection(mDscHolder);
finishDomainSelection(mEmergencyDscHolder);
@@ -572,7 +580,7 @@
default:
if (isCdmaMo()) {
- mCdmaDispatcher.handleMessage(msg);
+ if (mCdmaDispatcher != null) mCdmaDispatcher.handleMessage(msg);
} else {
mGsmDispatcher.handleMessage(msg);
}
@@ -654,7 +662,8 @@
private void handlePartialSegmentTimerExpiry(long waitTimerStart) {
if (mGsmInboundSmsHandler.getCurrentState().getName().equals("WaitingState")
- || mCdmaInboundSmsHandler.getCurrentState().getName().equals("WaitingState")) {
+ || (mCdmaInboundSmsHandler != null
+ && mCdmaInboundSmsHandler.getCurrentState().getName().equals("WaitingState"))) {
logd("handlePartialSegmentTimerExpiry: ignoring timer expiry as InboundSmsHandler is"
+ " in WaitingState");
return;
@@ -785,7 +794,7 @@
+ ", format=" + format + "to mGsmInboundSmsHandler");
mGsmInboundSmsHandler.sendMessage(
InboundSmsHandler.EVENT_INJECT_SMS, isOverIms ? 1 : 0, token, ar);
- } else if (format.equals(SmsConstants.FORMAT_3GPP2)) {
+ } else if (format.equals(SmsConstants.FORMAT_3GPP2) && mCdmaInboundSmsHandler != null) {
Rlog.i(TAG, "SmsDispatchersController:injectSmsText Sending msg=" + msg
+ ", format=" + format + "to mCdmaInboundSmsHandler");
mCdmaInboundSmsHandler.sendMessage(
@@ -824,8 +833,7 @@
if (!tracker.mUsesImsServiceForIms) {
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(tracker.mDestAddress);
+ boolean isEmergency = isEmergencyNumber(tracker.mDestAddress);
// This may be invoked by another thread, so this operation is posted and
// handled through the execution flow of SmsDispatchersController.
SomeArgs args = SomeArgs.obtain();
@@ -834,7 +842,7 @@
null, UserHandle.USER_NULL, null, null,
null, null, false, null, 0,
null, null, false,
- 0, false, 0, 0L, false);
+ 0, false, 0, 0L, false, false);
args.arg3 = "sendRetrySms";
sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
return;
@@ -994,6 +1002,7 @@
* @return true if Cdma format should be used for MO SMS, false otherwise.
*/
protected boolean isCdmaMo() {
+ if (mFeatureFlags.cleanupCdma()) return false;
if (!isIms()) {
// IMS is not registered, use Voice technology to determine SMS format.
return (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType());
@@ -1009,6 +1018,7 @@
* @return true if format given is CDMA format, false otherwise.
*/
public boolean isCdmaFormat(String format) {
+ if (mFeatureFlags.cleanupCdma()) return false;
return (mCdmaDispatcher.getFormat().equals(format));
}
@@ -1214,8 +1224,7 @@
private void handleSmsSentCompletedUsingDomainSelection(@NonNull String destAddr,
long messageId, boolean success, boolean isOverIms, boolean isLastSmsPart) {
if (mEmergencyStateTracker != null) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (tm.isEmergencyNumber(destAddr)) {
+ if (isEmergencyNumber(destAddr)) {
mEmergencyStateTracker.endSms(String.valueOf(messageId), success,
isOverIms ? NetworkRegistrationInfo.DOMAIN_PS
: NetworkRegistrationInfo.DOMAIN_CS,
@@ -1231,7 +1240,8 @@
boolean isOverIms, boolean isLastSmsPart, boolean success) {
notifySmsSentToEmergencyStateTracker(tracker.mDestAddress,
tracker.mMessageId, isOverIms, isLastSmsPart, success);
- notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId, success);
+ notifySmsSentToDatagramDispatcher(tracker.mUniqueMessageId,
+ tracker.isSinglePartOrLastPart(), success && !tracker.isAnyPartFailed());
}
/**
@@ -1251,9 +1261,12 @@
}
}
- private void notifySmsSentToDatagramDispatcher(long messageId, boolean success) {
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
- DatagramDispatcher.getInstance().onSendSmsDone(mPhone.getSubId(), messageId, success);
+ private void notifySmsSentToDatagramDispatcher(
+ long messageId, boolean isLastSmsPart, boolean success) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)
+ && isLastSmsPart) {
+ DatagramDispatcher.getInstance().onSendSmsDone(
+ mPhone.getSubId(), messageId, success);
}
}
@@ -1264,8 +1277,7 @@
*/
private void handleSmsReceivedViaIms(@Nullable String origAddr) {
if (mEmergencyStateTracker != null) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- if (origAddr != null && tm.isEmergencyNumber(origAddr)) {
+ if (origAddr != null && isEmergencyNumber(origAddr)) {
mEmergencyStateTracker.onEmergencySmsReceived();
}
}
@@ -1283,7 +1295,9 @@
private boolean isTestEmergencyNumber(String number) {
try {
+ if (!mPhone.hasCalling()) return false;
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm == null) return false;
Map<Integer, List<EmergencyNumber>> eMap = tm.getEmergencyNumberList();
return eMap.values().stream().flatMap(Collection::stream).anyMatch(eNumber ->
eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST)
@@ -1622,7 +1636,7 @@
destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, data, destPort, null,
null, false, 0, false, 0,
- 0L, false),
+ 0L, false, false),
"sendData");
return;
}
@@ -1858,9 +1872,9 @@
callingPkg, callingUser, destAddr, scAddr, asArrayList(sentIntent),
asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
messageUri, persistMessage, priority, expectMore, validityPeriod, messageId,
- skipShortCodeCheck);
+ skipShortCodeCheck, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -1873,8 +1887,7 @@
logd("sendTextInternal: messageId=" + request.messageId
+ ", uniqueMessageId=" + request.uniqueMessageId);
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
+ boolean isEmergency = isEmergencyNumber(request.destAddr);
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
request, "sendText");
return;
@@ -2023,9 +2036,9 @@
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);
+ validityPeriod, messageId, false, false);
- if (SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(mPhone)) {
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
// Send multipart P2P SMS using carrier roaming NB IOT NTN
DatagramDispatcher.getInstance().sendSms(pendingRequest);
return;
@@ -2034,11 +2047,17 @@
sendMultipartTextInternal(pendingRequest);
}
+ private boolean isEmergencyNumber(String number) {
+ if (!mPhone.hasCalling()) return false;
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ if (tm == null) return false;
+ return tm.isEmergencyNumber(number);
+ }
+
private void sendMultipartTextInternal(PendingRequest request) {
logd("sendMultipartTextInternal: messageId=" + request.messageId);
if (isSmsDomainSelectionEnabled()) {
- TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
- boolean isEmergency = tm.isEmergencyNumber(request.destAddr);
+ boolean isEmergency = isEmergencyNumber(request.destAddr);
sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
request, "sendMultipartText");
return;
@@ -2200,7 +2219,7 @@
*/
public void sendCarrierRoamingNbIotNtnText(@NonNull PendingRequest request) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- logd("onSendCarrierRoamingNbIotNtnTextError: carrier roaming nb iot ntn "
+ logd("sendCarrierRoamingNbIotNtnText: carrier roaming nb iot ntn "
+ "feature flag is disabled");
return;
}
@@ -2228,6 +2247,44 @@
sendMessage(obtainMessage(EVENT_SEND_TEXT_OVER_NTN_ERROR, pendingRequest));
}
+ /**
+ * This API should be used only by {@link DatagramDispatcher} to send MT SMS Polling message
+ * over non-terrestrial network.
+ * To enable users to receive incoming messages, the device needs to send an MO SMS to itself
+ * to trigger SMSC to send all pending SMS to the particular subscription.
+ */
+ public void sendMtSmsPollingMessage() {
+ if (!SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
+ logd("sendMtSmsPollingMessage: not in roaming nb iot ntn");
+ return;
+ }
+
+ SubscriptionManager subscriptionManager = (SubscriptionManager) mContext
+ .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ String destAddr = subscriptionManager.getPhoneNumber(mPhone.getSubId());
+ if (TextUtils.isEmpty(destAddr)) {
+ logd("sendMtSmsPollingMessage: destAddr is null or empty.");
+ return;
+ }
+
+ String mtSmsPollingText = mContext.getResources()
+ .getString(R.string.config_mt_sms_polling_text);
+ if (TextUtils.isEmpty(mtSmsPollingText)) {
+ logd("sendMtSmsPollingMessage: mtSmsPollingText is null or empty.");
+ return;
+ }
+
+ String callingPackage = mContext.getPackageName();
+ PendingRequest pendingRequest = new PendingRequest(PendingRequest.TYPE_TEXT, null,
+ callingPackage, Binder.getCallingUserHandle().getIdentifier(), destAddr,
+ getSmscAddressFromUSIMWithPhoneIdentity(callingPackage), asArrayList(null),
+ asArrayList(null), false, null, 0, asArrayList(mtSmsPollingText), null, false, 0,
+ false, 5, 0L, true, true);
+
+ if (SatelliteController.getInstance().shouldSendSmsToDatagramDispatcher(mPhone)) {
+ DatagramDispatcher.getInstance().sendSms(pendingRequest);
+ }
+ }
public interface SmsInjectionCallback {
void onSmsInjectedResult(int result);
@@ -2235,9 +2292,9 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mGsmInboundSmsHandler.dump(fd, pw, args);
- mCdmaInboundSmsHandler.dump(fd, pw, args);
+ if (mCdmaInboundSmsHandler != null) mCdmaInboundSmsHandler.dump(fd, pw, args);
mGsmDispatcher.dump(fd, pw, args);
- mCdmaDispatcher.dump(fd, pw, args);
+ if (mCdmaDispatcher != null) mCdmaDispatcher.dump(fd, pw, args);
mImsSmsDispatcher.dump(fd, pw, args);
}
diff --git a/src/java/com/android/internal/telephony/SmsUsageMonitor.java b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
index 8e4ac60..7fb5811 100644
--- a/src/java/com/android/internal/telephony/SmsUsageMonitor.java
+++ b/src/java/com/android/internal/telephony/SmsUsageMonitor.java
@@ -35,6 +35,7 @@
import android.util.AtomicFile;
import android.util.Xml;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.XmlUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.telephony.Rlog;
@@ -113,6 +114,8 @@
/** Context for retrieving regexes from XML resource. */
private final Context mContext;
+ private final FeatureFlags mFeatureFlags;
+
/** Country code for the cached short code pattern matcher. */
private String mCurrentCountry;
@@ -255,8 +258,9 @@
* @param context the context to use to load resources and get TelephonyManager service
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public SmsUsageMonitor(Context context) {
+ public SmsUsageMonitor(Context context, FeatureFlags flags) {
mContext = context;
+ mFeatureFlags = flags;
ContentResolver resolver = context.getContentResolver();
mRoleManager = (RoleManager) mContext.getSystemService(Context.ROLE_SERVICE);
@@ -404,7 +408,8 @@
synchronized (mSettingsObserverHandler) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
// always allow emergency numbers
- if (tm.isEmergencyNumber(destAddress)) {
+ if (TelephonyCapabilities.supportsTelephonyCalling(mFeatureFlags, mContext)
+ && tm != null && tm.isEmergencyNumber(destAddress)) {
if (DBG) Rlog.d(TAG, "isEmergencyNumber");
return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
}
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index 71d3b14..b650b43 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -18,6 +18,8 @@
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.SystemProperties;
@@ -209,4 +211,14 @@
return featureFlags.minimalTelephonyCdmCheck();
}
+
+ /**
+ * @return true if this device supports telephony calling, false if it does not.
+ */
+ public static boolean supportsTelephonyCalling(@NonNull FeatureFlags featureFlags,
+ Context context) {
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(featureFlags)) return true;
+ return context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ }
}
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 10e97b6..b4a3ee6 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -301,8 +301,8 @@
return new SmsStorageMonitor(phone, flags);
}
- public SmsUsageMonitor makeSmsUsageMonitor(Context context) {
- return new SmsUsageMonitor(context);
+ public SmsUsageMonitor makeSmsUsageMonitor(Context context, FeatureFlags flags) {
+ return new SmsUsageMonitor(context, flags);
}
public ServiceStateTracker makeServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci,
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java b/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
index 0fac334..eea49e3 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
@@ -28,6 +28,7 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
import com.android.telephony.Rlog;
import java.util.concurrent.atomic.AtomicInteger;
@@ -63,6 +64,7 @@
// Constructor
private CdmaSubscriptionSourceManager(Context context, CommandsInterface ci) {
+ if (Flags.cleanupCdma()) return;
mCi = ci;
mCi.registerForCdmaSubscriptionChanged(this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
mCi.registerForOn(this, EVENT_RADIO_ON, null);
@@ -97,7 +99,7 @@
mCdmaSubscriptionSourceChangedRegistrants.remove(h);
synchronized (sReferenceCountMonitor) {
sReferenceCount--;
- if (sReferenceCount <= 0) {
+ if (sReferenceCount <= 0 && mCi != null) {
mCi.unregisterForCdmaSubscriptionChanged(this);
mCi.unregisterForOn(this);
mCi.unregisterForSubscriptionStatusChanged(this);
@@ -112,6 +114,7 @@
*/
@Override
public void handleMessage(Message msg) {
+ if (Flags.cleanupCdma()) return;
AsyncResult ar;
switch (msg.what) {
case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
@@ -165,6 +168,8 @@
* @return Default CDMA subscription source from Settings DB if present.
*/
public static int getDefault(Context context) {
+ if (Flags.cleanupCdma()) return Phone.CDMA_SUBSCRIPTION_UNKNOWN;
+
// Get the default value from the Settings
int subscriptionSource = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.CDMA_SUBSCRIPTION_MODE, Phone.PREFERRED_CDMA_SUBSCRIPTION);
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 89b0fec..543f064 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -892,6 +892,17 @@
}
/**
+ * Returns whether the data roaming setting for satellite connection is ignored.
+ *
+ * @return {@code true} if data roaming setting for satellite connection is ignored,
+ * {@code false} otherwise.
+ */
+ public boolean isIgnoringDataRoamingSettingForSatellite() {
+ return mCarrierConfig.getBoolean(
+ CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL);
+ }
+
+ /**
* @return Whether data throttling should be reset when the TAC changes from the carrier config.
*/
public boolean shouldResetDataThrottlingWhenTacChanges() {
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index 40c0081..f5eae91 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -225,8 +225,6 @@
SIM_LOADED(true),
/** SIM is removed. */
SIM_REMOVAL(true),
- /** SIM is disabled. */
- SIM_DISABLED(true),
/** Data profiles changed. */
DATA_PROFILES_CHANGED(true),
/** When service state changes.(For now only considering data RAT and data registration). */
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 9e432e1..9899405 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1664,7 +1664,11 @@
}
// Check if data roaming is disabled.
- if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()) {
+ // But if the data roaming setting for satellite connection is ignored as the satellite
+ // data plan is included in the user mobile plan, then we should not disallow data due to
+ // roaming disabled.
+ if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()
+ && !shouldIgnoreDataRoamingSettingForSatellite()) {
evaluation.addDataDisallowedReason(DataDisallowedReason.ROAMING_DISABLED);
}
@@ -1811,6 +1815,18 @@
}
/**
+ * Returns whether the data roaming setting should be ignored for satellite connection,
+ * as the satellite data plan is included in the user mobile plan.
+ *
+ * @return {@code true} if the data roaming setting should be ignored for satellite connection.
+ * {@code false} otherwise.
+ */
+ private boolean shouldIgnoreDataRoamingSettingForSatellite() {
+ return mServiceState.isUsingNonTerrestrialNetwork()
+ && mDataConfigManager.isIgnoringDataRoamingSettingForSatellite();
+ }
+
+ /**
* This method
* - At evaluation network request and evaluation data network determines, if
* bootstrap sim current data usage reached bootstrap sim max data limit allowed set
@@ -3543,6 +3559,15 @@
}
/**
+ * Called when SIM is absent.
+ */
+ private void onSimAbsent() {
+ log("onSimAbsent");
+ sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
+ DataEvaluationReason.SIM_REMOVAL));
+ }
+
+ /**
* Called when SIM state changes.
*
* @param simState SIM state. (Note this is mixed with card state and application state.)
@@ -3550,22 +3575,13 @@
private void onSimStateChanged(@SimState int simState) {
log("onSimStateChanged: state=" + TelephonyManager.simStateToString(simState));
if (mSimState != simState) {
+ mSimState = simState;
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
- log("onSimStateChanged: SIM absent.");
- sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
- DataEvaluationReason.SIM_REMOVAL));
- } else if (simState == TelephonyManager.SIM_STATE_NOT_READY
- && mSimState == TelephonyManager.SIM_STATE_LOADED) {
- if (mFeatureFlags.simDisabledGracefulTearDown()) {
- log("onSimStateChanged: SIM disabled.");
- sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
- DataEvaluationReason.SIM_DISABLED));
- }
+ onSimAbsent();
} else if (simState == TelephonyManager.SIM_STATE_LOADED) {
sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
DataEvaluationReason.SIM_LOADED));
}
- mSimState = simState;
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onSimStateChanged(mSimState)));
}
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 62d33d9..079e705 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -1834,16 +1834,18 @@
if (phone == null) {
return false;
}
-
+ Call bgCall = phone.getBackgroundCall();
+ Call fgCall = phone.getForegroundCall();
+ if (bgCall == null || fgCall == null) {
+ return false;
+ }
// A phone in voice call might trigger data being switched to it.
// Exclude dialing to give modem time to process an EMC first before dealing with DDS switch
// Include alerting because modem RLF leads to delay in switch, so carrier required to
// switch in alerting phase.
// TODO: check ringing call for vDADA
- return (!phone.getBackgroundCall().isIdle()
- && phone.getBackgroundCall().getState() != Call.State.DIALING)
- || (!phone.getForegroundCall().isIdle()
- && phone.getForegroundCall().getState() != Call.State.DIALING);
+ return (!bgCall.isIdle() && bgCall.getState() != Call.State.DIALING)
+ || (!fgCall.isIdle() && fgCall.getState() != Call.State.DIALING);
}
private void updateHalCommandToUse() {
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index e5ea0c0..b3e8095 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -109,8 +109,6 @@
* from the modem.
*/
private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1 * 1000;
- @VisibleForTesting
- public static final int DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3 * 1000;
/** Default value for if Emergency Callback Mode is supported. */
private static final boolean DEFAULT_EMERGENCY_CALLBACK_MODE_SUPPORTED = true;
/** Default Emergency Callback Mode exit timeout value. */
@@ -142,6 +140,7 @@
private final CarrierConfigManager mConfigManager;
private final Handler mHandler;
private final boolean mIsSuplDdsSwitchRequiredForEmergencyCall;
+ private final int mWaitForInServiceTimeoutMs;
private final PowerManager.WakeLock mWakeLock;
private RadioOnHelper mRadioOnHelper;
@EmergencyConstants.EmergencyMode
@@ -474,10 +473,10 @@
* @param featureFlags The telephony feature flags.
*/
public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall,
- @NonNull FeatureFlags featureFlags) {
+ int waitForInServiceTimeout, @NonNull FeatureFlags featureFlags) {
if (INSTANCE == null) {
INSTANCE = new EmergencyStateTracker(context, Looper.myLooper(),
- isSuplDdsSwitchRequiredForEmergencyCall, featureFlags);
+ isSuplDdsSwitchRequiredForEmergencyCall, waitForInServiceTimeout, featureFlags);
}
}
@@ -497,11 +496,13 @@
* Initializes EmergencyStateTracker.
*/
private EmergencyStateTracker(Context context, Looper looper,
- boolean isSuplDdsSwitchRequiredForEmergencyCall, @NonNull FeatureFlags featureFlags) {
+ boolean isSuplDdsSwitchRequiredForEmergencyCall, int waitForInServiceTimeout,
+ @NonNull FeatureFlags featureFlags) {
mEcmExitTimeoutMs = DEFAULT_ECM_EXIT_TIMEOUT_MS;
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
+ mWaitForInServiceTimeoutMs = waitForInServiceTimeout;
mFeatureFlags = featureFlags;
PowerManager pm = context.getSystemService(PowerManager.class);
mWakeLock = (pm != null) ? pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -534,6 +535,10 @@
* @param looper The {@link Looper} of the application.
* @param isSuplDdsSwitchRequiredForEmergencyCall Whether gnss supl requires default data for
* emergency call.
+ * @param waitForInServiceTimeout The timeout duration how long does it wait for
+ * modem to get in-service state when emergency
+ * call is dialed in airplane mode before
+ * starting the emergency call.
* @param phoneFactoryProxy The {@link PhoneFactoryProxy} to be injected.
* @param phoneSwitcherProxy The {@link PhoneSwitcherProxy} to be injected.
* @param telephonyManagerProxy The {@link TelephonyManagerProxy} to be
@@ -543,12 +548,14 @@
*/
@VisibleForTesting
public EmergencyStateTracker(Context context, Looper looper,
- boolean isSuplDdsSwitchRequiredForEmergencyCall, PhoneFactoryProxy phoneFactoryProxy,
- PhoneSwitcherProxy phoneSwitcherProxy, TelephonyManagerProxy telephonyManagerProxy,
- RadioOnHelper radioOnHelper, long ecmExitTimeoutMs, FeatureFlags featureFlags) {
+ boolean isSuplDdsSwitchRequiredForEmergencyCall, int waitForInServiceTimeout,
+ PhoneFactoryProxy phoneFactoryProxy, PhoneSwitcherProxy phoneSwitcherProxy,
+ TelephonyManagerProxy telephonyManagerProxy, RadioOnHelper radioOnHelper,
+ long ecmExitTimeoutMs, FeatureFlags featureFlags) {
mContext = context;
mHandler = new MyHandler(looper);
mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
+ mWaitForInServiceTimeoutMs = waitForInServiceTimeout;
mPhoneFactoryProxy = phoneFactoryProxy;
mPhoneSwitcherProxy = phoneSwitcherProxy;
mTelephonyManagerProxy = telephonyManagerProxy;
@@ -601,6 +608,11 @@
releaseWakeLock();
((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.TRUE);
+ if (mFeatureFlags.emergencyCallbackModeNotification()) {
+ mPhone.stopEmergencyCallbackMode(EMERGENCY_CALLBACK_MODE_CALL,
+ STOP_REASON_OUTGOING_EMERGENCY_CALL_INITIATED);
+ }
+
mOngoingCallProperties = 0;
mCallEmergencyModeFuture = new CompletableFuture<>();
setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN,
@@ -1684,12 +1696,22 @@
final Phone phoneForEmergency = phone;
final android.telecom.Connection expectedConnection = mOngoingConnection;
- final int waitForInServiceTimeout =
- needToTurnOnRadio ? DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS : 0;
+ final int waitForInServiceTimeout = needToTurnOnRadio ? mWaitForInServiceTimeoutMs : 0;
Rlog.i(TAG, "turnOnRadioAndSwitchDds: timeout=" + waitForInServiceTimeout);
mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
+ // Make sure the Call has not already been canceled by the user.
+ if (expectedConnection.getState() == STATE_DISCONNECTED) {
+ Rlog.i(TAG, "Call disconnected before the outgoing call was placed."
+ + "Skipping call placement.");
+ // If call is already canceled by the user, notify modem to exit emergency
+ // call mode by sending radio on with forEmergencyCall=false.
+ for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+ phone.setRadioPower(true, false, false, true);
+ }
+ return;
+ }
if (!isRadioReady) {
if (satelliteController.isSatelliteEnabledOrBeingEnabled()) {
// Could not turn satellite off
@@ -1738,8 +1760,7 @@
return phone.getServiceStateTracker().isRadioOn()
&& !satelliteController.isSatelliteEnabledOrBeingEnabled();
}
- }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout,
- /* forNormalRoutingEmergencyCall */ false);
+ }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout);
} 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 11162b8..e2291c9 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, boolean forNormalRoutingEmergencyCall) {
+ int emergencyTimeoutIntervalMillis) {
setupListeners();
mCallback = callback;
mInProgressListeners.clear();
@@ -102,8 +102,7 @@
mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall
&& phone == phoneForEmergencyCall, timeoutCallbackInterval);
}
- powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber,
- forNormalRoutingEmergencyCall);
+ powerOnRadio(forEmergencyCall, phoneForEmergencyCall, isTestEmergencyNumber);
if (SatelliteController.getInstance().isSatelliteEnabledOrBeingEnabled()) {
powerOffSatellite();
}
@@ -114,25 +113,17 @@
* get an onServiceStateChanged() callback when the radio successfully comes up.
*/
private void powerOnRadio(boolean forEmergencyCall, Phone phoneForEmergencyCall,
- boolean isTestEmergencyNumber, boolean forNormalRoutingEmergencyCall) {
+ boolean isTestEmergencyNumber) {
// 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) && !forNormalRoutingEmergencyCall);
+ phone.setRadioPowerOnForTestEmergencyCall(phone == phoneForEmergencyCall);
} else {
- 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);
+ phone.setRadioPower(true, forEmergencyCall, phone == phoneForEmergencyCall,
+ false);
}
}
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index 3a3f6c8..f44dc70 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -157,6 +157,11 @@
public void onRegistrationFailure(int causeCode) {
Rlog.d(TAG, "onRegistrationFailure: causeCode " + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ Rlog.d(TAG, "onTerrestrialNetworkAvailableChanged: isAvailable " + isAvailable);
+ }
};
private Callback mCallback; // The callback to notify upon completion.
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index eb389b7..b95911f 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -51,6 +52,7 @@
import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
+import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -129,6 +131,10 @@
private static final int HANDLER_MSIM_CONFIGURATION_CHANGE = 7;
// clear any carrier ImsService test overrides.
private static final int HANDLER_CLEAR_CARRIER_IMS_SERVICE_CONFIG = 8;
+ // the user has switched
+ private static final int HANDLER_USER_SWITCHED = 9;
+ // A dynamic query has failed permanently, remove the package from being tracked
+ private static final int HANDLER_REMOVE_PACKAGE_PERM_ERROR = 10;
// Delay between dynamic ImsService queries.
private static final int DELAY_DYNAMIC_QUERY_MS = 5000;
@@ -158,14 +164,19 @@
}
private static class OverrideConfig {
+ public final String packageName;
public final int slotId;
+ public final int userId;
public final boolean isCarrierService;
- public final Map<Integer, String> featureTypeToPackageMap;
+ public final int[] featureTypes;
- OverrideConfig(int slotIndex, boolean isCarrier, Map<Integer, String> feature) {
+ OverrideConfig(String pkgName, int slotIndex, int userIndex, boolean isCarrier,
+ int[] features) {
+ packageName = pkgName;
slotId = slotIndex;
+ userId = userIndex;
isCarrierService = isCarrier;
- featureTypeToPackageMap = feature;
+ featureTypes = features;
}
}
@@ -175,7 +186,8 @@
*/
@VisibleForTesting
public static class ImsServiceInfo {
- public ComponentName name;
+ public final ComponentName name;
+ public final Set<UserHandle> users = new HashSet<>();
// Determines if features were created from metadata in the manifest or through dynamic
// query.
public boolean featureFromMetadata = true;
@@ -184,7 +196,8 @@
// Map slotId->Feature
private final HashSet<ImsFeatureConfiguration.FeatureSlotPair> mSupportedFeatures;
- public ImsServiceInfo() {
+ public ImsServiceInfo(ComponentName componentName) {
+ name = componentName;
mSupportedFeatures = new HashSet<>();
}
@@ -208,37 +221,41 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
-
ImsServiceInfo that = (ImsServiceInfo) o;
-
- if (name != null ? !name.equals(that.name) : that.name != null) return false;
- if (!mSupportedFeatures.equals(that.mSupportedFeatures)) {
- return false;
- }
- return controllerFactory != null ? controllerFactory.equals(that.controllerFactory)
- : that.controllerFactory == null;
+ return Objects.equals(name, that.name) && Objects.equals(users, that.users);
}
@Override
public int hashCode() {
- // We do not include mSupportedFeatures in hashcode because the internal structure
- // changes after adding.
- int result = name != null ? name.hashCode() : 0;
- result = 31 * result + (controllerFactory != null ? controllerFactory.hashCode() : 0);
- return result;
+ return Objects.hash(name, users);
}
@Override
public String toString() {
return "[ImsServiceInfo] name="
+ name
- + ", featureFromMetadata="
+ + ", user="
+ + users
+ + ",featureFromMetadata="
+ featureFromMetadata
+ ","
+ printFeatures(mSupportedFeatures);
}
}
+ private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final UserHandle handle = intent.getParcelableExtra(Intent.EXTRA_USER,
+ UserHandle.class);
+ switch (action) {
+ case Intent.ACTION_USER_SWITCHED ->
+ mHandler.obtainMessage(HANDLER_USER_SWITCHED, handle).sendToTarget();
+ }
+ }
+ };
+
// Receives broadcasts from the system involving changes to the installed applications. If
// an ImsService that we are configured to use is installed, we must bind to it.
private final BroadcastReceiver mAppChangedReceiver = new BroadcastReceiver() {
@@ -311,6 +328,17 @@
};
/**
+ * Testing interface used to mock ActivityManager in testing
+ */
+ @VisibleForTesting
+ public interface ActivityManagerProxy {
+ /**
+ * @return The current user
+ */
+ UserHandle getCurrentUser();
+ }
+
+ /**
* Testing interface used to mock SubscriptionManager in testing
*/
@VisibleForTesting
@@ -360,6 +388,13 @@
}
};
+ private ActivityManagerProxy mActivityManagerProxy = new ActivityManagerProxy() {
+ @Override
+ public UserHandle getCurrentUser() {
+ return UserHandle.of(ActivityManager.getCurrentUser());
+ }
+ };
+
/**
* Testing interface for injecting mock ImsServiceControllers.
*/
@@ -470,6 +505,11 @@
maybeRemovedImsService(packageName);
break;
}
+ case HANDLER_REMOVE_PACKAGE_PERM_ERROR: {
+ Pair<String, UserHandle> packageInfo = (Pair<String, UserHandle>) msg.obj;
+ maybeRemovedImsServiceForUser(packageInfo.first, packageInfo.second);
+ break;
+ }
case HANDLER_BOOT_COMPLETE: {
if (!mBootCompletedHandlerRan) {
mBootCompletedHandlerRan = true;
@@ -517,11 +557,15 @@
}
case HANDLER_OVERRIDE_IMS_SERVICE_CONFIG: {
OverrideConfig config = (OverrideConfig) msg.obj;
+ setPackageNameUserOverride(config.packageName, config.userId);
+ Map<Integer, String> featureConfig = new HashMap<>();
+ for (int featureType : config.featureTypes) {
+ featureConfig.put(featureType, config.packageName);
+ }
if (config.isCarrierService) {
- overrideCarrierService(config.slotId,
- config.featureTypeToPackageMap);
+ overrideCarrierService(config.slotId, featureConfig);
} else {
- overrideDeviceService(config.featureTypeToPackageMap);
+ overrideDeviceService(featureConfig);
}
break;
}
@@ -534,6 +578,11 @@
clearCarrierServiceOverrides(msg.arg1);
break;
}
+ case HANDLER_USER_SWITCHED: {
+ UserHandle handle = (UserHandle) msg.obj;
+ Log.i(TAG, "onUserSwitched=" + handle);
+ maybeAddedImsService(null);
+ }
default:
break;
}
@@ -561,11 +610,16 @@
}
@Override
- public void onPermanentError(ComponentName name) {
+ public void onPermanentError(ComponentName name, UserHandle user) {
Log.w(TAG, "onPermanentError: component=" + name);
mEventLog.log("onPermanentError - error for " + name);
- mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
- name.getPackageName()).sendToTarget();
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
+ name.getPackageName()).sendToTarget();
+ } else {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE_PERM_ERROR,
+ new Pair<>(name.getPackageName(), user)).sendToTarget();
+ }
}
};
@@ -573,6 +627,8 @@
// Array index corresponds to slot, per slot there is a feature->package name mapping.
// should only be accessed from handler
private final SparseArray<SparseArray<String>> mOverrideServices;
+ //Used during testing, restricts the ImsService to be bound on a specific user.
+ private final Map<String, UserHandle> mImsServiceTestUserRestrictions = new HashMap<>();
// Outer array index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
// Locked on mBoundServicesLock
private final SparseArray<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
@@ -628,6 +684,11 @@
}
@VisibleForTesting
+ public void setActivityManagerProxy(ActivityManagerProxy proxy) {
+ mActivityManagerProxy = proxy;
+ }
+
+ @VisibleForTesting
public Handler getHandler() {
return mHandler;
}
@@ -660,6 +721,10 @@
appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
appChangedFilter.addDataScheme("package");
mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
+ if (mFeatureFlags.imsResolverUserAware()) {
+ mReceiverContext.registerReceiver(mUserReceiver, new IntentFilter(
+ Intent.ACTION_USER_SWITCHED));
+ }
mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
@@ -706,19 +771,24 @@
// carrier config changed.
private void bindCarrierServicesIfAvailable() {
boolean hasConfigChanged = false;
+ boolean pendingDynamicQuery = false;
for (int slotId = 0; slotId < mNumSlots; slotId++) {
int subId = mSubscriptionManagerProxy.getSubId(slotId);
Map<Integer, String> featureMap = getImsPackageOverrideConfig(subId);
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
String newPackageName = featureMap.getOrDefault(f, "");
if (!TextUtils.isEmpty(newPackageName)) {
+ Log.d(TAG, "bindCarrierServicesIfAvailable - carrier package found: "
+ + newPackageName + ", feature "
+ + ImsFeature.FEATURE_LOG_MAP.getOrDefault(f, "invalid")
+ + " on slot " + slotId);
mEventLog.log("bindCarrierServicesIfAvailable - carrier package found: "
+ newPackageName + " on slot " + slotId);
// Carrier configs are already available, so mark received.
mCarrierConfigReceived = true;
setSubId(slotId, subId);
setCarrierConfiguredPackageName(newPackageName, slotId, f);
- ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(newPackageName);
// We do not want to trigger feature configuration changes unless there is
// already a valid carrier config change.
if (info != null && info.featureFromMetadata) {
@@ -726,11 +796,18 @@
} else {
// Config will change when this query completes
scheduleQueryForFeatures(info);
+ if (info != null) pendingDynamicQuery = true;
}
}
}
}
- if (hasConfigChanged) calculateFeatureConfigurationChange();
+ // we want to make sure that we are either pending to bind to a carrier configured service
+ // or bind to the device config if we potentially missed the carrier config changed
+ // indication.
+ if (hasConfigChanged || (mFeatureFlags.imsResolverUserAware()
+ && mCarrierConfigReceived && !pendingDynamicQuery)) {
+ calculateFeatureConfigurationChange();
+ }
}
/**
@@ -833,14 +910,15 @@
}
// Used for testing only.
- public boolean overrideImsServiceConfiguration(int slotId, boolean isCarrierService,
- Map<Integer, String> featureConfig) {
+ public boolean overrideImsServiceConfiguration(String packageName, int slotId, int userId,
+ boolean isCarrierService, int[] overrideFeatureTypes) {
if (slotId < 0 || slotId >= mNumSlots) {
Log.w(TAG, "overrideImsServiceConfiguration: invalid slotId!");
return false;
}
- OverrideConfig overrideConfig = new OverrideConfig(slotId, isCarrierService, featureConfig);
+ OverrideConfig overrideConfig = new OverrideConfig(packageName, slotId, userId,
+ isCarrierService, overrideFeatureTypes);
Message.obtain(mHandler, HANDLER_OVERRIDE_IMS_SERVICE_CONFIG, overrideConfig)
.sendToTarget();
return true;
@@ -881,10 +959,14 @@
}
// not synchronized, access in handler ONLY.
- private void removeOverridePackageName(int slotId) {
+ private Set<String> removeOverridePackageName(int slotId) {
+ Set<String> removedOverrides = new HashSet<>();
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
- getOverridePackageName(slotId).remove(f);
+ SparseArray<String> overrides = getOverridePackageName(slotId);
+ String packageName = overrides.removeReturnOld(f);
+ if (packageName != null) removedOverrides.add(packageName);
}
+ return removedOverrides;
}
// not synchronized, access in handler ONLY.
@@ -894,6 +976,22 @@
}
// not synchronized, access in handler ONLY.
+ private void setPackageNameUserOverride(String packageName, int userId) {
+ if (packageName == null || packageName.isEmpty() || userId == UserHandle.USER_NULL) return;
+ Log.i(TAG, "setPackageNameUserOverride: set for " + packageName + ", user= " + userId);
+ mImsServiceTestUserRestrictions.put(packageName, UserHandle.of(userId));
+ }
+
+ // not synchronized, access in handler ONLY.
+ private void clearPackageNameUserOverride(String packageName) {
+ UserHandle handle = mImsServiceTestUserRestrictions.remove(packageName);
+ if (handle != null) {
+ Log.i(TAG, "clearPackageNameUserOverride: cleared for " + packageName
+ + "on user " + handle);
+ }
+ }
+
+ // not synchronized, access in handler ONLY.
private @Nullable String getOverridePackageName(int slotId,
@ImsFeature.FeatureType int featureType) {
return getOverridePackageName(slotId).get(featureType);
@@ -927,13 +1025,14 @@
/**
* Check the cached ImsServices that exist on this device to determine if there is a ImsService
- * with the same package name that matches the provided configuration.
+ * with the same package name that matches the provided configuration and is configured to run
+ * in one of the active users.
*/
// not synchronized, access in handler ONLY.
private boolean doesCachedImsServiceExist(String packageName, int slotId,
@ImsFeature.FeatureType int featureType) {
// Config exists, but the carrier ImsService also needs to support this feature
- ImsServiceInfo info = getImsServiceInfoFromCache(packageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(packageName);
return info != null && info.getSupportedFeatures().stream().anyMatch(
feature -> feature.slotId == slotId && feature.featureType == featureType);
}
@@ -1073,7 +1172,8 @@
return null;
}
- private void putImsController(int slotId, int feature, ImsServiceController controller) {
+ private void putImsController(int slotId, int subId, int feature,
+ ImsServiceController controller) {
if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.FEATURE_INVALID
|| feature >= ImsFeature.FEATURE_MAX) {
Log.w(TAG, "putImsController received invalid parameters - slot: " + slotId
@@ -1088,9 +1188,9 @@
}
mEventLog.log("putImsController - [" + slotId + ", "
+ ImsFeature.FEATURE_LOG_MAP.get(feature) + "] -> " + controller);
- Log.i(TAG, "ImsServiceController added on slot: " + slotId + " with feature: "
- + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
- + controller.getComponentName());
+ Log.i(TAG, "ImsServiceController added on slot: " + slotId + ", subId: " + subId
+ + " with feature: " + ImsFeature.FEATURE_LOG_MAP.get(feature)
+ + " using package: " + controller.getComponentName());
services.put(feature, controller);
}
}
@@ -1134,6 +1234,10 @@
// features. Will only be one (if it exists), since it is a set.
ImsServiceInfo match = getInfoByComponentName(mInstalledServicesCache, info.name);
if (match != null) {
+ if (mFeatureFlags.imsResolverUserAware()) {
+ match.users.clear();
+ match.users.addAll(info.users);
+ }
// for dynamic query the new "info" will have no supported features yet. Don't wipe
// out the cache for the existing features or update yet. Instead start a query
// for features dynamically.
@@ -1141,9 +1245,8 @@
mEventLog.log("maybeAddedImsService - updating features for " + info.name
+ ": " + printFeatures(match.getSupportedFeatures()) + " -> "
+ printFeatures(info.getSupportedFeatures()));
- Log.i(TAG, "Updating features in cached ImsService: " + info.name);
- Log.d(TAG, "Updating features - Old features: " + match + " new features: "
- + info);
+ Log.d(TAG, "Updating features in cached ImsService: " + info.name
+ + ", old features: " + match + " new features: " + info);
// update features in the cache
match.replaceFeatures(info.getSupportedFeatures());
requiresCalculation = true;
@@ -1168,10 +1271,9 @@
if (requiresCalculation) calculateFeatureConfigurationChange();
}
- // Remove the ImsService from the cache. This may have been due to the ImsService being removed
- // from the device or was returning permanent errors when bound.
+ // Remove the ImsService from the cache due to the ImsService package being removed.
// Called from the handler ONLY
- private boolean maybeRemovedImsService(String packageName) {
+ private boolean maybeRemovedImsServiceOld(String packageName) {
ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
if (match != null) {
mInstalledServicesCache.remove(match.name);
@@ -1184,6 +1286,70 @@
return false;
}
+ // Remove the ImsService from the cache due to the ImsService package being removed.
+ // Called from the handler ONLY
+ private boolean maybeRemovedImsService(String packageName) {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return maybeRemovedImsServiceOld(packageName);
+ }
+ ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
+ if (match != null) {
+ List<ImsServiceInfo> imsServices = searchForImsServices(packageName,
+ match.controllerFactory);
+ ImsServiceInfo newMatch = imsServices.isEmpty() ? null : imsServices.getFirst();
+ if (newMatch == null) {
+ clearPackageNameUserOverride(match.name.getPackageName());
+ // The package doesn't exist anymore on any user, so remove
+ mInstalledServicesCache.remove(match.name);
+ mEventLog.log("maybeRemovedImsService - removing ImsService: " + match);
+ Log.i(TAG, "maybeRemovedImsService Removing ImsService for all users: "
+ + match.name);
+ unbindImsService(match);
+ } else {
+ // The Package exists on some users still, so modify the users
+ match.users.clear();
+ match.users.addAll(newMatch.users);
+ mEventLog.log("maybeRemovedImsService - modifying ImsService users: " + match);
+ Log.i(TAG, "maybeRemovedImsService - Modifying ImsService users " + match);
+ // If this package still remains on some users, then it is possible we are unbinding
+ // an active ImsService, but the assumption here is that the package is being
+ // removed on an active user. Be safe and unbind now - we will rebind below if
+ // needed.
+ unbindImsService(match);
+ }
+ calculateFeatureConfigurationChange();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove the cached ImsService for a specific user. If there are no more users available after
+ * removing the specified user, remove the ImsService cache entry entirely.
+ */
+ // Called from the handler ONLY
+ private boolean maybeRemovedImsServiceForUser(String packageName, UserHandle user) {
+ ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
+ if (match != null) {
+ mEventLog.log("maybeRemovedImsServiceForUser - removing ImsService " + match
+ + "for user " + user);
+ Log.i(TAG, "maybeRemovedImsServiceForUser: Removing ImsService "
+ + match + "for user " + user);
+ unbindImsService(match);
+ match.users.remove(user);
+ if (match.users.isEmpty()) {
+ mEventLog.log("maybeRemovedImsServiceForUser - no more users, removing "
+ + "ImsService " + match);
+ Log.i(TAG, "maybeRemovedImsServiceForUser - no more users, removing "
+ + "ImsService " + match);
+ mInstalledServicesCache.remove(match.name);
+ }
+ calculateFeatureConfigurationChange();
+ return true;
+ }
+ return false;
+ }
+
private boolean isDeviceService(ImsServiceInfo info) {
if (info == null) return false;
synchronized (mDeviceServices) {
@@ -1193,6 +1359,14 @@
private List<Integer> getSlotsForActiveCarrierService(ImsServiceInfo info) {
if (info == null) return Collections.emptyList();
+ if (mFeatureFlags.imsResolverUserAware()) {
+ UserHandle activeUser = getUserForBind(info);
+ if (activeUser == null) {
+ Log.d(TAG, "getSlotsForActiveCarrierService: ImsService " + info.name + "is not "
+ + "configured to run for any users, skipping...");
+ return Collections.emptyList();
+ }
+ }
List<Integer> slots = new ArrayList<>(mNumSlots);
for (int i = 0; i < mNumSlots; i++) {
if (!TextUtils.isEmpty(getCarrierConfiguredPackageNames(i).values().stream()
@@ -1222,7 +1396,7 @@
return searchMap.get(matchValue);
}
- private void bindImsServiceWithFeatures(ImsServiceInfo info,
+ private void bindImsServiceWithFeatures(ImsServiceInfo info, UserHandle user,
Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
// Only bind if there are features that will be created by the service.
if (shouldFeaturesCauseBind(features)) {
@@ -1230,10 +1404,21 @@
ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, info);
SparseIntArray slotIdToSubIdMap = mSlotIdToSubIdMap.clone();
if (controller != null) {
- Log.i(TAG, "ImsService connection exists for " + info.name + ", updating features "
- + features);
try {
- controller.changeImsServiceFeatures(features, slotIdToSubIdMap);
+ if (!mFeatureFlags.imsResolverUserAware()
+ || Objects.equals(user, controller.getBoundUser())) {
+ Log.i(TAG, "ImsService connection exists for " + info.name
+ + ", updating features " + features);
+ controller.changeImsServiceFeatures(features, slotIdToSubIdMap);
+ } else {
+ // Changing a user is a pretty rare event, we need to unbind and rebind
+ // on the correct new user.
+ Log.i(TAG, "ImsService user changed for " + info.name
+ + ", rebinding on user " + user + ", features " + features);
+ controller.unbind();
+ controller.bind(user, features, slotIdToSubIdMap);
+ }
+
// Features have been set, there was an error adding/removing. When the
// controller recovers, it will add/remove again.
} catch (RemoteException e) {
@@ -1243,8 +1428,9 @@
controller = info.controllerFactory.create(mContext, info.name, this, mRepo,
mFeatureFlags);
Log.i(TAG, "Binding ImsService: " + controller.getComponentName()
- + " with features: " + features);
- controller.bind(features, slotIdToSubIdMap);
+ + "on user " + user + " with features: " + features + ", subIdMap: "
+ + slotIdToSubIdMap);
+ controller.bind(user, features, slotIdToSubIdMap);
mEventLog.log("bindImsServiceWithFeatures - create new controller: "
+ controller);
}
@@ -1285,7 +1471,7 @@
imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
.filter(feature -> info.name.getPackageName().equals(
getCarrierConfiguredPackageName(feature.slotId, feature.featureType)))
- .collect(Collectors.toList()));
+ .toList());
return imsFeaturesBySlot;
}
if (isDeviceService(info)) {
@@ -1298,7 +1484,7 @@
// by the carrier ImsService.
.filter(feature -> !doesCarrierConfigurationExist(feature.slotId,
feature.featureType))
- .collect(Collectors.toList()));
+ .toList());
}
return imsFeaturesBySlot;
}
@@ -1309,8 +1495,9 @@
* adds the ImsServiceController from the mBoundImsServicesByFeature structure.
*/
@Override
- public void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller) {
- putImsController(slotId, feature, controller);
+ public void imsServiceFeatureCreated(int slotId, int subId, int feature,
+ ImsServiceController controller) {
+ putImsController(slotId, subId, feature, controller);
}
/**
@@ -1341,13 +1528,19 @@
}
@Override
- public void imsServiceBindPermanentError(ComponentName name) {
+ public void imsServiceBindPermanentError(ComponentName name, UserHandle user) {
if (name == null) {
return;
}
- Log.w(TAG, "imsServiceBindPermanentError: component=" + name);
- mEventLog.log("imsServiceBindPermanentError - for " + name);
- mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget();
+ Log.w(TAG, "imsServiceBindPermanentError: component=" + name + ", user=" + user);
+ mEventLog.log("imsServiceBindPermanentError - for " + name + ", user " + user);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
+ name.getPackageName()).sendToTarget();
+ } else {
+ mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE_PERM_ERROR,
+ new Pair<>(name.getPackageName(), user)).sendToTarget();
+ }
}
/**
@@ -1381,7 +1574,10 @@
private void clearCarrierServiceOverrides(int slotId) {
Log.i(TAG, "clearing carrier ImsService overrides");
mEventLog.log("clearing carrier ImsService overrides");
- removeOverridePackageName(slotId);
+ Set<String> removedPackages = removeOverridePackageName(slotId);
+ for (String pkg : removedPackages) {
+ clearPackageNameUserOverride(pkg);
+ }
carrierConfigChanged(slotId, getSubId(slotId));
}
@@ -1399,8 +1595,9 @@
+ oldPackageName + " -> " + overridePackageName);
mEventLog.log("overrideDeviceService - device package changed (override): "
+ oldPackageName + " -> " + overridePackageName);
+ clearPackageNameUserOverride(oldPackageName);
setDeviceConfiguration(overridePackageName, featureType);
- ImsServiceInfo info = getImsServiceInfoFromCache(overridePackageName);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(overridePackageName);
if (info == null || info.featureFromMetadata) {
requiresRecalc = true;
} else {
@@ -1430,7 +1627,7 @@
ArrayMap<String, ImsServiceInfo> featureDynamicImsPackages = new ArrayMap<>();
for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
String packageName = getDeviceConfiguration(f);
- ImsServiceInfo serviceInfo = getImsServiceInfoFromCache(packageName);
+ ImsServiceInfo serviceInfo = getVisibleImsServiceInfoFromCache(packageName);
if (serviceInfo != null && !serviceInfo.featureFromMetadata
&& !featureDynamicImsPackages.containsKey(packageName)) {
featureDynamicImsPackages.put(packageName, serviceInfo);
@@ -1465,13 +1662,7 @@
setCarrierConfiguredPackageName(newPackageName, slotId, f);
// Carrier config may have not changed, but we still want to kick off a recalculation
// in case there has been a change to the supported device features.
- ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
- Log.i(TAG, "updateBoundServices - carrier package changed: "
- + oldPackageName + " -> " + newPackageName + " on slot " + slotId
- + ", hasConfigChanged=" + hasConfigChanged);
- mEventLog.log("updateBoundServices - carrier package changed: "
- + oldPackageName + " -> " + newPackageName + " on slot " + slotId
- + ", hasConfigChanged=" + hasConfigChanged);
+ ImsServiceInfo info = getVisibleImsServiceInfoFromCache(newPackageName);
if (info == null || info.featureFromMetadata) {
hasConfigChanged = true;
} else {
@@ -1479,6 +1670,12 @@
scheduleQueryForFeatures(info);
didQuerySchedule = true;
}
+ Log.i(TAG, "updateBoundServices - carrier package changed: "
+ + oldPackageName + " -> " + newPackageName + " on slot " + slotId
+ + ", hasConfigChanged=" + hasConfigChanged);
+ mEventLog.log("updateBoundServices - carrier package changed: "
+ + oldPackageName + " -> " + newPackageName + " on slot " + slotId
+ + ", hasConfigChanged=" + hasConfigChanged);
}
if (hasConfigChanged) calculateFeatureConfigurationChange();
@@ -1530,7 +1727,7 @@
}
private void scheduleQueryForFeatures(ComponentName name, int delayMs) {
- ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
+ ImsServiceInfo service = getVisibleImsServiceInfoFromCache(name.getPackageName());
if (service == null) {
Log.w(TAG, "scheduleQueryForFeatures: Couldn't find cached info for name: " + name);
return;
@@ -1614,6 +1811,12 @@
// Starts a dynamic query. Called from handler ONLY.
private void startDynamicQuery(ImsServiceInfo service) {
+ UserHandle user = getUserForBind(service);
+ if (user == null) {
+ Log.i(TAG, "scheduleQueryForFeatures: skipping query for ImsService that is not"
+ + " running: " + service);
+ return;
+ }
// if not current device/carrier service, don't perform query. If this changes, this method
// will be called again.
if (!isDeviceService(service) && getSlotsForActiveCarrierService(service).isEmpty()) {
@@ -1622,7 +1825,7 @@
return;
}
mEventLog.log("startDynamicQuery - starting query for " + service);
- boolean queryStarted = mFeatureQueryManager.startQuery(service.name,
+ boolean queryStarted = mFeatureQueryManager.startQuery(service.name, user,
service.controllerFactory.getServiceInterface());
if (!queryStarted) {
Log.w(TAG, "startDynamicQuery: service could not connect. Retrying after delay.");
@@ -1637,7 +1840,7 @@
// process complete dynamic query. Called from handler ONLY.
private void dynamicQueryComplete(ComponentName name,
Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
- ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
+ ImsServiceInfo service = getVisibleImsServiceInfoFromCache(name.getPackageName());
if (service == null) {
Log.w(TAG, "dynamicQueryComplete: Couldn't find cached info for name: "
+ name);
@@ -1683,17 +1886,92 @@
// Calculate the new configuration for the bound ImsServices.
// Should ONLY be called from the handler.
- private void calculateFeatureConfigurationChange() {
+ private void calculateFeatureConfigurationChangeOld() {
for (ImsServiceInfo info : mInstalledServicesCache.values()) {
Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
if (shouldFeaturesCauseBind(features)) {
- bindImsServiceWithFeatures(info, features);
+ bindImsServiceWithFeatures(info, mContext.getUser(), features);
} else {
unbindImsService(info);
}
}
}
+ // Should ONLY be called from the handler.
+ private void calculateFeatureConfigurationChange() {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ calculateFeatureConfigurationChangeOld();
+ return;
+ }
+ // There is an implicit assumption here that the ImsServiceController will remove itself
+ // from caches BEFORE adding a new one. If this assumption is broken, we will remove a valid
+ // ImsServiceController from the cache accidentally. To keep this assumption valid, we will
+ // iterate through the cache twice - first to unbind, then to bind and change features of
+ // existing ImsServiceControllers. This is a little inefficient, but there should be on the
+ // order of 10 installed ImsServices at most, so running through this list twice is
+ // reasonable vs the memory cost of caching binding vs unbinding services.
+
+ // Unbind first if needed
+ for (ImsServiceInfo info : mInstalledServicesCache.values()) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
+ UserHandle user = getUserForBind(info);
+ if (shouldFeaturesCauseBind(features) && user != null) continue;
+ unbindImsService(info);
+ }
+ // Bind/alter features second
+ for (ImsServiceInfo info : mInstalledServicesCache.values()) {
+ Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
+ UserHandle user = getUserForBind(info);
+ if (shouldFeaturesCauseBind(features) && user != null) {
+ bindImsServiceWithFeatures(info, user, features);
+ }
+ }
+ }
+
+ /**
+ * Returns the UserHandle that should be used to bind the ImsService.
+ *
+ * @return The UserHandle of the user that telephony is running in if the
+ * ImsService is configured to run in that user, or the current active user
+ * if not. Returns null if the ImsService is not configured to run in any
+ * active user.
+ */
+ private UserHandle getUserForBind(ImsServiceInfo info) {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return mContext.getUser();
+ }
+ UserHandle currentUser = mActivityManagerProxy.getCurrentUser();
+ List<UserHandle> activeUsers = getActiveUsers().stream()
+ .filter(info.users::contains).toList();
+ if (activeUsers.isEmpty()) return null;
+ // If there is a test restriction in place for this package, prioritize that restriction
+ UserHandle testRestriction = mImsServiceTestUserRestrictions.getOrDefault(
+ info.name.getPackageName(), null);
+ if (testRestriction != null && activeUsers.stream()
+ .anyMatch(u -> Objects.equals(u, testRestriction))) {
+ return testRestriction;
+ }
+ // Prioritize the User that Telephony is in, since it is always running
+ if (activeUsers.stream()
+ .anyMatch(u -> Objects.equals(u, mContext.getUser()))) {
+ return mContext.getUser();
+ }
+ if (activeUsers.stream().anyMatch(u -> Objects.equals(u, currentUser))) {
+ return currentUser;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of full users that are currently active.
+ */
+ private Set<UserHandle> getActiveUsers() {
+ Set<UserHandle> profiles = new HashSet<>();
+ profiles.add(mContext.getUser());
+ profiles.add(mActivityManagerProxy.getCurrentUser());
+ return profiles;
+ }
+
private static String printFeatures(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
StringBuilder featureString = new StringBuilder();
featureString.append(" features: [");
@@ -1711,8 +1989,24 @@
}
/**
- * Returns the ImsServiceInfo that matches the provided packageName. Visible for testing
- * the ImsService caching functionality.
+ * Returns the ImsServiceInfo that matches the provided packageName if it belongs to a
+ * package that is visible as part of the set of active users.
+ */
+ public ImsServiceInfo getVisibleImsServiceInfoFromCache(String packageName) {
+ ImsServiceInfo match = getImsServiceInfoFromCache(packageName);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return match;
+ }
+ if (match == null) return null;
+ UserHandle targetUser = getUserForBind(match);
+ Log.d(TAG, "getVisibleImsServiceInfoFromCache: " + packageName + ", match=" + match
+ + ", targetUser=" + targetUser);
+ if (targetUser != null) return match; else return null;
+ }
+
+ /**
+ * Returns the ImsServiceInfo that matches the provided packageName. This includes
+ * ImsServiceInfos that are not currently visible for the active users.
*/
@VisibleForTesting
public ImsServiceInfo getImsServiceInfoFromCache(String packageName) {
@@ -1738,6 +2032,12 @@
return infos;
}
+ private ImsServiceInfo getInfoFromCache(List<ImsServiceInfo> infos,
+ ComponentName componentName) {
+ return infos.stream().filter(info -> Objects.equals(info.name, componentName)).findFirst()
+ .orElse(null);
+ }
+
private List<ImsServiceInfo> searchForImsServices(String packageName,
ImsServiceControllerFactory controllerFactory) {
List<ImsServiceInfo> infos = new ArrayList<>();
@@ -1745,62 +2045,84 @@
Intent serviceIntent = new Intent(controllerFactory.getServiceInterface());
serviceIntent.setPackage(packageName);
+ Set<UserHandle> profiles;
+ if (mFeatureFlags.imsResolverUserAware()) {
+ profiles = getActiveUsers();
+ } else {
+ profiles = Collections.singleton(mContext.getUser());
+ }
+ Log.v(TAG, "searchForImsServices: package=" + packageName + ", users=" + profiles);
+
PackageManager packageManager = mContext.getPackageManager();
- for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
- serviceIntent,
- PackageManager.GET_META_DATA,
- UserHandle.of(UserHandle.myUserId()))) {
- ServiceInfo serviceInfo = entry.serviceInfo;
+ for (UserHandle handle : profiles) {
+ for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(serviceIntent,
+ PackageManager.GET_META_DATA, handle)) {
+ ServiceInfo serviceInfo = entry.serviceInfo;
- if (serviceInfo != null) {
- ImsServiceInfo info = new ImsServiceInfo();
- info.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
- info.controllerFactory = controllerFactory;
+ if (serviceInfo != null) {
+ ComponentName name = new ComponentName(serviceInfo.packageName,
+ serviceInfo.name);
+ ImsServiceInfo info = getInfoFromCache(infos, name);
+ if (info != null) {
+ info.users.add(handle);
+ Log.d(TAG, "service modify users:" + info);
+ continue;
+ } else {
+ info = new ImsServiceInfo(name);
+ info.users.add(handle);
+ }
+ info.controllerFactory = controllerFactory;
- // we will allow the manifest method of declaring manifest features in two cases:
- // 1) it is the device overlay "default" ImsService, where the features do not
- // change (the new method can still be used if the default does not define manifest
- // entries).
- // 2) using the "compat" ImsService, which only supports manifest query.
- if (isDeviceService(info)
- || mImsServiceControllerFactoryCompat == controllerFactory) {
- if (serviceInfo.metaData != null) {
- if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
- info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_MMTEL);
- // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
- if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE,
- false)) {
- info.addFeatureForAllSlots(mNumSlots,
- ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ // we will allow the manifest method of declaring manifest features in two
+ // cases:
+
+ // 1) it is the device overlay "default" ImsService, where the features do not
+ // change (the new method can still be used if the default does not define
+ // manifest entries).
+ // 2) using the "compat" ImsService, which only supports manifest query.
+ if (isDeviceService(info)
+ || mImsServiceControllerFactoryCompat == controllerFactory) {
+ if (serviceInfo.metaData != null) {
+ if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
+ info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_MMTEL);
+ // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
+ if (serviceInfo.metaData.getBoolean(
+ METADATA_EMERGENCY_MMTEL_FEATURE,
+ false)) {
+ info.addFeatureForAllSlots(mNumSlots,
+ ImsFeature.FEATURE_EMERGENCY_MMTEL);
+ }
+ }
+ if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
+ info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_RCS);
}
}
- if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
- info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_RCS);
+ // Only dynamic query if we are not a compat version of ImsService and the
+ // default service.
+ if (mImsServiceControllerFactoryCompat != controllerFactory
+ && info.getSupportedFeatures().isEmpty()) {
+ // metadata empty, try dynamic query instead
+ info.featureFromMetadata = false;
}
- }
- // Only dynamic query if we are not a compat version of ImsService and the
- // default service.
- if (mImsServiceControllerFactoryCompat != controllerFactory
- && info.getSupportedFeatures().isEmpty()) {
- // metadata empty, try dynamic query instead
+ } else {
+ // We are a carrier service and not using the compat version of ImsService.
info.featureFromMetadata = false;
}
- } else {
- // We are a carrier service and not using the compat version of ImsService.
- info.featureFromMetadata = false;
- }
- Log.i(TAG, "service name: " + info.name + ", manifest query: "
- + info.featureFromMetadata);
- // Check manifest permission to be sure that the service declares the correct
- // permissions. Overridden if the METADATA_OVERRIDE_PERM_CHECK metadata is set to
- // true.
- // NOTE: METADATA_OVERRIDE_PERM_CHECK should only be set for testing.
- if (TextUtils.equals(serviceInfo.permission, Manifest.permission.BIND_IMS_SERVICE)
- || serviceInfo.metaData.getBoolean(METADATA_OVERRIDE_PERM_CHECK, false)) {
- infos.add(info);
- } else {
- Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
- + info.name);
+ Log.d(TAG, "service name: " + info.name + ", manifest query: "
+ + info.featureFromMetadata + ", users: " + info.users);
+ // Check manifest permission to be sure that the service declares the correct
+ // permissions. Overridden if the METADATA_OVERRIDE_PERM_CHECK metadata is set
+ // to true.
+ // NOTE: METADATA_OVERRIDE_PERM_CHECK should only be set for testing.
+ if (TextUtils.equals(serviceInfo.permission,
+ Manifest.permission.BIND_IMS_SERVICE)
+ || serviceInfo.metaData.getBoolean(METADATA_OVERRIDE_PERM_CHECK,
+ false)) {
+ infos.add(info);
+ } else {
+ Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
+ + info.name);
+ }
}
}
}
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index ea8399f..37c10eb 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -196,7 +196,7 @@
}
if (mCallbacks != null) {
// Will trigger an unbind.
- mCallbacks.imsServiceBindPermanentError(getComponentName());
+ mCallbacks.imsServiceBindPermanentError(getComponentName(), mBoundUser);
}
}
@@ -217,7 +217,8 @@
/**
* Called by ImsServiceController when a new MMTEL or RCS feature has been created.
*/
- void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller);
+ void imsServiceFeatureCreated(int slotId, int subId, int feature,
+ ImsServiceController controller);
/**
* Called by ImsServiceController when a new MMTEL or RCS feature has been removed.
*/
@@ -234,7 +235,7 @@
* Called by the ImsServiceController when there has been an error binding that is
* not recoverable, such as the ImsService returning a null binder.
*/
- void imsServiceBindPermanentError(ComponentName name);
+ void imsServiceBindPermanentError(ComponentName name, UserHandle user);
}
/**
@@ -273,6 +274,7 @@
private boolean mIsBound = false;
private boolean mIsBinding = false;
+ private UserHandle mBoundUser = null;
// Set of a pair of slotId->feature
private Set<ImsFeatureConfiguration.FeatureSlotPair> mImsFeatures;
private SparseIntArray mSlotIdToSubIdMap;
@@ -337,7 +339,7 @@
if (mIsBound) {
return;
}
- bind(mImsFeatures, mSlotIdToSubIdMap);
+ bind(mBoundUser, mImsFeatures, mSlotIdToSubIdMap);
}
}
};
@@ -413,17 +415,18 @@
* @return {@link true} if the service is in the process of being bound, {@link false} if it
* has failed.
*/
- public boolean bind(Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet,
- SparseIntArray slotIdToSubIdMap) {
+ public boolean bind(UserHandle user, Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet,
+ SparseIntArray slotIdToSubIdMap) {
synchronized (mLock) {
if (!mIsBound && !mIsBinding) {
mIsBinding = true;
+ mBoundUser = user;
sanitizeFeatureConfig(imsFeatureSet);
mImsFeatures = imsFeatureSet;
mSlotIdToSubIdMap = slotIdToSubIdMap;
// Set the number of slots that support the feature
mImsEnablementTracker.setNumOfSlots(mSlotIdToSubIdMap.size());
- grantPermissionsToService();
+ grantPermissionsToService(user);
Intent imsServiceIntent = new Intent(getServiceInterface()).setComponent(
mComponentName);
mImsServiceConnection = new ImsServiceConnection();
@@ -432,8 +435,8 @@
mLocalLog.log("binding " + imsFeatureSet);
Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
try {
- boolean bindSucceeded = mContext.bindService(imsServiceIntent,
- mImsServiceConnection, serviceFlags);
+ boolean bindSucceeded = mContext.bindServiceAsUser(imsServiceIntent,
+ mImsServiceConnection, serviceFlags, user);
if (!bindSucceeded) {
mLocalLog.log(" binding failed, retrying in "
+ mBackoff.getCurrentDelay() + " mS");
@@ -482,6 +485,7 @@
changeImsServiceFeatures(new HashSet<>(), mSlotIdToSubIdMap);
mIsBound = false;
mIsBinding = false;
+ mBoundUser = null;
setServiceController(null);
unbindService();
}
@@ -608,6 +612,13 @@
}
/**
+ * @return The UserHandle that this controller is bound to or null if bound to no service.
+ */
+ public UserHandle getBoundUser() {
+ return mBoundUser;
+ }
+
+ /**
* Notify ImsService to enable IMS for the framework. This will trigger IMS registration and
* trigger ImsFeature status updates.
*/
@@ -766,7 +777,7 @@
// Grant runtime permissions to ImsService. PermissionManager ensures that the ImsService is
// system/signed before granting permissions.
- private void grantPermissionsToService() {
+ private void grantPermissionsToService(UserHandle user) {
mLocalLog.log("grant permissions to " + getComponentName());
Log.i(LOG_TAG, "Granting Runtime permissions to:" + getComponentName());
String[] pkgToGrant = {mComponentName.getPackageName()};
@@ -774,8 +785,7 @@
if (mPermissionManager != null) {
CountDownLatch latch = new CountDownLatch(1);
mPermissionManager.grantDefaultPermissionsToEnabledImsServices(
- pkgToGrant, UserHandle.of(UserHandle.myUserId()), Runnable::run,
- isSuccess -> {
+ pkgToGrant, user, Runnable::run, isSuccess -> {
if (isSuccess) {
latch.countDown();
} else {
@@ -807,7 +817,8 @@
Log.i(LOG_TAG, "supports emergency calling on slot " + featurePair.slotId);
}
// Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
- mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
+ mCallbacks.imsServiceFeatureCreated(featurePair.slotId, subId, featurePair.featureType,
+ this);
}
// This method should only be called when synchronized on mLock
@@ -978,10 +989,11 @@
@Override
public String toString() {
synchronized (mLock) {
- return "[ImsServiceController: componentName=" + getComponentName() + ", features="
- + mImsFeatures + ", isBinding=" + mIsBinding + ", isBound=" + mIsBound
- + ", serviceController=" + getImsServiceController() + ", rebindDelay="
- + getRebindDelay() + "]";
+ return "[ImsServiceController: componentName=" + getComponentName() + ", boundUser="
+ + mBoundUser + ", features=" + mImsFeatures + ", isBinding=" + mIsBinding
+ + ", isBound=" + mIsBound + ", serviceController=" + getImsServiceController()
+ + ", rebindDelay=" + getRebindDelay() + ", slotToSubIdMap=" + mSlotIdToSubIdMap
+ + "]";
}
}
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java b/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
index 564cdcc..a4b4f46 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceFeatureQueryManager.java
@@ -21,6 +21,7 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
+import android.os.UserHandle;
import android.telephony.ims.aidl.IImsServiceController;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.util.Log;
@@ -42,14 +43,16 @@
private static final String LOG_TAG = "ImsServiceFeatureQuery";
private final ComponentName mName;
+ private final UserHandle mUser;
private final String mIntentFilter;
// Track the status of whether or not the Service has died in case we need to permanently
// unbind (see onNullBinding below).
private boolean mIsServiceConnectionDead = false;
- ImsServiceFeatureQuery(ComponentName name, String intentFilter) {
+ ImsServiceFeatureQuery(ComponentName name, UserHandle user, String intentFilter) {
mName = name;
+ mUser = user;
mIntentFilter = intentFilter;
}
@@ -62,7 +65,8 @@
Intent imsServiceIntent = new Intent(mIntentFilter).setComponent(mName);
int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_IMPORTANT;
- boolean bindStarted = mContext.bindService(imsServiceIntent, this, serviceFlags);
+ boolean bindStarted = mContext.bindServiceAsUser(imsServiceIntent, this,
+ serviceFlags, mUser);
if (!bindStarted) {
// Docs say to unbind if this fails.
cleanup();
@@ -78,7 +82,7 @@
} else {
Log.w(LOG_TAG, "onServiceConnected: " + name + " binder null.");
cleanup();
- mListener.onPermanentError(name);
+ mListener.onPermanentError(name, mUser);
}
}
@@ -103,7 +107,7 @@
// permanently unbind and instead let the automatic rebind occur.
if (mIsServiceConnectionDead) return;
cleanup();
- mListener.onPermanentError(name);
+ mListener.onPermanentError(name, mUser);
}
private void queryImsFeatures(IImsServiceController controller) {
@@ -154,7 +158,7 @@
/**
* Called when a query has failed due to a permanent error and should not be retried.
*/
- void onPermanentError(ComponentName name);
+ void onPermanentError(ComponentName name, UserHandle user);
}
// Maps an active ImsService query (by Package Name String) its query.
@@ -171,16 +175,17 @@
/**
* Starts an ImsService feature query for the ComponentName and Intent specified.
* @param name The ComponentName of the ImsService being queried.
+ * @param user The User associated with the request.
* @param intentFilter The Intent filter that the ImsService specified.
* @return true if the query started, false if it was unable to start.
*/
- public boolean startQuery(ComponentName name, String intentFilter) {
+ public boolean startQuery(ComponentName name, UserHandle user, String intentFilter) {
synchronized (mLock) {
if (mActiveQueries.containsKey(name)) {
// We already have an active query, wait for it to return.
return true;
}
- ImsServiceFeatureQuery query = new ImsServiceFeatureQuery(name, intentFilter);
+ ImsServiceFeatureQuery query = new ImsServiceFeatureQuery(name, user, intentFilter);
mActiveQueries.put(name, query);
return query.start();
}
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 9f74890..fdd0c0a 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -177,7 +177,6 @@
/** Maximum number of Satellite relevant stats to store between pulls. */
private final int mMaxNumSatelliteStats;
- private final int mMaxNumSatelliteControllerStats = 1;
private final int mMaxNumCarrierRoamingSatelliteSessionStats = 1;
/** Maximum number of data network validation to store during pulls. */
@@ -710,76 +709,75 @@
/** Adds a new {@link SatelliteController} to the storage. */
public synchronized void addSatelliteControllerStats(SatelliteController stats) {
- // SatelliteController is a single data point
- SatelliteController[] atomArray = mAtoms.satelliteController;
- if (atomArray == null || atomArray.length == 0) {
- atomArray = new SatelliteController[] {new SatelliteController()};
+ // find existing satellite controller atom with same carrier ID.
+ SatelliteController existingStats = find(stats);
+ if (existingStats != null) {
+ existingStats.countOfSatelliteServiceEnablementsSuccess
+ += stats.countOfSatelliteServiceEnablementsSuccess;
+ existingStats.countOfSatelliteServiceEnablementsFail
+ += stats.countOfSatelliteServiceEnablementsFail;
+ existingStats.countOfOutgoingDatagramSuccess
+ += stats.countOfOutgoingDatagramSuccess;
+ existingStats.countOfOutgoingDatagramFail
+ += stats.countOfOutgoingDatagramFail;
+ existingStats.countOfIncomingDatagramSuccess
+ += stats.countOfIncomingDatagramSuccess;
+ existingStats.countOfIncomingDatagramFail
+ += stats.countOfIncomingDatagramFail;
+ existingStats.countOfDatagramTypeSosSmsSuccess
+ += stats.countOfDatagramTypeSosSmsSuccess;
+ existingStats.countOfDatagramTypeSosSmsFail
+ += stats.countOfDatagramTypeSosSmsFail;
+ existingStats.countOfDatagramTypeLocationSharingSuccess
+ += stats.countOfDatagramTypeLocationSharingSuccess;
+ existingStats.countOfDatagramTypeLocationSharingFail
+ += stats.countOfDatagramTypeLocationSharingFail;
+ existingStats.countOfProvisionSuccess
+ += stats.countOfProvisionSuccess;
+ existingStats.countOfProvisionFail
+ += stats.countOfProvisionFail;
+ existingStats.countOfDeprovisionSuccess
+ += stats.countOfDeprovisionSuccess;
+ existingStats.countOfDeprovisionFail
+ += stats.countOfDeprovisionFail;
+ existingStats.totalServiceUptimeSec
+ += stats.totalServiceUptimeSec;
+ existingStats.totalBatteryConsumptionPercent
+ += stats.totalBatteryConsumptionPercent;
+ existingStats.totalBatteryChargedTimeSec
+ += stats.totalBatteryChargedTimeSec;
+ existingStats.countOfDemoModeSatelliteServiceEnablementsSuccess
+ += stats.countOfDemoModeSatelliteServiceEnablementsSuccess;
+ existingStats.countOfDemoModeSatelliteServiceEnablementsFail
+ += stats.countOfDemoModeSatelliteServiceEnablementsFail;
+ existingStats.countOfDemoModeOutgoingDatagramSuccess
+ += stats.countOfDemoModeOutgoingDatagramSuccess;
+ existingStats.countOfDemoModeOutgoingDatagramFail
+ += stats.countOfDemoModeOutgoingDatagramFail;
+ existingStats.countOfDemoModeIncomingDatagramSuccess
+ += stats.countOfDemoModeIncomingDatagramSuccess;
+ existingStats.countOfDemoModeIncomingDatagramFail
+ += stats.countOfDemoModeIncomingDatagramFail;
+ existingStats.countOfDatagramTypeKeepAliveSuccess
+ += stats.countOfDatagramTypeKeepAliveSuccess;
+ existingStats.countOfDatagramTypeKeepAliveFail
+ += stats.countOfDatagramTypeKeepAliveFail;
+ existingStats.countOfAllowedSatelliteAccess += stats.countOfAllowedSatelliteAccess;
+ existingStats.countOfDisallowedSatelliteAccess
+ += stats.countOfDisallowedSatelliteAccess;
+ existingStats.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
+
+ existingStats.isProvisioned = stats.isProvisioned;
+
+ existingStats.countOfSatelliteAllowedStateChangedEvents
+ += stats.countOfSatelliteAllowedStateChangedEvents;
+ existingStats.countOfSuccessfulLocationQueries +=
+ stats.countOfSuccessfulLocationQueries;
+ existingStats.countOfFailedLocationQueries += stats.countOfFailedLocationQueries;
+ } else {
+ mAtoms.satelliteController = insertAtRandomPlace(mAtoms.satelliteController, stats,
+ mMaxNumSatelliteStats);
}
-
- SatelliteController atom = atomArray[0];
- atom.countOfSatelliteServiceEnablementsSuccess
- += stats.countOfSatelliteServiceEnablementsSuccess;
- atom.countOfSatelliteServiceEnablementsFail
- += stats.countOfSatelliteServiceEnablementsFail;
- atom.countOfOutgoingDatagramSuccess
- += stats.countOfOutgoingDatagramSuccess;
- atom.countOfOutgoingDatagramFail
- += stats.countOfOutgoingDatagramFail;
- atom.countOfIncomingDatagramSuccess
- += stats.countOfIncomingDatagramSuccess;
- atom.countOfIncomingDatagramFail
- += stats.countOfIncomingDatagramFail;
- atom.countOfDatagramTypeSosSmsSuccess
- += stats.countOfDatagramTypeSosSmsSuccess;
- atom.countOfDatagramTypeSosSmsFail
- += stats.countOfDatagramTypeSosSmsFail;
- atom.countOfDatagramTypeLocationSharingSuccess
- += stats.countOfDatagramTypeLocationSharingSuccess;
- atom.countOfDatagramTypeLocationSharingFail
- += stats.countOfDatagramTypeLocationSharingFail;
- atom.countOfProvisionSuccess
- += stats.countOfProvisionSuccess;
- atom.countOfProvisionFail
- += stats.countOfProvisionFail;
- atom.countOfDeprovisionSuccess
- += stats.countOfDeprovisionSuccess;
- atom.countOfDeprovisionFail
- += stats.countOfDeprovisionFail;
- atom.totalServiceUptimeSec
- += stats.totalServiceUptimeSec;
- atom.totalBatteryConsumptionPercent
- += stats.totalBatteryConsumptionPercent;
- atom.totalBatteryChargedTimeSec
- += stats.totalBatteryChargedTimeSec;
- atom.countOfDemoModeSatelliteServiceEnablementsSuccess
- += stats.countOfDemoModeSatelliteServiceEnablementsSuccess;
- atom.countOfDemoModeSatelliteServiceEnablementsFail
- += stats.countOfDemoModeSatelliteServiceEnablementsFail;
- atom.countOfDemoModeOutgoingDatagramSuccess
- += stats.countOfDemoModeOutgoingDatagramSuccess;
- atom.countOfDemoModeOutgoingDatagramFail
- += stats.countOfDemoModeOutgoingDatagramFail;
- atom.countOfDemoModeIncomingDatagramSuccess
- += stats.countOfDemoModeIncomingDatagramSuccess;
- atom.countOfDemoModeIncomingDatagramFail
- += stats.countOfDemoModeIncomingDatagramFail;
- atom.countOfDatagramTypeKeepAliveSuccess
- += stats.countOfDatagramTypeKeepAliveSuccess;
- atom.countOfDatagramTypeKeepAliveFail
- += stats.countOfDatagramTypeKeepAliveFail;
- atom.countOfAllowedSatelliteAccess += stats.countOfAllowedSatelliteAccess;
- atom.countOfDisallowedSatelliteAccess += stats.countOfDisallowedSatelliteAccess;
- atom.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
-
- atom.isProvisioned = stats.isProvisioned;
- atom.carrierId = stats.carrierId;
-
- atom.countOfSatelliteAllowedStateChangedEvents
- += stats.countOfSatelliteAllowedStateChangedEvents;
- atom.countOfSuccessfulLocationQueries += stats.countOfSuccessfulLocationQueries;
- atom.countOfFailedLocationQueries += stats.countOfFailedLocationQueries;
-
- mAtoms.satelliteController = atomArray;
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
}
@@ -1825,7 +1823,7 @@
atoms.outgoingShortCodeSms = sanitizeAtoms(atoms.outgoingShortCodeSms,
OutgoingShortCodeSms.class, mMaxOutgoingShortCodeSms);
atoms.satelliteController = sanitizeAtoms(atoms.satelliteController,
- SatelliteController.class, mMaxNumSatelliteControllerStats);
+ SatelliteController.class, mMaxNumSatelliteStats);
atoms.satelliteSession = sanitizeAtoms(atoms.satelliteSession,
SatelliteSession.class, mMaxNumSatelliteStats);
atoms.satelliteIncomingDatagram = sanitizeAtoms(atoms.satelliteIncomingDatagram,
@@ -1848,7 +1846,7 @@
mMaxNumSatelliteStats);
atoms.carrierRoamingSatelliteControllerStats = sanitizeAtoms(
atoms.carrierRoamingSatelliteControllerStats,
- CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteControllerStats);
+ CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteStats);
atoms.satelliteEntitlement = sanitizeAtoms(atoms.satelliteEntitlement,
SatelliteEntitlement.class, mMaxNumSatelliteStats);
atoms.satelliteConfigUpdater = sanitizeAtoms(atoms.satelliteConfigUpdater,
@@ -2390,6 +2388,19 @@
}
/**
+ * Returns SatelliteController atom that has same carrier_id value or
+ * {@code null} if does not exist.
+ */
+ private @Nullable SatelliteController find(SatelliteController key) {
+ for (SatelliteController stats : mAtoms.satelliteController) {
+ if (stats.carrierId == key.carrierId) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns CarrierRoamingSatelliteControllerStats atom that has same carrier_id value or
* {@code null} if does not exist.
*/
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 9f6edf2..acd3fd1 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@@ -419,6 +420,15 @@
&& mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
return false;
}
+ boolean allowCheckMessageInNotConnected =
+ mContext.getResources().getBoolean(
+ R.bool.config_satellite_allow_check_message_in_not_connected);
+ if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS
+ && mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED
+ && allowCheckMessageInNotConnected
+ && mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return false;
+ }
if (mSatelltieModemState != SATELLITE_MODEM_STATE_CONNECTED
&& mSatelltieModemState != SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING) {
return true;
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 42aa2aa..5c3bcb0 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -16,9 +16,13 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
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_MODEM_STATE_DATAGRAM_TRANSFERRING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
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;
@@ -75,6 +79,7 @@
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 int EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT = 10;
private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@@ -130,6 +135,15 @@
private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
@Nullable private PersistentLogger mPersistentLogger = null;
+ @GuardedBy("mLock")
+ private int mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ @GuardedBy("mLock")
+ private boolean mHasEnteredConnectedState = false;
+ @GuardedBy("mLock")
+ private boolean mShouldPollMtSms = false;
+ @GuardedBy("mLock")
+ private boolean mIsMtSmsPollingThrottled = false;
+
/**
* Create the DatagramDispatcher singleton instance.
* @param context The Context to use to create the DatagramDispatcher.
@@ -402,6 +416,16 @@
break;
}
+ case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
+ synchronized (mLock) {
+ mIsMtSmsPollingThrottled = false;
+ if (allowMtSmsPolling()) {
+ sendMtSmsPollingMessage();
+ }
+ }
+ break;
+ }
+
default:
plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
@@ -491,6 +515,9 @@
mIsAligned = isAligned;
plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
+ if (allowMtSmsPolling()) {
+ sendMtSmsPollingMessage();
+ }
}
}
@@ -598,6 +625,13 @@
pendingDatagram.iterator().next().getValue();
if (mDatagramController.needsWaitingForSatelliteConnected(datagramArg.datagramType)) {
plogd("sendPendingDatagrams: wait for satellite connected");
+ mDatagramController.updateSendStatus(datagramArg.subId,
+ datagramArg.datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(
+ datagramArg.datagramType);
return;
}
@@ -719,6 +753,8 @@
private void reportSendDatagramCompleted(@NonNull SendSatelliteDatagramArgument argument,
@NonNull @SatelliteManager.SatelliteResult int resultCode) {
+ long datagramTransmissionTime = argument.datagramStartTime > 0
+ ? (System.currentTimeMillis() - argument.datagramStartTime) : 0;
SatelliteStats.getInstance().onSatelliteOutgoingDatagramMetrics(
new SatelliteStats.SatelliteOutgoingDatagramParams.Builder()
.setDatagramType(argument.datagramType)
@@ -726,15 +762,15 @@
.setDatagramSizeBytes(argument.getDatagramRoundedSizeBytes())
/* In case pending datagram has not been attempted to send to modem
interface. transfer time will be 0. */
- .setDatagramTransferTimeMillis(argument.datagramStartTime > 0
- ? (System.currentTimeMillis() - argument.datagramStartTime) : 0)
+ .setDatagramTransferTimeMillis(datagramTransmissionTime)
.setIsDemoMode(mIsDemoMode)
.setCarrierId(SatelliteController.getInstance().getSatelliteCarrierId())
.build());
if (resultCode == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
mControllerMetricsStats.reportOutgoingDatagramSuccessCount(argument.datagramType,
mIsDemoMode);
- mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(argument.datagramType);
+ mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(argument.datagramType,
+ datagramTransmissionTime);
} else {
mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
mIsDemoMode);
@@ -759,6 +795,7 @@
*/
public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
synchronized (mLock) {
+ mModemState = state;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
|| state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
plogd("onSatelliteModemStateChanged: cleaning up resources");
@@ -767,10 +804,23 @@
sendPendingMessages();
}
- if (state == SATELLITE_MODEM_STATE_CONNECTED
- && isDatagramWaitForConnectedStateTimerStarted()) {
- stopDatagramWaitForConnectedStateTimer();
- sendPendingMessages();
+ if (state == SATELLITE_MODEM_STATE_CONNECTED) {
+ mHasEnteredConnectedState = true;
+ if (isDatagramWaitForConnectedStateTimerStarted()) {
+ stopDatagramWaitForConnectedStateTimer();
+ sendPendingMessages();
+ }
+ }
+
+ if (state == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ if (mHasEnteredConnectedState) {
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = shouldPollMtSms();
+ }
+ }
+
+ if (allowMtSmsPolling()) {
+ sendMtSmsPollingMessage();
}
}
}
@@ -803,6 +853,10 @@
mSendSatelliteDatagramRequest = null;
mIsAligned = false;
mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
+ mModemState = SATELLITE_MODEM_STATE_UNKNOWN;
+ mHasEnteredConnectedState = false;
+ mShouldPollMtSms = false;
+ stopMtSmsPollingThrottle();
}
/** @return {@code true} if already sent an emergency datagram during a session. */
@@ -1060,7 +1114,8 @@
synchronized (mLock) {
// Add SMS to pending list
mPendingSmsMap.put(messageId, pendingSms);
- int datagramType = SatelliteManager.DATAGRAM_TYPE_SMS;
+ int datagramType = pendingSms.isMtSmsPolling ?
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
mLastSendRequestDatagramType = datagramType;
if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
@@ -1099,14 +1154,23 @@
}
if (pendingSms != null && pendingSms.iterator().hasNext()) {
+ PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
+ int datagramType = pendingRequest.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
if (mDatagramController.needsWaitingForSatelliteConnected(DATAGRAM_TYPE_SMS)) {
plogd("sendPendingSms: wait for satellite connected");
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ getPendingMessagesCount(),
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ startDatagramWaitForConnectedStateTimer(datagramType);
return;
}
mSendingInProgress = true;
- PendingRequest pendingRequest = pendingSms.iterator().next().getValue();
- mDatagramController.updateSendStatus(subId, DATAGRAM_TYPE_SMS,
+ mDatagramController.updateSendStatus(subId,
+ datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
sendMessage(obtainMessage(CMD_SEND_SMS, pendingRequest));
@@ -1169,18 +1233,30 @@
private void handleEventSendSmsDone(int subId, long messageId, boolean success) {
synchronized (mLock) {
+ PendingRequest pendingSms = mPendingSmsMap.remove(messageId);
+ if (pendingSms == null) {
+ // Just return, the SMS is not sent by DatagramDispatcher such as Data SMS
+ plogd("handleEventSendSmsDone there is no pendingSms for messageId=" + messageId);
+ return;
+ }
+
mSendingInProgress = false;
- mPendingSmsMap.remove(messageId);
- int datagramType = DATAGRAM_TYPE_SMS;
+ int datagramType = pendingSms.isMtSmsPolling
+ ? DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS : DATAGRAM_TYPE_SMS;
plogd("handleEventSendSmsDone subId=" + subId + " messageId=" + messageId
- + " success=" + success);
+ + " success=" + success + " datagramType=" + datagramType);
+
if (success) {
- // Update send status for current datagram
+ // Update send status
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
getPendingMessagesCount(), SATELLITE_RESULT_SUCCESS);
+ if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS) {
+ startMtSmsPollingThrottle();
+ }
} else {
+ // Update send status
mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingMessagesCount(), SATELLITE_RESULT_NETWORK_ERROR);
@@ -1196,6 +1272,95 @@
}
}
+ private boolean isEnabledMtSmsPolling() {
+ return mContext.getResources().getBoolean(R.bool.config_enabled_mt_sms_polling);
+ }
+
+ private long getMtSmsPollingThrottleMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_mt_sms_polling_throttle_millis);
+ }
+
+ private boolean shouldPollMtSms() {
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ Phone satellitePhone = satelliteController.getSatellitePhone();
+ return isEnabledMtSmsPolling()
+ && satelliteController.shouldSendSmsToDatagramDispatcher(satellitePhone);
+ }
+
+ @GuardedBy("mLock")
+ private void sendMtSmsPollingMessage() {
+ if (!mShouldPollMtSms) {
+ return;
+ }
+
+ plogd("sendMtSmsPollingMessage");
+ mShouldPollMtSms = false;
+
+ for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
+ PendingRequest pendingRequest = entry.getValue();
+ if (pendingRequest.isMtSmsPolling) {
+ plogd("sendMtSmsPollingMessage: mPendingSmsMap already has the polling message.");
+ return;
+ }
+ }
+
+ Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("sendMtSmsPollingMessage: satellitePhone is null.");
+ return;
+ }
+
+ SmsDispatchersController smsDispatchersController =
+ satellitePhone.getSmsDispatchersController();
+ if (smsDispatchersController == null) {
+ ploge("sendMtSmsPollingMessage: smsDispatchersController is null.");
+ return;
+ }
+
+ smsDispatchersController.sendMtSmsPollingMessage();
+ }
+
+ @GuardedBy("mLock")
+ private void startMtSmsPollingThrottle() {
+ plogd("startMtSmsPollingThrottle");
+ mIsMtSmsPollingThrottled = true;
+ sendMessageDelayed(obtainMessage(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT),
+ getMtSmsPollingThrottleMillis());
+ }
+
+ @GuardedBy("mLock")
+ private void stopMtSmsPollingThrottle() {
+ mIsMtSmsPollingThrottled = false;
+ removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
+ }
+
+ @GuardedBy("mLock")
+ private boolean allowMtSmsPolling() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) return false;
+
+ if (mIsMtSmsPollingThrottled) return false;
+
+ if (!mIsAligned) return false;
+
+ boolean isModemStateConnectedOrTransferring =
+ mModemState == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED
+ || mModemState
+ == SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
+ if (!isModemStateConnectedOrTransferring && !allowCheckMessageInNotConnected()) {
+ plogd("EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT:"
+ + " allow_check_message_in_not_connected is disabled");
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean allowCheckMessageInNotConnected() {
+ return mContext.getResources()
+ .getBoolean(R.bool.config_satellite_allow_check_message_in_not_connected);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index a921b89..75771d0 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -376,6 +376,10 @@
});
}
+ // Send the captured data about incoming datagram to metric
+ sInstance.reportMetrics(satelliteDatagram,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+
if (pendingCount <= 0) {
sInstance.mDatagramController.updateReceiveStatus(mSubId,
SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
@@ -393,10 +397,6 @@
internalCallback::accept);
sInstance.pollPendingSatelliteDatagramsInternal(mSubId, callback);
}
-
- // Send the captured data about incoming datagram to metric
- sInstance.reportMetrics(satelliteDatagram,
- SatelliteManager.SATELLITE_RESULT_SUCCESS);
break;
}
@@ -748,8 +748,8 @@
(int) (Math.round((double) sizeBytes / ROUNDING_UNIT) * ROUNDING_UNIT);
}
datagramTransferTime = (System.currentTimeMillis() - mDatagramTransferStartTime);
- mDatagramTransferStartTime = 0;
}
+ mDatagramTransferStartTime = 0;
SatelliteStats.getInstance().onSatelliteIncomingDatagramMetrics(
new SatelliteStats.SatelliteIncomingDatagramParams.Builder()
diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
index 7b64c61..d908597 100644
--- a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
+++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
@@ -287,12 +287,12 @@
* and {@code false} to disable
* @param errorCallback The callback to receive the error code result of the operation.
*/
- public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled,
+ public void enableTerrestrialNetworkScanWhileSatelliteModeIsOn(boolean enabled,
@NonNull IIntegerConsumer errorCallback) {
try {
errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS);
} catch (RemoteException e) {
- loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ loge("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: RemoteException " + e);
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index dfc7919..4b53178 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -52,7 +52,8 @@
logd("Registered to satellite PLMN " + satellitePlmn);
networkRegistrationInfo.setIsNonTerrestrialNetwork(true);
networkRegistrationInfo.setAvailableServices(
- satelliteController.getSupportedSatelliteServices(subId, satellitePlmn));
+ satelliteController.getSupportedSatelliteServicesForPlmn(
+ subId, satellitePlmn));
break;
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 6876ad5..a64f24c 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -22,6 +22,7 @@
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_TYPE;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
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;
@@ -29,17 +30,21 @@
import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE;
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_DATA_SUPPORT_MODE_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
-import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY;
import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.SubscriptionManager.isValidSubscriptionId;
@@ -53,6 +58,7 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
@@ -62,6 +68,7 @@
import android.annotation.ArrayRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -75,7 +82,9 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.devicestate.DeviceState;
@@ -109,6 +118,7 @@
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
+import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.NetworkRegistrationInfo;
@@ -118,6 +128,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -125,6 +136,7 @@
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
+import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
@@ -133,12 +145,14 @@
import android.telephony.satellite.SatelliteSubscriberInfo;
import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.telephony.satellite.SystemSelectionSpecifier;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.uwb.UwbManager;
+import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -160,6 +174,7 @@
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.FunctionalUtils;
@@ -173,6 +188,7 @@
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
+import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -212,6 +228,11 @@
/** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
"oem_enabled_satellite_provision_status_key";
+ /** Key used to read/write default messages application NTN SMS support
+ * in shared preferences. */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public static final String NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY =
+ "ntn_sms_supported_by_messages_app_key";
public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS =
TimeUnit.SECONDS.toMillis(30);
@@ -220,6 +241,14 @@
private static final long WAIT_FOR_REPORT_ENTITLED_MERTICS_TIMEOUT_MILLIS =
TimeUnit.HOURS.toMillis(23);
+ /**
+ * Delay SatelliteEnable request when network selection auto. current RIL not verified to
+ * response right after network selection auto changed. Some RIL has delay for waiting in-svc
+ * with Automatic selection request.
+ */
+ private static final long DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS =
+ TimeUnit.SECONDS.toMillis(1);
+
/** Message codes used in handleMessage() */
//TODO: Move the Commands and events related to position updates to PointingAppController
private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1;
@@ -272,6 +301,12 @@
EVENT_WAIT_FOR_UPDATE_SATELLITE_ENABLE_ATTRIBUTES_RESPONSE_TIMED_OUT = 52;
private static final int EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT = 53;
protected static final int EVENT_SATELLITE_REGISTRATION_FAILURE = 54;
+ private static final int EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED = 55;
+ private static final int EVENT_SET_NETWORK_SELECTION_AUTO_DONE = 56;
+ private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 57;
+ private static final int CMD_UPDATE_SYSTEM_SELECTION_CHANNELS = 58;
+ private static final int EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = 59;
+ private static final int EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED = 60;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -354,6 +389,8 @@
new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteRegistrationFailure =
new AtomicBoolean(false);
+ private final AtomicBoolean mRegisteredForTerrestrialNetworkAvailableChanged =
+ new AtomicBoolean(false);
/**
* Map key: subId, value: callback to get error code of the provision request.
*/
@@ -388,9 +425,22 @@
*/
private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback>
mSatelliteRegistrationFailureListeners = new ConcurrentHashMap<>();
- private final Object mIsSatelliteSupportedLock = new Object();
+ /**
+ * Map key: binder of the callback, value: callback to receive terrestrial network
+ * available changed
+ */
+ private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback>
+ mTerrestrialNetworkAvailableChangedListeners = new ConcurrentHashMap<>();
+ /**
+ * Map key: binder of the callback, value: callback to receive selected NB IOT satellite
+ * subscription changed
+ */
+ private final ConcurrentHashMap<IBinder, ISelectedNbIotSatelliteSubscriptionCallback>
+ mSelectedNbIotSatelliteSubscriptionChangedListeners = new ConcurrentHashMap<>();
+
+ protected final Object mIsSatelliteSupportedLock = new Object();
@GuardedBy("mIsSatelliteSupportedLock")
- private Boolean mIsSatelliteSupported = null;
+ protected Boolean mIsSatelliteSupported = null;
private boolean mIsDemoModeEnabled = false;
private boolean mIsEmergency = false;
private final Object mIsSatelliteEnabledLock = new Object();
@@ -404,11 +454,11 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean mRadioOffRequested = false;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected final Object mSatelliteViaOemProvisionLock = new Object();
+ protected final Object mDeviceProvisionLock = new Object();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- @GuardedBy("mSatelliteViaOemProvisionLock")
- protected Boolean mIsSatelliteViaOemProvisioned = null;
- @GuardedBy("mSatelliteViaOemProvisionLock")
+ @GuardedBy("mDeviceProvisionLock")
+ protected Boolean mIsDeviceProvisioned = null;
+ @GuardedBy("mDeviceProvisionLock")
private Boolean mOverriddenIsSatelliteViaOemProvisioned = null;
private final Object mSatelliteCapabilitiesLock = new Object();
@GuardedBy("mSatelliteCapabilitiesLock")
@@ -446,6 +496,13 @@
* {@code true} for enabled and {@code false} for disabled. */
@NonNull private final Map<Integer, Boolean> mIsSatelliteAttachEnabledForCarrierArrayPerSub =
new HashMap<>();
+ /** Key: subId, value: (key: Regional satellite config Id string, value: Integer
+ * arrays of earfcns in the corresponding regions.)
+ */
+ @GuardedBy("mRegionalSatelliteEarfcnsLock")
+ @NonNull private final Map<Integer, Map<String, Set<Integer>>>
+ mRegionalSatelliteEarfcns = new HashMap<>();
+ @NonNull private final Object mRegionalSatelliteEarfcnsLock = new Object();
@NonNull private final FeatureFlags mFeatureFlags;
@NonNull private final Object mSatelliteConnectedLock = new Object();
/** Key: Subscription ID; Value: Last satellite connected time */
@@ -489,6 +546,10 @@
@NonNull private final Map<Integer, List<Integer>>
mSatModeCapabilitiesForCarrierRoaming = new HashMap<>();
+ @GuardedBy("mSatelliteConnectedLock")
+ private SparseArray<NtnSignalStrength> mLastNotifiedCarrierRoamingNtnSignalStrength =
+ new SparseArray<>();
+
/**
* This is used for testing only. When mEnforcedEmergencyCallToSatelliteHandoverType is valid,
* Telephony will ignore the IMS registration status and cellular availability, and always send
@@ -518,6 +579,21 @@
* carrierPlmnList. */
@GuardedBy("mSupportedSatelliteServicesLock")
private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>();
+ /** Key Subscription ID, value : map to plmn info with related data plan. */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ SparseArray<Map<String, Integer>> mEntitlementDataPlanMapPerCarrier = new SparseArray<>();
+ /** Key Subscription ID, value : map to plmn info with related service type. */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ SparseArray<Map<String, List<Integer>>> mEntitlementServiceTypeMapPerCarrier =
+ new SparseArray<>();
+ /** Key Subscription ID, value : map to plmn info with related service policy for data service */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ SparseArray<Map<String, Integer>> mEntitlementDataServicePolicyMapPerCarrier =
+ new SparseArray<>();
+ /** Key Subscription ID, value : map to plmn info with related service policy for voice service */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ SparseArray<Map<String, Integer>> mEntitlementVoiceServicePolicyMapPerCarrier =
+ new SparseArray<>();
private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
// key : subscriberId, value : provisioned or not.
@GuardedBy("mSatelliteTokenProvisionedLock")
@@ -530,6 +606,11 @@
@GuardedBy("mSatelliteTokenProvisionedLock")
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected TreeMap<Integer, List<SubscriptionInfo>> mSubsInfoListPerPriority = new TreeMap<>();
+ // List of subscriber information and status at the time of last evaluation
+ @GuardedBy("mSatelliteTokenProvisionedLock")
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ private List<SatelliteSubscriberProvisionStatus> mLastEvaluatedSubscriberProvisionStatus =
+ new ArrayList<>();
// The ID of the satellite subscription that has highest priority and is provisioned.
@GuardedBy("mSatelliteTokenProvisionedLock")
private int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -547,6 +628,7 @@
private long mLastEmergencyCallTime;
private long mSatelliteEmergencyModeDurationMillis;
private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300;
+ private AlertDialog mNetworkSelectionModeAutoDialog = null;
/** Key used to read/write satellite system notification done in shared preferences. */
private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
@@ -586,6 +668,21 @@
private static final String ACTION_NOTIFICATION_CLICK = "action_notification_click";
private static final String ACTION_NOTIFICATION_DISMISS = "action_notification_dismiss";
private AtomicBoolean mOverrideNtnEligibility;
+ private String mDefaultSmsPackageName = "";
+ private String mSatelliteGatewayServicePackageName = "";
+
+ private final Object mNtnSmsSupportedByMessagesAppLock = new Object();
+ @GuardedBy("mNtnSmsSupportedByMessagesAppLock")
+ private Boolean mNtnSmsSupportedByMessagesApp = null;
+
+ private final Object mSatelliteModemStateLock = new Object();
+ @GuardedBy("mSatelliteModemStateLock")
+ @SatelliteManager.SatelliteModemState
+ private int mSatelliteModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
+
+ // Data Plan types at entitlement for the plmn allowed
+ public static final int SATELLITE_DATA_PLAN_METERED = 0;
+ public static final int SATELLITE_DATA_PLAN_UNMETERED = 1;
private BroadcastReceiver
mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -598,10 +695,110 @@
}
};
+ private BroadcastReceiver mPackageStateChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+ mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage();
+ String schemeSpecificPart = intent.getData().getSchemeSpecificPart();
+ plogd("packageStateChanged: " + intent.getData().toString()
+ + " DefaultSmsPackageName:" + mDefaultSmsPackageName);
+
+ if (!schemeSpecificPart.equals(mSatelliteGatewayServicePackageName)
+ && !schemeSpecificPart.equals(mDefaultSmsPackageName)) {
+ plogv("Neither SMS or SatelliteGateway package");
+ return;
+ }
+ int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
+ if (activeSubIds != null) {
+ for (int activeSubId : activeSubIds) {
+ plogd("mPackageStateChangedReceiver: activeSubId= " + activeSubId);
+ handleCarrierRoamingNtnAvailableServicesChanged(activeSubId);
+ }
+ } else {
+ ploge("mPackageStateChangedReceiver: activeSubIds is null");
+ }
+ }
+ };
+
// List of device states returned from DeviceStateManager to determine if running on a foldable
// device.
private List<DeviceState> mDeviceStates = new ArrayList();
+ public static final int RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD = 500;
+ protected final Object mResultReceiverTotalCountLock = new Object();
+ @GuardedBy("mResultReceiverTotalCountLock")
+ protected int mResultReceiverTotalCount;
+ @GuardedBy("mResultReceiverTotalCountLock")
+ protected HashMap<String, Integer> mResultReceiverCountPerMethodMap = new HashMap<>();
+
+ // Satellite anomaly uuid -- ResultReceiver count threshold exceeded
+ private final UUID mAnomalyUnexpectedResultReceiverCountUUID =
+ UUID.fromString("e268f22d-9bba-4d27-b76a-1c7f5b42e241");
+
+ private UUID generateAnomalyUnexpectedResultReceiverCountUUID(int error, int errorCode) {
+ long lerror = error;
+ long lerrorCode = errorCode;
+ return new UUID(mAnomalyUnexpectedResultReceiverCountUUID.getMostSignificantBits(),
+ mAnomalyUnexpectedResultReceiverCountUUID.getLeastSignificantBits()
+ + ((lerrorCode << 32) + lerror));
+ }
+
+ /**
+ * Increments the ResultReceiver count and logs the caller information.
+ * If the count exceeds the threshold, it reports an anomaly via AnomalyReporter.
+ *
+ * @param caller The caller information that created the ResultReceiver
+ * (e.g., class name and method name)
+ */
+ public void incrementResultReceiverCount(String caller) {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ synchronized (mResultReceiverTotalCountLock) {
+ mResultReceiverTotalCount++;
+ logd("[incrementResultReceiverCount] : " + caller
+ + " | ResultReceiver total count= " + mResultReceiverTotalCount);
+ mResultReceiverCountPerMethodMap.compute(caller,
+ (k, v) -> v == null ? 1 : v + 1);
+
+ if (mResultReceiverTotalCount > RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD) {
+ loge("[mResultReceiverTotalCount] is exceeds limits : "
+ + mResultReceiverTotalCount);
+ loge("[incrementResultReceiverCount] mResultReceiverCountPerMethodMap is "
+ + mResultReceiverCountPerMethodMap);
+ AnomalyReporter.reportAnomaly(
+ generateAnomalyUnexpectedResultReceiverCountUUID(0, 0),
+ "Satellite ResultReceiver total count= "
+ + mResultReceiverTotalCount + " exceeds limit.");
+ }
+ }
+ } else {
+ logd("[incrementResultReceiverCount]: carrierRoamingNbIotNtn is not enabled");
+ }
+ }
+
+ /**
+ * Decrements the ResultReceiver count and logs the caller information.
+ * Prevents the count from going below zero.
+ *
+ * @param caller The caller information that released the ResultReceiver
+ * (e.g., class name and method name)
+ */
+ public void decrementResultReceiverCount(String caller) {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ synchronized (mResultReceiverTotalCountLock) {
+ if (mResultReceiverTotalCount > 0) {
+ mResultReceiverTotalCount--;
+ }
+ logd("[decrementResultReceiverCount] : " + caller
+ + " | ResultReceiver total count=" + mResultReceiverTotalCount);
+ mResultReceiverCountPerMethodMap.computeIfPresent(caller,
+ (k, v) -> v > 0 ? v - 1 : v);
+ }
+ } else {
+ logd("[decrementResultReceiverCount]: carrierRoamingNbIotNtn is not enabled");
+ }
+ }
+
/**
* @return The singleton instance of SatelliteController.
*/
@@ -686,6 +883,7 @@
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
registerForServiceStateChanged();
+ registerForSignalStrengthChanged();
mContentResolver = mContext.getContentResolver();
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
@@ -706,6 +904,7 @@
}
mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig();
+ registerApplicationStateChanged();
updateSupportedSatelliteServicesForActiveSubscriptions();
mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) ->
@@ -729,7 +928,15 @@
mDSM.registerForSignalStrengthReportDecision(this, CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING,
null);
+
loadSatelliteSharedPreferences();
+ if (mSharedPreferences != null) {
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = mSharedPreferences.getBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+ }
+ }
+
mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis();
mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources();
mDemoPointingNotAlignedDurationMillis =
@@ -924,15 +1131,13 @@
public void onStateChanged(int state, int reason) {
plogd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state));
plogd("Adapter state changed reason " + String.valueOf(reason));
- synchronized (mRadioStateLock) {
- if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) {
- mUwbStateEnabled = false;
- evaluateToSendSatelliteEnabledSuccess();
- } else {
- mUwbStateEnabled = true;
- }
- plogd("mUwbStateEnabled: " + mUwbStateEnabled);
+ if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) {
+ setUwbEnabledState(false);
+ evaluateToSendSatelliteEnabledSuccess();
+ } else {
+ setUwbEnabledState(true);
}
+ plogd("mUwbStateEnabled: " + getUwbEnabledState());
}
}
@@ -949,50 +1154,47 @@
case BluetoothAdapter.ACTION_STATE_CHANGED:
int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
- synchronized (mRadioStateLock) {
- boolean currentBTStateEnabled = mBTStateEnabled;
- if (btState == BluetoothAdapter.STATE_OFF) {
- mBTStateEnabled = false;
- evaluateToSendSatelliteEnabledSuccess();
- } else if (btState == BluetoothAdapter.STATE_ON) {
- mBTStateEnabled = true;
- }
- if (currentBTStateEnabled != mBTStateEnabled) {
- plogd("mBTStateEnabled=" + mBTStateEnabled);
- }
+ boolean currentBTStateEnabled = getBTEnabledState();
+ if (btState == BluetoothAdapter.STATE_OFF) {
+ setBTEnabledState(false);
+ evaluateToSendSatelliteEnabledSuccess();
+ } else if (btState == BluetoothAdapter.STATE_ON) {
+ setBTEnabledState(true);
+ }
+
+ if (currentBTStateEnabled != getBTEnabledState()) {
+ plogd("mBTStateEnabled=" + getBTEnabledState());
}
break;
case NfcAdapter.ACTION_ADAPTER_STATE_CHANGED:
int nfcState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, -1);
- synchronized (mRadioStateLock) {
- boolean currentNfcStateEnabled = mNfcStateEnabled;
- if (nfcState == NfcAdapter.STATE_ON) {
- mNfcStateEnabled = true;
- } else if (nfcState == NfcAdapter.STATE_OFF) {
- mNfcStateEnabled = false;
- evaluateToSendSatelliteEnabledSuccess();
- }
- if (currentNfcStateEnabled != mNfcStateEnabled) {
- plogd("mNfcStateEnabled=" + mNfcStateEnabled);
- }
+ boolean currentNfcStateEnabled = getNfcEnabledState();
+ if (nfcState == NfcAdapter.STATE_ON) {
+ setNfcEnabledState(true);
+ } else if (nfcState == NfcAdapter.STATE_OFF) {
+ setNfcEnabledState(false);
+ evaluateToSendSatelliteEnabledSuccess();
+ }
+
+ if (currentNfcStateEnabled != getNfcEnabledState()) {
+ plogd("mNfcStateEnabled=" + getNfcEnabledState());
}
break;
case WifiManager.WIFI_STATE_CHANGED_ACTION:
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
- synchronized (mRadioStateLock) {
- boolean currentWifiStateEnabled = mWifiStateEnabled;
- if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
- mWifiStateEnabled = true;
- } else if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
- mWifiStateEnabled = false;
- evaluateToSendSatelliteEnabledSuccess();
- }
- if (currentWifiStateEnabled != mWifiStateEnabled) {
- plogd("mWifiStateEnabled=" + mWifiStateEnabled);
- }
+ boolean currentWifiStateEnabled = getWifiEnabledState();
+ if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
+ setWifiEnabledState(true);
+ } else if (wifiState == WifiManager.WIFI_STATE_DISABLED) {
+ setWifiEnabledState(false);
+ evaluateToSendSatelliteEnabledSuccess();
+ }
+
+ if (currentWifiStateEnabled != getWifiEnabledState()) {
+ plogd("mWifiStateEnabled=" + getWifiEnabledState());
}
break;
default:
@@ -1063,6 +1265,18 @@
}
}
+ private static final class UpdateSystemSelectionChannelsArgument {
+ @NonNull List<SystemSelectionSpecifier> mSystemSelectionSpecifiers;
+ @NonNull ResultReceiver mResult;
+
+ UpdateSystemSelectionChannelsArgument(
+ @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
+ @NonNull ResultReceiver result) {
+ this.mSystemSelectionSpecifiers = systemSelectionSpecifiers;
+ this.mResult = result;
+ }
+ }
+
/**
* Arguments to send to SatelliteTransmissionUpdate registrants
*/
@@ -1215,11 +1429,12 @@
if (mNeedsSatellitePointing) {
mPointingAppController.removeListenerForPointingUI();
}
+
+ if (!isWaitingForSatelliteModemOff()) {
+ moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_SUCCESS);
+ }
+
synchronized (mSatelliteEnabledRequestLock) {
- if (!mWaitingForSatelliteModemOff) {
- moveSatelliteToOffStateAndCleanUpResources(
- SATELLITE_RESULT_SUCCESS);
- }
mWaitingForDisableSatelliteModemResponse = false;
}
}
@@ -1241,8 +1456,8 @@
// If Satellite enable/disable request returned Error, no need to wait for radio
argument.callback.accept(error);
}
-
if (argument.enableSatellite) {
+ mSessionMetricsStats.resetSessionStatsShadowCounters();
mSessionMetricsStats.setInitializationResult(error)
.setSatelliteTechnology(getSupportedNtnRadioTechnology())
.setInitializationProcessingTime(
@@ -1399,6 +1614,7 @@
updateSatelliteSupportedState(false);
}
((ResultReceiver) request.argument).send(error, bundle);
+ decrementResultReceiverCount("SC:requestIsSatelliteEnabled");
break;
}
@@ -1451,13 +1667,14 @@
synchronized (mNeedsSatellitePointingLock) {
mNeedsSatellitePointing = capabilities.isPointingRequired();
}
+
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
- overrideSatelliteCapabilitiesIfApplicable();
- if (DBG) plogd("getSatelliteCapabilities: " + mSatelliteCapabilities);
- bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
- mSatelliteCapabilities);
}
+ overrideSatelliteCapabilitiesIfApplicable();
+ if (DBG) plogd("getSatelliteCapabilities: " + getSatelliteCapabilities());
+ bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
+ getSatelliteCapabilities());
}
}
((ResultReceiver) request.argument).send(error, bundle);
@@ -1493,6 +1710,7 @@
}
}
((ResultReceiver) request.argument).send(error, bundle);
+ decrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility");
break;
}
@@ -1516,19 +1734,21 @@
if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
if (mSatelliteModemInterface.isSatelliteServiceConnected()) {
- synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported == null || !mIsSatelliteSupported) {
- ResultReceiver receiver = new ResultReceiver(this) {
- @Override
- protected void onReceiveResult(
- int resultCode, Bundle resultData) {
- plogd("onRadioStateChanged.requestIsSatelliteSupported: "
- + "resultCode=" + resultCode
- + ", resultData=" + resultData);
- }
- };
- sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null);
- }
+ Boolean isSatelliteSupported = getIsSatelliteSupported();
+ if (isSatelliteSupported == null || !isSatelliteSupported) {
+ final String caller = "SC:CMD_IS_SATELLITE_SUPPORTED";
+ ResultReceiver receiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(
+ int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(caller);
+ plogd("onRadioStateChanged.requestIsSatelliteSupported: "
+ + "resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ }
+ };
+ sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, receiver, null);
+ incrementResultReceiverCount(caller);
}
}
}
@@ -1566,6 +1786,7 @@
ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
} else {
handleEventSatelliteModemStateChanged((int) ar.result);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone());
}
break;
@@ -1645,6 +1866,7 @@
}
result.send(errorCode, null);
}
+ decrementResultReceiverCount("SC:requestNtnSignalStrength");
break;
}
@@ -1654,6 +1876,7 @@
ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
} else {
handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(getSatellitePhone());
}
break;
}
@@ -1732,12 +1955,13 @@
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();
- }
+ }
+
+ boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
+ plogd("EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT:"
+ + " isCarrierRoamingNtnEligible=" + eligible);
+ if (eligible) {
+ requestIsSatelliteAllowedForCurrentLocation();
}
break;
}
@@ -1754,7 +1978,7 @@
onCompleted = obtainMessage(EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE, request);
boolean provisionChanged = updateSatelliteSubscriptionProvisionState(
argument.mSatelliteSubscriberInfoList, argument.mProvisioned);
- selectBindingSatelliteSubscription();
+ selectBindingSatelliteSubscription(false);
int subId = getSelectedSatelliteSubId();
SubscriptionInfo subscriptionInfo =
mSubscriptionManagerService.getSubscriptionInfo(subId);
@@ -1783,6 +2007,7 @@
argument.mProvisioned ? SatelliteManager.KEY_PROVISION_SATELLITE_TOKENS
: SatelliteManager.KEY_DEPROVISION_SATELLITE_TOKENS, true);
argument.mResult.send(SATELLITE_RESULT_SUCCESS, bundle);
+ decrementResultReceiverCount("SC:provisionSatellite");
break;
}
@@ -1808,8 +2033,8 @@
mIsWifiConnected = (boolean) ar.result;
plogd("EVENT_WIFI_CONNECTIVITY_STATE_CHANGED: mIsWifiConnected="
+ mIsWifiConnected);
- handleStateChangedForCarrierRoamingNtnEligibility();
}
+ evaluateCarrierRoamingNtnEligibilityChange();
break;
}
case EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT: {
@@ -1848,6 +2073,63 @@
}
break;
+ case EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED:
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ loge("EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED: result is null");
+ } else {
+ handleEventTerrestrialNetworkAvailableChanged((boolean) ar.result);
+ }
+ break;
+
+ case EVENT_SET_NETWORK_SELECTION_AUTO_DONE: {
+ logd("EVENT_SET_NETWORK_SELECTION_AUTO_DONE");
+ RequestSatelliteEnabledArgument argument =
+ (RequestSatelliteEnabledArgument) msg.obj;
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, argument, null);
+ break;
+ }
+
+ case EVENT_SIGNAL_STRENGTH_CHANGED: {
+ ar = (AsyncResult) msg.obj;
+ int phoneId = (int) ar.userObj;
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ PhoneFactory.getPhone(phoneId));
+ break;
+ }
+
+ case CMD_UPDATE_SYSTEM_SELECTION_CHANNELS: {
+ plogd("CMD_UPDATE_SYSTEM_SELECTION_CHANNELS");
+ request = (SatelliteControllerHandlerRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request);
+ mSatelliteModemInterface.updateSystemSelectionChannels(
+ ((UpdateSystemSelectionChannelsArgument) (request.argument))
+ .mSystemSelectionSpecifiers,
+ onCompleted);
+ break;
+ }
+
+ case EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (SatelliteControllerHandlerRequest) ar.userObj;
+ int error = SatelliteServiceUtils.getSatelliteError(
+ ar, "updateSystemSelectionChannel");
+ plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = " + error);
+ ((UpdateSystemSelectionChannelsArgument) (request.argument)).mResult.send(error,
+ null);
+ break;
+ }
+
+ case EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED: {
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ loge("EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED: result is null");
+ } else {
+ handleEventSelectedNbIotSatelliteSubscriptionChanged((int) ar.result);
+ }
+ break;
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1962,16 +2244,29 @@
* SATELLITE_RESULT_ERROR error
* 4. ongoing request = enable, current request = disable: send request to modem
*/
+ Boolean isSatelliteEnabled = getIsSatelliteEnabled();
synchronized (mSatelliteEnabledRequestLock) {
- if (!isSatelliteEnabledRequestInProgress()) {
- synchronized (mIsSatelliteEnabledLock) {
- if (mIsSatelliteEnabled != null && mIsSatelliteEnabled == enableSatellite) {
- evaluateToUpdateSatelliteEnabledAttributes(result,
- SatelliteManager.SATELLITE_RESULT_SUCCESS, request,
- mIsDemoModeEnabled, mIsEmergency);
- return;
- }
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (mSatelliteEnabledRequest != null && mNetworkSelectionModeAutoDialog != null
+ && mNetworkSelectionModeAutoDialog.isShowing()
+ && request.isEmergency && request.enableSatellite) {
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(
+ mSatelliteEnabledRequest.callback::accept));
+ mSatelliteEnabledRequest = null;
+ mNetworkSelectionModeAutoDialog.dismiss();
+ mNetworkSelectionModeAutoDialog = null;
}
+ }
+ if (!isSatelliteEnabledRequestInProgress()) {
+ if (isSatelliteEnabled != null && isSatelliteEnabled == enableSatellite) {
+ evaluateToUpdateSatelliteEnabledAttributes(result,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS, request,
+ mIsDemoModeEnabled, mIsEmergency);
+ return;
+ }
+
if (enableSatellite) {
mSatelliteEnabledRequest = request;
} else {
@@ -2025,7 +2320,87 @@
}
}
}
- sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ Phone satellitePhone = getSatellitePhone();
+ if (enableSatellite && satellitePhone != null
+ && satellitePhone.getServiceStateTracker() != null
+ && satellitePhone.getServiceStateTracker().getServiceState()
+ .getIsManualSelection()) {
+ checkNetworkSelectionModeAuto(request);
+ } else {
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ }
+ } else {
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
+ }
+ }
+
+ private void checkNetworkSelectionModeAuto(RequestSatelliteEnabledArgument argument) {
+ plogd("checkNetworkSelectionModeAuto");
+ if (argument.isEmergency) {
+ // ESOS
+ getSatellitePhone().setNetworkSelectionModeAutomatic(null);
+ sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE, argument),
+ DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS);
+ } else {
+ // P2P
+ if (mNetworkSelectionModeAutoDialog != null
+ && mNetworkSelectionModeAutoDialog.isShowing()) {
+ logd("requestSatelliteEnabled: already auto network selection mode popup showing");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ return;
+ }
+ logd("requestSatelliteEnabled: auto network selection mode popup");
+ Configuration configuration = Resources.getSystem().getConfiguration();
+ boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext, nightMode
+ ? AlertDialog.THEME_DEVICE_DEFAULT_DARK
+ : AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);
+
+ String title = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_title);
+ String message = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_message);
+ String ok = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_ok);
+ String cancel = mContext.getResources().getString(
+ R.string.satellite_manual_selection_state_popup_cancel);
+
+ builder.setTitle(title).setMessage(message)
+ .setPositiveButton(ok, (dialog, which) -> {
+ logd("checkNetworkSelectionModeAuto: setPositiveButton");
+ getSatellitePhone().setNetworkSelectionModeAutomatic(null);
+ sendMessageDelayed(obtainMessage(EVENT_SET_NETWORK_SELECTION_AUTO_DONE,
+ argument), DELAY_WAITING_SET_NETWORK_SELECTION_AUTO_MILLIS);
+ })
+ .setNegativeButton(cancel, (dialog, which) -> {
+ logd("checkNetworkSelectionModeAuto: setNegativeButton");
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnabledRequest = null;
+ }
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ })
+ .setOnCancelListener(dialog -> {
+ logd("checkNetworkSelectionModeAuto: setOnCancelListener");
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteEnabledRequest = null;
+ }
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE,
+ FunctionalUtils.ignoreRemoteException(argument.callback::accept));
+ });
+ mNetworkSelectionModeAutoDialog = builder.create();
+ mNetworkSelectionModeAutoDialog.getWindow()
+ .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mNetworkSelectionModeAutoDialog.show();
+ }
}
/**
@@ -2110,17 +2485,17 @@
return;
}
- synchronized (mIsSatelliteEnabledLock) {
- if (mIsSatelliteEnabled != null) {
- /* We have already successfully queried the satellite modem. */
- Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, mIsSatelliteEnabled);
- result.send(SATELLITE_RESULT_SUCCESS, bundle);
- return;
- }
+ Boolean isSatelliteEnabled = getIsSatelliteEnabled();
+ if (isSatelliteEnabled != null) {
+ /* We have already successfully queried the satellite modem. */
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, isSatelliteEnabled);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ return;
}
sendRequestAsync(CMD_IS_SATELLITE_ENABLED, result, null);
+ incrementResultReceiverCount("SC:requestIsSatelliteEnabled");
}
/**
@@ -2151,10 +2526,14 @@
return false;
}
- if (mSatelliteSessionController != null) {
- return mSatelliteSessionController.isInEnablingState();
+ if (mSatelliteSessionController != null
+ && mSatelliteSessionController.isInEnablingState()) {
+ return true;
}
- return false;
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ return (mSatelliteEnabledRequest != null);
+ }
}
/**
@@ -2174,10 +2553,14 @@
* @return {@code true} if the satellite modem is being disabled and {@code false} otherwise.
*/
public boolean isSatelliteBeingDisabled() {
- if (mSatelliteSessionController != null) {
- return mSatelliteSessionController.isInDisablingState();
+ if (mSatelliteSessionController != null
+ && mSatelliteSessionController.isInDisablingState()) {
+ return true;
}
- return false;
+
+ synchronized (mSatelliteEnabledRequestLock) {
+ return (mSatelliteDisabledRequest != null);
+ }
}
/**
@@ -2244,15 +2627,16 @@
result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
return;
}
- synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported != null) {
- /* We have already successfully queried the satellite modem. */
- Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
- bundle.putInt(SATELLITE_SUBSCRIPTION_ID, getSelectedSatelliteSubId());
- result.send(SATELLITE_RESULT_SUCCESS, bundle);
- return;
- }
+
+ int subId = getSelectedSatelliteSubId();
+ Boolean isSatelliteSupported = getIsSatelliteSupported();
+ if (isSatelliteSupported != null) {
+ /* We have already successfully queried the satellite modem. */
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, isSatelliteSupported);
+ bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ return;
}
sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, null);
@@ -2271,14 +2655,13 @@
return;
}
- synchronized (mSatelliteCapabilitiesLock) {
- if (mSatelliteCapabilities != null) {
- Bundle bundle = new Bundle();
- bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
- mSatelliteCapabilities);
- result.send(SATELLITE_RESULT_SUCCESS, bundle);
- return;
- }
+ if (getSatelliteCapabilities() != null) {
+ Bundle bundle = new Bundle();
+ overrideSatelliteCapabilitiesIfApplicable();
+ bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
+ getSatelliteCapabilities());
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ return;
}
sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, null);
@@ -2344,36 +2727,60 @@
@NonNull String token, @NonNull byte[] provisionData,
@NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
- return null;
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ List<SatelliteSubscriberInfo> subscriberInfoList =
+ getNtnOnlySatelliteSubscriberInfoList(result);
+ if (subscriberInfoList == null) {
+ return null;
+ }
+ ResultReceiver internalReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("provisionSatelliteService: resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ result.accept(resultCode);
+ }
+ };
+ provisionSatellite(subscriberInfoList, internalReceiver);
+
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
+ deprovisionSatellite(subscriberInfoList, internalReceiver);
+ mProvisionMetricsStats.setIsCanceled(true);
+ });
+ return cancelTransport;
+ } else {
+ int error = evaluateOemSatelliteRequestAllowed(false);
+ if (error != SATELLITE_RESULT_SUCCESS) {
+ result.accept(error);
+ return null;
+ }
+
+ final int validSubId = getSelectedSatelliteSubId();
+ if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
+ result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS);
+ return null;
+ }
+
+ Boolean satelliteProvisioned = isDeviceProvisioned();
+ if (satelliteProvisioned != null && satelliteProvisioned) {
+ result.accept(SATELLITE_RESULT_SUCCESS);
+ return null;
+ }
+
+ sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
+ new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId),
+ null);
+
+ ICancellationSignal cancelTransport = CancellationSignal.createTransport();
+ CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
+ sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
+ new ProvisionSatelliteServiceArgument(token, provisionData, null,
+ validSubId), null);
+ mProvisionMetricsStats.setIsCanceled(true);
+ });
+ return cancelTransport;
}
-
- final int validSubId = getSelectedSatelliteSubId();
- if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
- result.accept(SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS);
- return null;
- }
-
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
- if (satelliteProvisioned != null && satelliteProvisioned) {
- result.accept(SATELLITE_RESULT_SUCCESS);
- return null;
- }
-
- sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
- new ProvisionSatelliteServiceArgument(token, provisionData, result, validSubId),
- null);
-
- ICancellationSignal cancelTransport = CancellationSignal.createTransport();
- CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
- sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
- new ProvisionSatelliteServiceArgument(token, provisionData, null,
- validSubId), null);
- mProvisionMetricsStats.setIsCanceled(true);
- });
- return cancelTransport;
}
/**
@@ -2389,21 +2796,38 @@
public void deprovisionSatelliteService(
@NonNull String token, @NonNull IIntegerConsumer callback) {
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.accept(error);
- return;
- }
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ List<SatelliteSubscriberInfo> subscriberInfoList =
+ getNtnOnlySatelliteSubscriberInfoList(result);
+ if (subscriberInfoList == null) {
+ return;
+ }
+ ResultReceiver internalReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("deprovisionSatelliteService: resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ result.accept(resultCode);
+ }
+ };
+ deprovisionSatellite(subscriberInfoList, internalReceiver);
+ } else {
+ int error = evaluateOemSatelliteRequestAllowed(false);
+ if (error != SATELLITE_RESULT_SUCCESS) {
+ result.accept(error);
+ return;
+ }
- if (Boolean.FALSE.equals(isSatelliteViaOemProvisioned())) {
- result.accept(SATELLITE_RESULT_SUCCESS);
- return;
- }
+ if (Boolean.FALSE.equals(isDeviceProvisioned())) {
+ result.accept(SATELLITE_RESULT_SUCCESS);
+ return;
+ }
- sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
+ sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
new ProvisionSatelliteServiceArgument(token, null,
result, getSelectedSatelliteSubId()),
null);
+ }
}
/**
@@ -2415,20 +2839,15 @@
*/
@SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
@NonNull ISatelliteProvisionStateCallback callback) {
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- return error;
- }
-
mSatelliteProvisionStateChangedListeners.put(callback.asBinder(), callback);
- boolean isProvisioned = Boolean.TRUE.equals(isSatelliteViaOemProvisioned());
+ boolean isProvisioned = Boolean.TRUE.equals(isDeviceProvisioned());
try {
callback.onSatelliteProvisionStateChanged(isProvisioned);
} catch (RemoteException ex) {
loge("registerForSatelliteProvisionStateChanged: " + ex);
}
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
plogd("registerForSatelliteProvisionStateChanged: report current provisioned "
+ "state, state=" + isProvisioned);
}
@@ -2467,17 +2886,18 @@
return;
}
- synchronized (mSatelliteViaOemProvisionLock) {
- if (mIsSatelliteViaOemProvisioned != null) {
+ synchronized (mDeviceProvisionLock) {
+ if (mIsDeviceProvisioned != null) {
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
- mIsSatelliteViaOemProvisioned);
+ mIsDeviceProvisioned);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
}
sendRequestAsync(CMD_IS_SATELLITE_PROVISIONED, result, null);
+ incrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
}
/**
@@ -2494,8 +2914,9 @@
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("registerForSatelliteModemStateChanged: add RegistrationFailure Listeners");
+ plogd("registerForSatelliteModemStateChanged: add Listeners for ModemState");
mSatelliteRegistrationFailureListeners.put(callback.asBinder(), callback);
+ mTerrestrialNetworkAvailableChangedListeners.put(callback.asBinder(), callback);
}
if (mSatelliteSessionController != null) {
mSatelliteSessionController.registerForSatelliteModemStateChanged(callback);
@@ -2527,8 +2948,9 @@
+ " is not initialized yet");
}
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("unregisterForModemStateChanged: remove RegistrationFailure Listeners");
+ plogd("unregisterForModemStateChanged: remove Listeners for ModemState");
mSatelliteRegistrationFailureListeners.remove(callback.asBinder());
+ mTerrestrialNetworkAvailableChangedListeners.remove(callback.asBinder());
}
}
@@ -2651,6 +3073,7 @@
}
sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, null);
+ incrementResultReceiverCount("SC:requestTimeForNextSatelliteVisibility");
}
/**
@@ -2803,6 +3226,7 @@
Phone phone = SatelliteServiceUtils.getPhone();
sendRequestAsync(CMD_REQUEST_NTN_SIGNAL_STRENGTH, result, phone);
+ incrementResultReceiverCount("SC:requestNtnSignalStrength");
}
/**
@@ -2921,6 +3345,59 @@
}
/**
+ * Registers for selected satellite subscription changed event.
+ *
+ * @param callback The callback to handle the selected satellite subscription changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ */
+ @SatelliteManager.SatelliteResult
+ public int registerForSelectedNbIotSatelliteSubscriptionChanged(
+ @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) {
+ if (DBG) plogd("registerForSelectedNbIotSatelliteSubscriptionChanged()");
+
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("carrierRoamingNbIotNtn flag is disabled");
+ return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+ }
+
+ int error = evaluateOemSatelliteRequestAllowed(false);
+ if (error != SATELLITE_RESULT_SUCCESS) return error;
+
+ mSelectedNbIotSatelliteSubscriptionChangedListeners.put(callback.asBinder(), callback);
+ try {
+ callback.onSelectedNbIotSatelliteSubscriptionChanged(getSelectedSatelliteSubId());
+ } catch (RemoteException ex) {
+ ploge("registerForSelectedNbIotSatelliteSubscriptionChanged: RemoteException ex="
+ + ex);
+ }
+ return SATELLITE_RESULT_SUCCESS;
+ }
+
+ /**
+ * Unregisters for the selected satellite subscription changed event.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param callback The callback that was passed to {@link
+ * #registerForSelectedNbIotSatelliteSubscriptionChanged(
+ * ISelectedNbIotSatelliteSubscriptionCallback)}.
+ */
+ public void unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+ @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) {
+ if (DBG) plogd("unregisterForSelectedNbIotSatelliteSubscriptionChanged()");
+
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ int error = evaluateOemSatelliteRequestAllowed(true);
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ mSelectedNbIotSatelliteSubscriptionChangedListeners.remove(callback.asBinder());
+ }
+ }
+
+ /**
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
@@ -2941,8 +3418,8 @@
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = null;
}
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = Optional.ofNullable(provisioned)
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = Optional.ofNullable(provisioned)
.filter(s -> s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false"))
.map(s -> s.equalsIgnoreCase("true"))
.orElse(null);
@@ -3165,7 +3642,7 @@
ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
return false;
}
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
if (reset) {
mOverriddenIsSatelliteViaOemProvisioned = null;
} else {
@@ -3215,15 +3692,18 @@
plogd("onSatelliteServiceConnected");
// Vendor service might have just come back from a crash
moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_MODEM_ERROR);
+ final String caller = "SC:onSatelliteServiceConnected";
ResultReceiver receiver = new ResultReceiver(this) {
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(caller);
plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
};
requestIsSatelliteSupported(receiver);
+ incrementResultReceiverCount(caller);
} else {
plogd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+ " Ignored the event");
@@ -3349,12 +3829,20 @@
* the satellite network {@code plmn}.
*/
@NonNull
- public List<Integer> getSupportedSatelliteServices(int subId, String plmn) {
+ public List<Integer> getSupportedSatelliteServicesForPlmn(int subId, String plmn) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
synchronized (mSupportedSatelliteServicesLock) {
+ Map<String, List<Integer>> allowedServicesList
+ = mEntitlementServiceTypeMapPerCarrier.get(subId);
+ if (allowedServicesList != null && allowedServicesList.containsKey(plmn)) {
+ List<Integer> allowedServiceValues = allowedServicesList.get(plmn);
+ if (allowedServiceValues != null && !allowedServiceValues.isEmpty()) {
+ return allowedServiceValues;
+ }
+ }
if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
Map<String, Set<Integer>> supportedServices =
mSatelliteServicesSupportedByCarriers.get(subId);
@@ -3399,17 +3887,16 @@
return false;
}
- synchronized (mSatelliteCapabilitiesLock) {
- if (mSatelliteCapabilities == null) {
- ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
- return false;
- }
- if (mSatelliteCapabilities.getSupportedRadioTechnologies().contains(
- SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN)) {
- return true;
- }
+ SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities();
+ if (satelliteCapabilities == null) {
+ ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
return false;
}
+ if (satelliteCapabilities.getSupportedRadioTechnologies().contains(
+ SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN)) {
+ return true;
+ }
+ return false;
}
/**
@@ -3517,6 +4004,11 @@
}
int subId = phone.getSubId();
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ return isInCarrierRoamingNbIotNtn(phone);
+ }
+
if (!isSatelliteSupportedViaCarrier(subId)) {
return false;
}
@@ -3559,12 +4051,9 @@
* esos session.
*/
public boolean shouldTurnOffCarrierSatelliteForEmergencyCall() {
- synchronized (mSatellitePhoneLock) {
- if (mSatellitePhone == null) return false;
- return !mDatagramController.isEmergencyCommunicationEstablished()
- && getConfigForSubId(mSatellitePhone.getSubId()).getBoolean(
- KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
- }
+ return !mDatagramController.isEmergencyCommunicationEstablished()
+ && getConfigForSubId(getSelectedSatelliteSubId()).getBoolean(
+ KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
}
/**
@@ -3582,31 +4071,14 @@
* else {@return false}
*/
public boolean isInCarrierRoamingNbIotNtn() {
- if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
- + "feature flag is disabled");
- return false;
- }
-
- if (!isSatelliteEnabled()) {
- plogd("iisInCarrierRoamingNbIotNtn: satellite is disabled");
- return false;
- }
-
- Phone satellitePhone = getSatellitePhone();
- if (!isCarrierRoamingNtnEligible(satellitePhone)) {
- plogd("isInCarrierRoamingNbIotNtn: not carrier roaming ntn eligible.");
- return false;
- }
- plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible.");
- return true;
+ return isInCarrierRoamingNbIotNtn(getSatellitePhone());
}
/**
* @return {@code true} if phone is in carrier roaming nb iot ntn mode,
* else {@return false}
*/
- public boolean isInCarrierRoamingNbIotNtn(@NonNull Phone phone) {
+ private boolean isInCarrierRoamingNbIotNtn(@Nullable Phone phone) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
+ "feature flag is disabled");
@@ -3618,12 +4090,31 @@
return false;
}
- if (!isCarrierRoamingNtnEligible(phone)) {
- plogd("isInCarrierRoamingNbIotNtn: phone associated with subId "
- + phone.getSubId()
- + " is not carrier roaming ntn eligible.");
+ if (phone == null) {
+ plogd("isInCarrierRoamingNbIotNtn: phone is null");
return false;
}
+
+ int subId = phone.getSubId();
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId()
+ + "]: satellite is not supported via carrier");
+ return false;
+ }
+
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType != CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ plogd("isInCarrierRoamingNbIotNtn[phoneId=" + phone.getPhoneId() + "]: not manual "
+ + "connect. carrierRoamingNtnConnectType = " + carrierRoamingNtnConnectType);
+ return false;
+ }
+
+ if (subId != getSelectedSatelliteSubId()) {
+ plogd("isInCarrierRoamingNbIotNtn: subId=" + subId
+ + " does not match satellite subId=" + getSelectedSatelliteSubId());
+ return false;
+ }
+
plogd("isInCarrierRoamingNbIotNtn: carrier roaming ntn eligible for phone"
+ " associated with subId " + phone.getSubId());
return true;
@@ -3736,10 +4227,18 @@
* @param entitlementEnabled {@code true} Satellite service enabled
* @param allowedPlmnList plmn allowed list to use the satellite service
* @param barredPlmnList plmn barred list to pass the modem
+ * @param plmnDataPlanMap data plan map for the plmn
+ * @param plmnServiceTypeMap available services map for the plmn
+ * @param plmnDataServicePolicyMap data service policy map for the plmn
+ * @param plmnVoiceServicePolicyMap voice service policy map for the plmn
* @param callback callback for accept
*/
public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
@Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList,
+ @Nullable Map<String,Integer> plmnDataPlanMap,
+ @Nullable Map<String,List<Integer>> plmnServiceTypeMap,
+ @Nullable Map<String,Integer> plmnDataServicePolicyMap,
+ @Nullable Map<String,Integer> plmnVoiceServicePolicyMap,
@Nullable IIntegerConsumer callback) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
logd("onSatelliteEntitlementStatusUpdated: carrierEnabledSatelliteFlag is not enabled");
@@ -3760,10 +4259,26 @@
if (barredPlmnList == null) {
barredPlmnList = new ArrayList<>();
}
+ if (plmnDataPlanMap == null) {
+ plmnDataPlanMap = new HashMap<>();
+ }
+ if (plmnServiceTypeMap == null) {
+ plmnServiceTypeMap = new HashMap<>();
+ }
+ if (plmnDataServicePolicyMap == null) {
+ plmnDataServicePolicyMap = new HashMap<>();
+ }
+ if (plmnVoiceServicePolicyMap == null) {
+ plmnVoiceServicePolicyMap = new HashMap<>();
+ }
logd("onSatelliteEntitlementStatusUpdated subId=" + subId + ", entitlementEnabled="
+ entitlementEnabled + ", allowedPlmnList=["
+ String.join(",", allowedPlmnList) + "]" + ", barredPlmnList=["
- + String.join(",", barredPlmnList) + "]");
+ + String.join(",", barredPlmnList) + "]"
+ + ", plmnDataPlanMap =" + plmnDataPlanMap.toString()
+ + ", plmnServiceTypeMap =" + plmnServiceTypeMap.toString()
+ + ", plmnDataServicePolicyMap=" + plmnDataServicePolicyMap.toString()
+ + ", plmnVoiceServicePolicyMap=" + plmnVoiceServicePolicyMap.toString());
synchronized (mSupportedSatelliteServicesLock) {
if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
@@ -3788,6 +4303,10 @@
mMergedPlmnListPerCarrier.remove(subId);
mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList);
+ mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap);
+ mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap);
+ mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap);
+ mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap);
updatePlmnListPerCarrier(subId);
configureSatellitePlmnForCarrier(subId);
mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList);
@@ -3825,12 +4344,12 @@
* we will retry the query one more time. Otherwise, we will return the cached result.
*/
private Boolean isSatelliteSupportedViaOemInternal() {
- synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported != null) {
- /* We have already successfully queried the satellite modem. */
- return mIsSatelliteSupported;
- }
+ Boolean isSatelliteSupported = getIsSatelliteSupported();
+ if (isSatelliteSupported != null) {
+ /* We have already successfully queried the satellite modem. */
+ return isSatelliteSupported;
}
+
/**
* We have not successfully checked whether the modem supports satellite service.
* Thus, we need to retry it now.
@@ -3839,10 +4358,13 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ decrementResultReceiverCount(
+ "SC:isSatelliteSupportedViaOemInternal");
plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
});
+ incrementResultReceiverCount("SC:isSatelliteSupportedViaOemInternal");
return null;
}
@@ -3868,8 +4390,8 @@
if (result == SATELLITE_RESULT_SUCCESS
|| result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
persistOemEnabledSatelliteProvisionStatus(true);
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = true;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = true;
}
callback.accept(SATELLITE_RESULT_SUCCESS);
handleEventSatelliteProvisionStateChanged(true);
@@ -3896,8 +4418,8 @@
if (result == SATELLITE_RESULT_SUCCESS
|| result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
persistOemEnabledSatelliteProvisionStatus(false);
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = false;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = false;
}
if (arg.callback != null) {
arg.callback.accept(SATELLITE_RESULT_SUCCESS);
@@ -3947,21 +4469,21 @@
}
/**
- * Check if satellite is provisioned for a subscription on the device.
- * @return true if satellite is provisioned on the given subscription else return false.
+ * Check if satellite is provisioned for the device.
+ * @return {@code true} if device is provisioned for satellite else return {@code false}.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Nullable
- protected Boolean isSatelliteViaOemProvisioned() {
- synchronized (mSatelliteViaOemProvisionLock) {
+ protected Boolean isDeviceProvisioned() {
+ synchronized (mDeviceProvisionLock) {
if (mOverriddenIsSatelliteViaOemProvisioned != null) {
return mOverriddenIsSatelliteViaOemProvisioned;
}
- if (mIsSatelliteViaOemProvisioned == null) {
- mIsSatelliteViaOemProvisioned = getPersistedOemEnabledSatelliteProvisionStatus();
+ if (mIsDeviceProvisioned == null) {
+ mIsDeviceProvisioned = getPersistedDeviceProvisionStatus();
}
- return mIsSatelliteViaOemProvisioned;
+ return mIsDeviceProvisioned;
}
}
@@ -3969,7 +4491,7 @@
RequestSatelliteEnabledArgument argument =
(RequestSatelliteEnabledArgument) request.argument;
handlePersistentLoggingOnSessionStart(argument);
- selectBindingSatelliteSubscription();
+ selectBindingSatelliteSubscription(argument.enableSatellite);
SatelliteModemEnableRequestAttributes enableRequestAttributes =
createModemEnableRequest(argument);
if (enableRequestAttributes == null) {
@@ -4060,6 +4582,7 @@
registerForNtnSignalStrengthChanged();
registerForCapabilitiesChanged();
registerForSatelliteRegistrationFailure();
+ registerForTerrestrialNetworkAvailableChanged();
requestIsSatelliteProvisioned(
new ResultReceiver(this) {
@@ -4067,6 +4590,7 @@
protected void onReceiveResult(int resultCode, Bundle resultData) {
plogd("updateSatelliteSupportedState.requestIsSatelliteProvisioned: "
+ "resultCode=" + resultCode + ", resultData=" + resultData);
+ decrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
requestSatelliteEnabled(false, false, false,
new IIntegerConsumer.Stub() {
@Override
@@ -4077,17 +4601,22 @@
});
}
});
+ incrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
+
requestSatelliteCapabilities(
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
plogd("updateSatelliteSupportedState.requestSatelliteCapabilities: "
+ "resultCode=" + resultCode + ", resultData=" + resultData);
+ decrementResultReceiverCount("SC:requestSatelliteCapabilities");
}
});
+ incrementResultReceiverCount("SC:requestSatelliteCapabilities");
}
registerForSatelliteSupportedStateChanged();
- selectBindingSatelliteSubscription();
+ selectBindingSatelliteSubscription(false);
+ notifySatelliteSupportedStateChanged(supported);
}
private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -4103,6 +4632,9 @@
if (!enabled) {
mIsModemEnabledReportingNtnSignalStrength.set(false);
}
+ if (mFeatureFlags.satelliteStateChangeListener()) {
+ notifyEnabledStateChanged(enabled);
+ }
}
private void registerForPendingDatagramCount() {
@@ -4175,14 +4707,27 @@
}
}
+ private void registerForTerrestrialNetworkAvailableChanged() {
+ if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+ if (!mRegisteredForTerrestrialNetworkAvailableChanged.get()) {
+ mSatelliteModemInterface.registerForTerrestrialNetworkAvailableChanged(this,
+ EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED, null);
+ mRegisteredForTerrestrialNetworkAvailableChanged.set(true);
+ }
+ }
+ }
+
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
persistOemEnabledSatelliteProvisionStatus(provisioned);
- mIsSatelliteViaOemProvisioned = provisioned;
+ mIsDeviceProvisioned = provisioned;
}
+ notifyDeviceProvisionStateChanged(provisioned);
+ }
+ private void notifyDeviceProvisionStateChanged(boolean provisioned) {
List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
mSatelliteProvisionStateChangedListeners.values().forEach(listener -> {
try {
@@ -4204,14 +4749,31 @@
boolean provisionChanged = false;
synchronized (mSatelliteTokenProvisionedLock) {
for (SatelliteSubscriberInfo subscriberInfo : newList) {
- if (mProvisionedSubscriberId.getOrDefault(subscriberInfo.getSubscriberId(), false)
- == provisioned) {
+
+ int subId = subscriberInfo.getSubId();
+ Boolean currentProvisioned =
+ mProvisionedSubscriberId.get(subscriberInfo.getSubscriberId());
+ if (currentProvisioned == null) {
+ currentProvisioned = false;
+ }
+
+ Boolean isProvisionedInPersistentDb = false;
+ try {
+ isProvisionedInPersistentDb = mSubscriptionManagerService
+ .isSatelliteProvisionedForNonIpDatagram(subId);
+ if (isProvisionedInPersistentDb == null) {
+ isProvisionedInPersistentDb = false;
+ }
+ } catch (IllegalArgumentException | SecurityException ex) {
+ ploge("isSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
+ + ex);
+ }
+ if (currentProvisioned == provisioned
+ && isProvisionedInPersistentDb == provisioned) {
continue;
}
provisionChanged = true;
mProvisionedSubscriberId.put(subscriberInfo.getSubscriberId(), provisioned);
- int subId = mSubscriberIdPerSub.getOrDefault(subscriberInfo.getSubscriberId(),
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
try {
mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
provisioned);
@@ -4231,14 +4793,26 @@
getPrioritizedSatelliteSubscriberProvisionStatusList();
plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
notifySatelliteSubscriptionProvisionStateChanged(informList);
- // Report updated provisioned status
+ updateDeviceProvisionStatus();
+ // Report updated provisioned status to metrics.
synchronized (mSatelliteTokenProvisionedLock) {
boolean isProvisioned = !mProvisionedSubscriberId.isEmpty()
&& mProvisionedSubscriberId.containsValue(Boolean.TRUE);
mControllerMetricsStats.setIsProvisioned(isProvisioned);
}
- selectBindingSatelliteSubscription();
- handleStateChangedForCarrierRoamingNtnEligibility();
+ selectBindingSatelliteSubscription(false);
+ evaluateCarrierRoamingNtnEligibilityChange();
+ }
+
+ private void updateDeviceProvisionStatus() {
+ boolean isProvisioned = getPersistedDeviceProvisionStatus();
+ plogd("updateDeviceProvisionStatus: isProvisioned=" + isProvisioned);
+ synchronized (mDeviceProvisionLock) {
+ if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) {
+ mIsDeviceProvisioned = isProvisioned;
+ notifyDeviceProvisionStateChanged(isProvisioned);
+ }
+ }
}
private void notifySatelliteSubscriptionProvisionStateChanged(
@@ -4260,28 +4834,33 @@
private void handleEventSatelliteModemStateChanged(
@SatelliteManager.SatelliteModemState int state) {
plogd("handleEventSatelliteModemStateChanged: state=" + state);
+
+ synchronized (mSatelliteModemStateLock) {
+ mSatelliteModemState = state;
+ }
+
if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
|| state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
+ if (!isWaitingForDisableSatelliteModemResponse()) {
+ moveSatelliteToOffStateAndCleanUpResources(SATELLITE_RESULT_SUCCESS);
+ } else {
+ notifyModemStateChangedToSessionController(
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ }
+
synchronized (mSatelliteEnabledRequestLock) {
- if (!mWaitingForDisableSatelliteModemResponse) {
- moveSatelliteToOffStateAndCleanUpResources(
- SATELLITE_RESULT_SUCCESS);
- } else {
- notifyModemStateChangedToSessionController(
- SatelliteManager.SATELLITE_MODEM_STATE_OFF);
- }
mWaitingForSatelliteModemOff = false;
}
} else {
if (isSatelliteEnabledOrBeingEnabled() || isSatelliteBeingDisabled()) {
notifyModemStateChangedToSessionController(state);
} else {
- // Telephony framework and modem are out of sync. We need to disable modem
+ // Telephony framework and modem are out of sync. We need to disable
synchronized (mSatelliteEnabledRequestLock) {
plogw("Satellite modem is in a bad state. Disabling satellite modem now ...");
Consumer<Integer> result = integer -> plogd(
"handleEventSatelliteModemStateChanged: disabling satellite result="
- + integer);
+ + integer);
mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(
false /* enableSatellite */, false /* enableDemoMode */,
false /* isEmergency */, result);
@@ -4337,14 +4916,13 @@
synchronized (mSatelliteCapabilitiesLock) {
mSatelliteCapabilities = capabilities;
}
+ overrideSatelliteCapabilitiesIfApplicable();
+ SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities();
List<ISatelliteCapabilitiesCallback> deadCallersList = new ArrayList<>();
mSatelliteCapabilitiesChangedListeners.values().forEach(listener -> {
- synchronized (this.mSatelliteCapabilitiesLock) {
- overrideSatelliteCapabilitiesIfApplicable();
- }
try {
- listener.onSatelliteCapabilitiesChanged(this.mSatelliteCapabilities);
+ listener.onSatelliteCapabilitiesChanged(satelliteCapabilities);
} catch (RemoteException e) {
plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
deadCallersList.add(listener);
@@ -4358,38 +4936,64 @@
private void handleEventSatelliteSupportedStateChanged(boolean supported) {
plogd("handleSatelliteSupportedStateChangedEvent: supported=" + supported);
- synchronized (mIsSatelliteSupportedLock) {
- if (mIsSatelliteSupported != null && mIsSatelliteSupported == supported) {
- if (DBG) {
- plogd("current satellite support state and new supported state are matched,"
- + " ignore update.");
- }
- return;
+ Boolean isSatelliteSupported = getIsSatelliteSupported();
+ if (isSatelliteSupported != null && isSatelliteSupported == supported) {
+ if (DBG) {
+ plogd("current satellite support state and new supported state are matched,"
+ + " ignore update.");
}
-
- updateSatelliteSupportedState(supported);
-
- /* In case satellite has been reported as not support from modem, but satellite is
- enabled, request disable satellite. */
- synchronized (mIsSatelliteEnabledLock) {
- if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) {
- plogd("Invoke requestSatelliteEnabled(), supported=false, "
- + "mIsSatelliteEnabled=true");
- requestSatelliteEnabled(false /* enableSatellite */, false /* enableDemoMode */,
- false /* isEmergency */,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- plogd("handleSatelliteSupportedStateChangedEvent: request "
- + "satellite disable, result=" + result);
- }
- });
-
- }
- }
- mIsSatelliteSupported = supported;
+ return;
}
+ updateSatelliteSupportedState(supported);
+
+ Boolean isSatelliteEnabled = getIsSatelliteEnabled();
+ /* In case satellite has been reported as not support from modem, but satellite is
+ enabled, request disable satellite. */
+ if (!supported && isSatelliteEnabled != null && isSatelliteEnabled) {
+ plogd("Invoke requestSatelliteEnabled(), supported=false, "
+ + "mIsSatelliteEnabled=true");
+ requestSatelliteEnabled(false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleSatelliteSupportedStateChangedEvent: request "
+ + "satellite disable, result=" + result);
+ }
+ });
+
+ }
+
+ synchronized (mIsSatelliteSupportedLock) {
+ mIsSatelliteSupported = supported;
+ }
+ }
+
+ private void handleEventSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleEventSelectedNbIotSatelliteSubscriptionChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ plogd("handleEventSelectedNbIotSatelliteSubscriptionChanged: " + selectedSubId);
+
+ List<ISelectedNbIotSatelliteSubscriptionCallback> deadCallersList = new ArrayList<>();
+ mSelectedNbIotSatelliteSubscriptionChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onSelectedNbIotSatelliteSubscriptionChanged(selectedSubId);
+ } catch (RemoteException e) {
+ logd("handleEventSelectedNbIotSatelliteSubscriptionChanged RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSelectedNbIotSatelliteSubscriptionChangedListeners.remove(listener.asBinder());
+ });
+ }
+
+ private void notifySatelliteSupportedStateChanged(boolean supported) {
List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
mSatelliteSupportedStateChangedListeners.values().forEach(listener -> {
try {
@@ -4567,6 +5171,7 @@
sendRequestAsync(CMD_UPDATE_SATELLITE_ENABLE_ATTRIBUTES,
mSatelliteEnableAttributesUpdateRequest, null);
}
+ updateLastNotifiedNtnModeAndNotify(getSatellitePhone());
}
}
}
@@ -4597,23 +5202,24 @@
public void moveSatelliteToOffStateAndCleanUpResources(
@SatelliteManager.SatelliteResult int resultCode) {
plogd("moveSatelliteToOffStateAndCleanUpResources");
+ setDemoModeEnabled(false);
+ handlePersistentLoggingOnSessionEnd(mIsEmergency);
+ setEmergencyMode(false);
synchronized (mIsSatelliteEnabledLock) {
- setDemoModeEnabled(false);
- handlePersistentLoggingOnSessionEnd(mIsEmergency);
- setEmergencyMode(false);
mIsSatelliteEnabled = false;
- setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
- setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
- abortSatelliteDisableRequest(resultCode);
- abortSatelliteEnableRequest(resultCode);
- abortSatelliteEnableAttributesUpdateRequest(resultCode);
- resetSatelliteEnabledRequest();
- resetSatelliteDisabledRequest();
- // TODO (b/361139260): Stop timer to wait for other radios off
- updateSatelliteEnabledState(
- false, "moveSatelliteToOffStateAndCleanUpResources");
}
- selectBindingSatelliteSubscription();
+ setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
+ setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
+ abortSatelliteDisableRequest(resultCode);
+ abortSatelliteEnableRequest(resultCode);
+ abortSatelliteEnableAttributesUpdateRequest(resultCode);
+ resetSatelliteEnabledRequest();
+ resetSatelliteDisabledRequest();
+ // TODO (b/361139260): Stop timer to wait for other radios off
+ updateSatelliteEnabledState(
+ false, "moveSatelliteToOffStateAndCleanUpResources");
+ selectBindingSatelliteSubscription(false);
+ updateLastNotifiedNtnModeAndNotify(getSatellitePhone());
}
private void setDemoModeEnabled(boolean enabled) {
@@ -4676,6 +5282,7 @@
if (activeSubIds != null) {
for (int subId : activeSubIds) {
updateSupportedSatelliteServices(subId);
+ handleCarrierRoamingNtnAvailableServicesChanged(subId);
}
} else {
loge("updateSupportedSatelliteServicesForActiveSubscriptions: "
@@ -4788,6 +5395,13 @@
KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE));
}
+ @NonNull
+ private Map<String, Set<Integer>> readRegionalSatelliteEarfcnsFromCarrierConfig(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ return SatelliteServiceUtils.parseRegionalSatelliteEarfcns(
+ config.getPersistableBundle(KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE));
+ }
+
@NonNull private PersistableBundle getConfigForSubId(int subId) {
PersistableBundle config = null;
if (mCarrierConfigManager != null) {
@@ -4795,6 +5409,7 @@
config = mCarrierConfigManager.getConfigForSubId(subId,
KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ KEY_SATELLITE_DISPLAY_NAME_STRING,
KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL,
KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
@@ -4809,7 +5424,11 @@
KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
- KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT
+ KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
+ KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT,
+ KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY,
+ KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE,
+ KEY_SATELLITE_DATA_SUPPORT_MODE_INT
);
} catch (Exception e) {
logw("getConfigForSubId: " + e);
@@ -4837,9 +5456,10 @@
updateSupportedSatelliteServicesForActiveSubscriptions();
processNewCarrierConfigData(subId);
resetCarrierRoamingSatelliteModeParams(subId);
- handleStateChangedForCarrierRoamingNtnEligibility();
+ evaluateCarrierRoamingNtnEligibilityChange();
sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
mEvaluateEsosProfilesPrioritizationDurationMillis);
+ updateRegionalSatelliteEarfcns(subId);
}
// imsi, msisdn, default sms subId change
@@ -4927,7 +5547,7 @@
/** If the provision state per subscriberId for the cached is not exist, check the database for
* the corresponding value and use it. */
- private void updateSatelliteProvisionedStatePerSubscriberId() {
+ protected void updateSatelliteProvisionedStatePerSubscriberId() {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
return;
}
@@ -4951,6 +5571,8 @@
}
}
}
+ // Need to update the provision status of the device
+ updateDeviceProvisionStatus();
}
@NonNull
@@ -5003,7 +5625,7 @@
KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
}
- private int getCarrierRoamingNtnConnectType(int subId) {
+ public int getCarrierRoamingNtnConnectType(int subId) {
return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT);
}
@@ -5012,6 +5634,11 @@
KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT);
}
+ @CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE
+ private int getCarrierSatelliteDataSupportedMode(int subId) {
+ return getConfigForSubId(subId).getInt(KEY_SATELLITE_DATA_SUPPORT_MODE_INT);
+ }
+
/**
* Check if satellite attach is enabled by user for the carrier associated with the
* {@code subId}.
@@ -5264,7 +5891,7 @@
}
if (isProvisionRequired) {
- Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
+ Boolean satelliteProvisioned = isDeviceProvisioned();
if (satelliteProvisioned == null) {
plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
@@ -5284,13 +5911,23 @@
*/
@VisibleForTesting
protected @SatelliteManager.NTRadioTechnology int getSupportedNtnRadioTechnology() {
- synchronized (mSatelliteCapabilitiesLock) {
- if (mSatelliteCapabilities != null) {
- return mSatelliteCapabilities.getSupportedRadioTechnologies()
- .stream().findFirst().orElse(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN);
- }
- return SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN;
+ SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities();
+ if (satelliteCapabilities != null) {
+ return satelliteCapabilities.getSupportedRadioTechnologies()
+ .stream().findFirst().orElse(SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN);
}
+ return SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN;
+ }
+
+ /**
+ * Returns a list of messaging apps that support satellite.
+ */
+ @NonNull public List<String> getSatelliteSupportedMsgApps(int subId) {
+ String[] satelliteSupportedMsgApps = getConfigForSubId(subId)
+ .getStringArray(KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY);
+
+ return satelliteSupportedMsgApps != null
+ ? List.of(satelliteSupportedMsgApps) : Collections.emptyList();
}
private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error,
@@ -5314,8 +5951,15 @@
}
}
+ private void registerForSignalStrengthChanged() {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ phone.getSignalStrengthController().registerForSignalStrengthChanged(this,
+ EVENT_SIGNAL_STRENGTH_CHANGED, phone.getPhoneId());
+ }
+ }
+
private void handleEventServiceStateChanged() {
- handleStateChangedForCarrierRoamingNtnEligibility();
+ evaluateCarrierRoamingNtnEligibilityChange();
handleServiceStateForSatelliteConnectionViaCarrier();
}
@@ -5379,6 +6023,7 @@
mWasSatelliteConnectedViaCarrier.put(subId, false);
}
updateLastNotifiedNtnModeAndNotify(phone);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone);
}
}
determineAutoConnectSystemNotification();
@@ -5399,6 +6044,7 @@
if (!initialized) mInitialized.put(subId, true);
mLastNotifiedNtnMode.put(subId, currNtnMode);
phone.notifyCarrierRoamingNtnModeChanged(currNtnMode);
+ updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(phone);
logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode);
if(mIsNotificationShowing && !currNtnMode) {
dismissSatelliteNotification();
@@ -5427,27 +6073,27 @@
}
}
- private void handleStateChangedForCarrierRoamingNtnEligibility() {
+ private void evaluateCarrierRoamingNtnEligibilityChange() {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
+ plogd("evaluateCarrierRoamingNtnEligibilityChange: "
+ "carrierRoamingNbIotNtn flag is disabled");
return;
}
- synchronized (mSatellitePhoneLock) {
- boolean eligible = isCarrierRoamingNtnEligible(mSatellitePhone);
- plogd("handleStateChangedForCarrierRoamingNtnEligibility: "
- + "isCarrierRoamingNtnEligible=" + eligible);
+ boolean eligible = isCarrierRoamingNtnEligible(getSatellitePhone());
+ plogd("evaluateCarrierRoamingNtnEligibilityChange: "
+ + "isCarrierRoamingNtnEligible=" + eligible);
- if (eligible) {
- if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
- startNtnEligibilityHysteresisTimer();
- }
- } else {
- mNtnEligibilityHysteresisTimedOut = false;
- stopNtnEligibilityHysteresisTimer();
- updateLastNotifiedNtnEligibilityAndNotify(false);
+ if (eligible) {
+ if (shouldStartNtnEligibilityHysteresisTimer(eligible)) {
+ startNtnEligibilityHysteresisTimer();
}
+ } else {
+ synchronized (mSatellitePhoneLock) {
+ mNtnEligibilityHysteresisTimedOut = false;
+ }
+ stopNtnEligibilityHysteresisTimer();
+ updateLastNotifiedNtnEligibilityAndNotify(false);
}
}
@@ -5471,20 +6117,22 @@
}
private void startNtnEligibilityHysteresisTimer() {
- synchronized (mSatellitePhoneLock) {
- if (mSatellitePhone == null) {
- ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null.");
- return;
- }
-
- int subId = getSelectedSatelliteSubId();
- long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId);
- mNtnEligibilityHysteresisTimedOut = false;
- plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId
- + ", phoneId=" + mSatellitePhone.getPhoneId() + ", timeout=" + timeout);
- sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT),
- timeout);
+ Phone satellitePhone = getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("startNtnEligibilityHysteresisTimer: mSatellitePhone is null.");
+ return;
}
+
+ int subId = getSelectedSatelliteSubId();
+ long timeout = getCarrierSupportedSatelliteNotificationHysteresisTimeMillis(subId);
+ synchronized (mSatellitePhoneLock) {
+ mNtnEligibilityHysteresisTimedOut = false;
+ }
+ plogd("startNtnEligibilityHysteresisTimer: sendMessageDelayed subId=" + subId
+ + ", phoneId=" + satellitePhone.getPhoneId() + ", timeout=" + timeout);
+ sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT),
+ timeout);
+
}
private void stopNtnEligibilityHysteresisTimer() {
@@ -5499,24 +6147,26 @@
return;
}
- if (mOverrideNtnEligibility != null) {
- mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ Phone satellitePhone = getSatellitePhone();
+ if (satellitePhone == null) {
+ ploge("notifyNtnEligibility: mSatellitePhone is null");
return;
}
- synchronized (mSatellitePhoneLock) {
- if (mSatellitePhone == null) {
- ploge("notifyNtnEligibility: mSatellitePhone is null");
- return;
- }
+ if (mOverrideNtnEligibility != null) {
+ satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ return;
+ }
- plogd("notifyNtnEligibility: phoneId=" + mSatellitePhone.getPhoneId()
+ int selectedSatelliteSubId = getSelectedSatelliteSubId();
+ synchronized (mSatellitePhoneLock) {
+ plogd("notifyNtnEligibility: phoneId=" + satellitePhone.getPhoneId()
+ " currentNtnEligibility=" + currentNtnEligibility);
if (mLastNotifiedNtnEligibility == null
|| mLastNotifiedNtnEligibility != currentNtnEligibility) {
mLastNotifiedNtnEligibility = currentNtnEligibility;
- mSatellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
- updateSatelliteSystemNotification(getSelectedSatelliteSubId(),
+ satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
+ updateSatelliteSystemNotification(selectedSatelliteSubId,
CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL,
currentNtnEligibility);
}
@@ -5536,10 +6186,10 @@
}
private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
- synchronized (mSatelliteViaOemProvisionLock) {
+ synchronized (mDeviceProvisionLock) {
plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ int subId = getNtnOnlySubscriptionId();
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
try {
mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
@@ -5566,24 +6216,34 @@
}
@Nullable
- private Boolean getPersistedOemEnabledSatelliteProvisionStatus() {
- plogd("getPersistedOemEnabledSatelliteProvisionStatus:");
- synchronized (mSatelliteViaOemProvisionLock) {
+ private boolean getPersistedDeviceProvisionStatus() {
+ plogd("getPersistedDeviceProvisionStatus");
+ synchronized (mDeviceProvisionLock) {
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- int subId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
+ int subId = getNtnOnlySubscriptionId();
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- return mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
- subId);
- } else {
- plogd("getPersistedOemEnabledSatelliteProvisionStatus: "
- + "subId=INVALID_SUBSCRIPTION_ID, return null");
- return null;
+ if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(subId)) {
+ return true;
+ }
}
+
+ List<SubscriptionInfo> activeSubscriptionInfoList =
+ mSubscriptionManagerService.getActiveSubscriptionInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag(), true);
+ for (SubscriptionInfo info : activeSubscriptionInfoList) {
+ if (info.isSatelliteESOSSupported()) {
+ if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
+ info.getSubscriptionId())) {
+ return true;
+ }
+ }
+ }
+ return false;
} else {
if (!loadSatelliteSharedPreferences()) return false;
if (mSharedPreferences == null) {
- ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is "
+ ploge("getPersistedDeviceProvisionStatus: mSharedPreferences is "
+ "null");
return false;
} else {
@@ -5615,8 +6275,9 @@
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
- Boolean.TRUE.equals(isSatelliteViaOemProvisioned()));
+ Boolean.TRUE.equals(isDeviceProvisioned()));
((ResultReceiver) request.argument).send(SATELLITE_RESULT_SUCCESS, bundle);
+ decrementResultReceiverCount("SC:requestIsSatelliteProvisioned");
}
private long getWaitForSatelliteEnablingResponseTimeoutMillis() {
@@ -5733,50 +6394,51 @@
+ argument.requestId + ", enableSatellite=" + argument.enableSatellite);
argument.callback.accept(SATELLITE_RESULT_MODEM_TIMEOUT);
- synchronized (mIsSatelliteEnabledLock) {
- if (argument.enableSatellite) {
- resetSatelliteEnabledRequest();
- abortSatelliteEnableAttributesUpdateRequest(SATELLITE_RESULT_REQUEST_ABORTED);
- synchronized (mSatelliteEnabledRequestLock) {
- if (mSatelliteDisabledRequest == null) {
- IIntegerConsumer callback = new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
- + "disable satellite result=" + result);
- }
- };
- Consumer<Integer> result =
- FunctionalUtils.ignoreRemoteException(callback::accept);
- mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(
- false, false, false, result);
- sendRequestAsync(CMD_SET_SATELLITE_ENABLED, mSatelliteDisabledRequest,
- null);
+ if (argument.enableSatellite) {
+ resetSatelliteEnabledRequest();
+ abortSatelliteEnableAttributesUpdateRequest(SATELLITE_RESULT_REQUEST_ABORTED);
+ if (getSatelliteDisabledRequest() == null) {
+ IIntegerConsumer callback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
+ + "disable satellite result=" + result);
}
+ };
+ Consumer<Integer> result =
+ FunctionalUtils.ignoreRemoteException(callback::accept);
+
+ RequestSatelliteEnabledArgument request;
+ synchronized (mSatelliteEnabledRequestLock) {
+ mSatelliteDisabledRequest = new RequestSatelliteEnabledArgument(
+ false, false, false, result);
+ request = mSatelliteDisabledRequest;
}
- mControllerMetricsStats.reportServiceEnablementFailCount();
- mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
- .setSatelliteTechnology(getSupportedNtnRadioTechnology())
- .setInitializationProcessingTime(
- System.currentTimeMillis() - mSessionProcessingTimeStamp)
- .setIsDemoMode(mIsDemoModeEnabled)
- .setCarrierId(getSatelliteCarrierId())
- .reportSessionMetrics();
- } else {
- resetSatelliteDisabledRequest();
- mControllerMetricsStats.onSatelliteDisabled();
- mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
- .setSatelliteTechnology(getSupportedNtnRadioTechnology())
- .setTerminationProcessingTime(
- System.currentTimeMillis() - mSessionProcessingTimeStamp)
- .setSessionDurationSec(calculateSessionDurationTimeSec())
- .reportSessionMetrics();
+ sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
}
- notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite);
- mSessionStartTimeStamp = 0;
- mSessionProcessingTimeStamp = 0;
+
+ mControllerMetricsStats.reportServiceEnablementFailCount();
+ mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setInitializationProcessingTime(
+ System.currentTimeMillis() - mSessionProcessingTimeStamp)
+ .setIsDemoMode(mIsDemoModeEnabled)
+ .setCarrierId(getSatelliteCarrierId())
+ .reportSessionMetrics();
+ } else {
+ resetSatelliteDisabledRequest();
+ mControllerMetricsStats.onSatelliteDisabled();
+ mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setTerminationProcessingTime(
+ System.currentTimeMillis() - mSessionProcessingTimeStamp)
+ .setSessionDurationSec(calculateSessionDurationTimeSec())
+ .reportSessionMetrics();
}
+ notifyEnablementFailedToSatelliteSessionController(argument.enableSatellite);
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
}
private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) {
@@ -5881,6 +6543,23 @@
updateSatelliteSystemNotification(-1, -1,/*visible*/ false);
}
+ public boolean isSatelliteSystemNotificationsEnabled(int carrierRoamingNtnConnectType) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return false;
+ }
+ if (carrierRoamingNtnConnectType
+ != CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ return true;
+ }
+ boolean notifySatelliteAvailabilityEnabled =
+ mContext.getResources().getBoolean(R.bool.config_satellite_should_notify_availability);
+ Boolean isSatelliteSupported = getIsSatelliteSupported();
+ if(isSatelliteSupported == null) {
+ return false;
+ }
+ return notifySatelliteAvailabilityEnabled && isSatelliteSupported;
+ }
+
/**
* 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
@@ -5894,6 +6573,11 @@
*/
private void updateSatelliteSystemNotification(int subId,
@CARRIER_ROAMING_NTN_CONNECT_TYPE int carrierRoamingNtnConnectType, boolean visible) {
+ if (!isSatelliteSystemNotificationsEnabled(carrierRoamingNtnConnectType)) {
+ plogd("updateSatelliteSystemNotification: satellite notifications are not enabled.");
+ return;
+ }
+
plogd("updateSatelliteSystemNotification subId=" + subId + ", carrierRoamingNtnConnectType="
+ SatelliteServiceUtils.carrierRoamingNtnConnectTypeToString(
carrierRoamingNtnConnectType) + ", visible=" + visible);
@@ -6259,6 +6943,13 @@
}
}
+ private void plogv(@NonNull String log) {
+ Rlog.v(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) {
if (mPersistentLogger == null) {
return;
@@ -6353,6 +7044,14 @@
if (!isNtnOnly && !isESOSSupported) {
continue;
}
+ if (!isActive && !isNtnOnly) {
+ continue;
+ }
+ if (!isNtnOnly && !isCarrierConfigLoaded(subId)) {
+ // Skip to add priority list if the carrier config is not loaded properly
+ // for the given carrier subscription.
+ continue;
+ }
int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
: (isESOSSupported && isActive) ? 1
@@ -6378,6 +7077,9 @@
logd("Old phone number is removed: id = " + subId);
isChanged = true;
}
+ if (!newSubscriberId.isEmpty()) {
+ mSubscriberIdPerSub.put(newSubscriberId, subId);
+ }
}
}
plogd("evaluateESOSProfilesPrioritization: newSubsInfoListPerPriority.size()="
@@ -6390,28 +7092,45 @@
// If priority has changed, send broadcast for provisioned ESOS subs IDs
synchronized (mSatelliteTokenProvisionedLock) {
+ List<SatelliteSubscriberProvisionStatus> newEvaluatedSubscriberProvisionStatus =
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ newSubsInfoListPerPriority);
if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority)
+ || isSubscriberContentChanged(mLastEvaluatedSubscriberProvisionStatus,
+ newEvaluatedSubscriberProvisionStatus)
|| isChanged) {
mSubsInfoListPerPriority = newSubsInfoListPerPriority;
+ mLastEvaluatedSubscriberProvisionStatus = newEvaluatedSubscriberProvisionStatus;
sendBroadCastForProvisionedESOSSubs();
mHasSentBroadcast = true;
- selectBindingSatelliteSubscription();
+ selectBindingSatelliteSubscription(false);
}
}
}
+ // to check if the contents of carrier config is loaded properly
+ private Boolean isCarrierConfigLoaded(int subId) {
+ PersistableBundle carrierConfig = mCarrierConfigManager
+ .getConfigForSubId(subId, KEY_CARRIER_CONFIG_APPLIED_BOOL);
+ return carrierConfig != null ? carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL) : false;
+ }
+
// The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
// subscriberId is the Imsi prefix 6 digit + phone number.
- private Pair<String, Integer> getSubscriberIdAndType(SubscriptionInfo info) {
+ private Pair<String, Integer> getSubscriberIdAndType(@Nullable SubscriptionInfo info) {
String subscriberId = "";
@SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
SatelliteSubscriberInfo.ICCID;
- if (info.isSatelliteESOSSupported()) {
- subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
- subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
+ if (info == null) {
+ logd("getSubscriberIdAndType: subscription info is null");
+ return new Pair<>(subscriberId, subscriberIdType);
}
if (info.isOnlyNonTerrestrialNetwork()) {
subscriberId = info.getIccId();
+ } else if (info.isSatelliteESOSSupported()) {
+ subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
}
logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
+ subscriberIdType);
@@ -6459,6 +7178,24 @@
return false;
}
+ // Checks if there are any changes between subscriberInfos. return false if the same.
+ // Note that, Use lists with the same priority so we can compare contents properly.
+ private boolean isSubscriberContentChanged(List<SatelliteSubscriberProvisionStatus> currentList,
+ List<SatelliteSubscriberProvisionStatus> newList) {
+ if (currentList.size() != newList.size()) {
+ return true;
+ }
+ for (int i = 0; i < currentList.size(); i++) {
+ SatelliteSubscriberProvisionStatus curSub = currentList.get(i);
+ SatelliteSubscriberProvisionStatus newSub = newList.get(i);
+ if (!curSub.getSatelliteSubscriberInfo().equals(newSub.getSatelliteSubscriberInfo())) {
+ logd("isSubscriberContentChanged: cur=" + curSub + " , new=" + newSub);
+ return true;
+ }
+ }
+ return false;
+ }
+
private void sendBroadCastForProvisionedESOSSubs() {
String packageName = getConfigSatelliteGatewayServicePackage();
String className = getConfigSatelliteCarrierRoamingEsosProvisionedClass();
@@ -6492,6 +7229,29 @@
}
/**
+ * Request to get the name to display for Satellite.
+ *
+ * @param result The result receiver that returns the name to display for the satellite
+ * or an error code if the request failed.
+ */
+ public void requestSatelliteDisplayName(@NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("requestSatelliteDisplayName: carrierRoamingNbIotNtn flag is disabled");
+ result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
+ return;
+ }
+
+ int subId = getSelectedSatelliteSubId();
+ String displayName = getConfigForSubId(subId).getString(
+ KEY_SATELLITE_DISPLAY_NAME_STRING, "Satellite");
+
+ plogd("requestSatelliteDisplayName: " + displayName);
+ Bundle bundle = new Bundle();
+ bundle.putString(SatelliteManager.KEY_SATELLITE_DISPLAY_NAME, displayName);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+
+ /**
* Request to get list of prioritized satellite tokens to be used for provision.
*
* @param result The result receiver, which returns the list of prioritized satellite tokens
@@ -6512,10 +7272,18 @@
private List<SatelliteSubscriberProvisionStatus>
getPrioritizedSatelliteSubscriberProvisionStatusList() {
+ synchronized (mSatelliteTokenProvisionedLock) {
+ return getPrioritizedSatelliteSubscriberProvisionStatusList(mSubsInfoListPerPriority);
+ }
+ }
+
+ private List<SatelliteSubscriberProvisionStatus>
+ getPrioritizedSatelliteSubscriberProvisionStatusList(
+ Map<Integer, List<SubscriptionInfo>> subsInfoListPerPriority) {
List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
synchronized (mSatelliteTokenProvisionedLock) {
- for (int priority : mSubsInfoListPerPriority.keySet()) {
- List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
+ for (int priority : subsInfoListPerPriority.keySet()) {
+ List<SubscriptionInfo> infoList = subsInfoListPerPriority.get(priority);
if (infoList == null) {
logd("getPrioritySatelliteSubscriberProvisionStatusList: no exist this "
+ "priority " + priority);
@@ -6547,7 +7315,7 @@
+ ", provisioned=" + provisioned);
list.add(new SatelliteSubscriberProvisionStatus.Builder()
.setSatelliteSubscriberInfo(satelliteSubscriberInfo)
- .setProvisionStatus(provisioned).build());
+ .setProvisioned(provisioned).build());
mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId());
}
}
@@ -6561,8 +7329,36 @@
}
}
- private void selectBindingSatelliteSubscription() {
- if (isSatelliteEnabled() || isSatelliteBeingEnabled()) {
+ /**
+ * Request to get the currently selected satellite subscription id.
+ *
+ * @param result The result receiver that returns the currently selected satellite subscription
+ * id if the request is successful or an error code if the request failed.
+ */
+ public void requestSelectedNbIotSatelliteSubscriptionId(@NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ logd("requestSelectedNbIotSatelliteSubscriptionId: carrierRoamingNbIotNtn is disabled");
+ return;
+ }
+
+ int selectedSatelliteSubId = getSelectedSatelliteSubId();
+ plogd("requestSelectedNbIotSatelliteSubscriptionId: " + selectedSatelliteSubId);
+ if (selectedSatelliteSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ result.send(SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION, null);
+ logd("requestSelectedNbIotSatelliteSubscriptionId: "
+ + "selectedSatelliteSubId is invalid");
+ return;
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(SatelliteManager.KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID,
+ selectedSatelliteSubId);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+
+ private void selectBindingSatelliteSubscription(boolean shouldIgnoreEnabledState) {
+ if ((isSatelliteEnabled() || isSatelliteBeingEnabled()) && !shouldIgnoreEnabledState) {
plogd("selectBindingSatelliteSubscription: satellite subscription will be selected "
+ "once the satellite session ends");
return;
@@ -6575,22 +7371,23 @@
// TODO: need to check if satellite is allowed at current location for the subscription
int subId = getSubIdFromSubscriberId(
status.getSatelliteSubscriberInfo().getSubscriberId());
- if (status.getProvisionStatus() && isActiveSubId(subId)) {
+ if (status.isProvisioned() && isActiveSubId(subId)) {
selectedSubId = subId;
break;
}
}
- synchronized (mSatelliteTokenProvisionedLock) {
- if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
- && isSatelliteSupportedViaOem()) {
- selectedSubId = SatelliteServiceUtils.getNtnOnlySubscriptionId(mContext);
- }
- mSelectedSatelliteSubId = selectedSubId;
- setSatellitePhone(selectedSubId);
+ if (selectedSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ && isSatelliteSupportedViaOem()) {
+ selectedSubId = getNtnOnlySubscriptionId();
}
- plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId="
- + mSelectedSatelliteSubId);
+
+ synchronized (mSatelliteTokenProvisionedLock) {
+ mSelectedSatelliteSubId = selectedSubId;
+ }
+ setSatellitePhone(selectedSubId);
+ plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId=" + selectedSubId);
+ handleEventSelectedNbIotSatelliteSubscriptionChanged(selectedSubId);
}
private int getSubIdFromSubscriberId(String subscriberId) {
@@ -6601,7 +7398,12 @@
}
private boolean isActiveSubId(int subId) {
- return mSubscriptionManagerService.getSubscriptionInfo(subId).isActive();
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+ if (subInfo == null) {
+ logd("isActiveSubId: subscription associated with subId=" + subId + " not found");
+ return false;
+ }
+ return subInfo.isActive();
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -6647,6 +7449,65 @@
RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
result, true);
sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ incrementResultReceiverCount("SC:provisionSatellite");
+ }
+
+ /**
+ * Request to update system selection channels.
+ *
+ * @param result The result receiver that returns if the request is successful or
+ * an error code if the request failed.
+ */
+ public void updateSystemSelectionChannels(
+ @NonNull List<SystemSelectionSpecifier> selectionSpecifiers,
+ @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("updateSystemSelectionChannels: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ return;
+ }
+
+ sendRequestAsync(CMD_UPDATE_SYSTEM_SELECTION_CHANNELS,
+ new UpdateSystemSelectionChannelsArgument(selectionSpecifiers, result), null);
+ }
+
+ /**
+ * @param subId Subscription ID.
+ * @return The The map of earfcns with key: regional satellite config Id,
+ * value: set of earfcns in the corresponding regions associated with the {@code subId}.
+ */
+ @NonNull
+ public Map<String, Set<Integer>> getRegionalSatelliteEarfcns(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ logd("getRegionalSatelliteEarfcns: carrierRoamingNbIotNtnFlag is disabled");
+ return new HashMap<>();
+ }
+ synchronized (mRegionalSatelliteEarfcnsLock) {
+ if (mRegionalSatelliteEarfcns.containsKey(subId)) {
+ return mRegionalSatelliteEarfcns.get(subId);
+ } else {
+ logd("getRegionalSatelliteEarfcns: Earfcns for subId: " + subId + " not found");
+ return new HashMap<>();
+ }
+ }
+ }
+
+ /**
+ * Update regional satellite earfcn information from carrier config.
+ */
+ public void updateRegionalSatelliteEarfcns(int subId) {
+ plogd("updateRegionalSatelliteEarfcns with subId " + subId);
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("updateRegionalSatelliteEarfcns: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ synchronized (mRegionalSatelliteEarfcnsLock) {
+ mRegionalSatelliteEarfcns.put(subId,
+ readRegionalSatelliteEarfcnsFromCarrierConfig(subId));
+ }
}
/**
@@ -6672,6 +7533,62 @@
RequestProvisionSatelliteArgument request = new RequestProvisionSatelliteArgument(list,
result, false);
sendRequestAsync(CMD_UPDATE_PROVISION_SATELLITE_TOKEN, request, null);
+ incrementResultReceiverCount("SC:provisionSatellite");
+ }
+
+ /**
+ * Inform whether application supports NTN SMS in satellite mode.
+ *
+ * This method is used by default messaging application to inform framework whether it supports
+ * NTN SMS or not.
+ *
+ * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}.
+ */
+ public void setNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ return;
+ }
+ persistNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+ handleCarrierRoamingNtnAvailableServicesChanged(getSelectedSatelliteSubId());
+ }
+
+ private void persistNtnSmsSupportedByMessagesApp(boolean ntnSmsSupported) {
+ plogd("persistNtnSmsSupportedByMessagesApp: ntnSmsSupported=" + ntnSmsSupported);
+ if (!loadSatelliteSharedPreferences()) return;
+
+ if (mSharedPreferences == null) {
+ ploge("persistNtnSmsSupportedByMessagesApp: mSharedPreferences is null");
+ } else {
+ mSharedPreferences.edit().putBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, ntnSmsSupported).apply();
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = ntnSmsSupported;
+ }
+ }
+ }
+
+ private boolean isNtnSmsSupportedByMessagesApp() {
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ if (mNtnSmsSupportedByMessagesApp != null) {
+ plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp);
+ return mNtnSmsSupportedByMessagesApp;
+ }
+ }
+
+ if (!loadSatelliteSharedPreferences()) return false;
+
+ if (mSharedPreferences == null) {
+ ploge("isNtnSmsSupportedByMessagesApp: mSharedPreferences is null");
+ return false;
+ } else {
+ boolean ntnSmsSupported = mSharedPreferences.getBoolean(
+ NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+ synchronized (mNtnSmsSupportedByMessagesAppLock) {
+ mNtnSmsSupportedByMessagesApp = ntnSmsSupported;
+ plogd("isNtnSmsSupportedByMessagesApp:" + mNtnSmsSupportedByMessagesApp);
+ }
+ return ntnSmsSupported;
+ }
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -6681,7 +7598,8 @@
if (mSatellitePhone == null) {
mSatellitePhone = SatelliteServiceUtils.getPhone();
}
- plogd("mSatellitePhone:" + (mSatellitePhone != null) + ", subId=" + subId);
+ plogd("mSatellitePhone: phoneId=" + (mSatellitePhone != null
+ ? mSatellitePhone.getPhoneId() : "null") + ", subId=" + subId);
int carrierId = mSatellitePhone.getCarrierId();
if (carrierId != UNKNOWN_CARRIER_ID) {
mControllerMetricsStats.setCarrierId(carrierId);
@@ -6726,6 +7644,11 @@
return false;
}
+ if (!mIsRadioOn) {
+ plogd("isCarrierRoamingNtnEligible: radio is off");
+ return false;
+ }
+
if (phone == null) {
plogd("isCarrierRoamingNtnEligible: phone is null");
return false;
@@ -6749,8 +7672,9 @@
return false;
}
- if (!isSatelliteServiceSupportedByCarrier(subId,
- NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
+
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+ if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
plogd("isCarrierRoamingNtnEligible[phoneId=" + phone.getPhoneId()
+ "]: SMS is not supported by carrier");
return false;
@@ -6785,11 +7709,19 @@
return true;
}
- private boolean isSatelliteServiceSupportedByCarrier(int subId,
+
+ /**
+ * Checks if the satellite service is supported by the carrier for the specified
+ * subscription ID and servicetype.
+ *
+ * @param subId The subscription id.
+ * @param serviceType The type of service to check
+ */
+ public boolean isSatelliteServiceSupportedByCarrier(int subId,
@NetworkRegistrationInfo.ServiceType int serviceType) {
List<String> satellitePlmnList = getSatellitePlmnsForCarrier(subId);
for (String satellitePlmn : satellitePlmnList) {
- if (getSupportedSatelliteServices(subId, satellitePlmn).contains(serviceType)) {
+ if (getSupportedSatelliteServicesForPlmn(subId, satellitePlmn).contains(serviceType)) {
return true;
}
}
@@ -6892,6 +7824,42 @@
});
}
+ private void handleEventTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleEventTerrestrialNetworkAvailableChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+
+ plogd("handleEventTerrestrialNetworkAvailableChanged: " + isAvailable);
+
+ List<ISatelliteModemStateCallback> deadCallersList = new ArrayList<>();
+ mTerrestrialNetworkAvailableChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onTerrestrialNetworkAvailableChanged(isAvailable);
+ } catch (RemoteException e) {
+ logd("handleEventTerrestrialNetworkAvailableChanged RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mTerrestrialNetworkAvailableChangedListeners.remove(listener.asBinder());
+ });
+
+ if (isAvailable && !mIsEmergency) {
+ requestSatelliteEnabled(
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleEventTerrestrialNetworkAvailableChanged:"
+ + " requestSatelliteEnabled result=" + result);
+ }
+ });
+ }
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value :
@@ -6941,7 +7909,8 @@
return result;
}
- private String getConfigSatelliteGatewayServicePackage() {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected String getConfigSatelliteGatewayServicePackage() {
if (!mChangeIntentComponent) {
return getStringFromOverlayConfig(
R.string.config_satellite_gateway_service_package);
@@ -7012,8 +7981,10 @@
} else {
mOverrideNtnEligibility.set(state);
}
- if (this.mSatellitePhone != null) {
- updateLastNotifiedNtnEligibilityAndNotify(state);
+ synchronized (mSatellitePhoneLock) {
+ if (this.mSatellitePhone != null) {
+ updateLastNotifiedNtnEligibilityAndNotify(state);
+ }
}
}
return true;
@@ -7025,19 +7996,471 @@
* uses the value in the existed mSatelliteCapabilities.
*/
private void overrideSatelliteCapabilitiesIfApplicable() {
- synchronized (this.mSatellitePhoneLock) {
- if (this.mSatellitePhone == null) {
- return;
- }
- }
int subId = getSelectedSatelliteSubId();
PersistableBundle config = getPersistableBundle(subId);
- if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE)) {
- int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE);
+ if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT)) {
+ int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT);
SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
if (!(subInfo == null || subInfo.isOnlyNonTerrestrialNetwork())) {
- this.mSatelliteCapabilities.setMaxBytesPerOutgoingDatagram(datagramSize);
+ synchronized (mSatelliteCapabilitiesLock) {
+ this.mSatelliteCapabilities.setMaxBytesPerOutgoingDatagram(datagramSize);
+ }
}
}
}
+
+ /**
+ * This method returns subscription id for supporting Ntn Only
+ */
+ public int getNtnOnlySubscriptionId() {
+ List<SubscriptionInfo> infoList = mSubscriptionManagerService.getAllSubInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ int subId = infoList.stream()
+ .filter(info -> info.isOnlyNonTerrestrialNetwork())
+ .mapToInt(SubscriptionInfo::getSubscriptionId)
+ .findFirst()
+ .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ logd("getNtnOnlySubscriptionId: subId=" + subId);
+ return subId;
+ }
+
+ @Nullable
+ private List<SatelliteSubscriberInfo> getNtnOnlySatelliteSubscriberInfoList(
+ Consumer<Integer> result) {
+ SatelliteSubscriberInfo satelliteSubscriberInfo = getNtnOnlySatelliteSubscriberInfo();
+ if (satelliteSubscriberInfo == null) {
+ result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+ return null;
+ }
+ List<SatelliteSubscriberInfo> satelliteSubscriberInfoList = new ArrayList<>();
+ satelliteSubscriberInfoList.add(satelliteSubscriberInfo);
+
+ return satelliteSubscriberInfoList;
+ }
+
+ @Nullable private SatelliteSubscriberInfo getNtnOnlySatelliteSubscriberInfo() {
+ int ntnOnlySubId = getNtnOnlySubscriptionId();
+ if (ntnOnlySubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ logw("getNtnOnlySatelliteSubscriberInfo: no ntn only subscription found");
+ return null;
+ }
+ SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(ntnOnlySubId);
+ if (subInfo == null) {
+ logw("getNtnOnlySatelliteSubscriberInfo: no subscription info found for subId="
+ + ntnOnlySubId);
+ return null;
+ }
+ return getSatelliteSubscriberInfo(subInfo);
+ }
+
+ @Nullable private SatelliteSubscriberInfo getSatelliteSubscriberInfo(
+ @NonNull SubscriptionInfo subInfo) {
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(subInfo);
+ String subscriberId = subscriberIdPair.first;
+ int carrierId = subInfo.getCarrierId();
+ String apn = getConfigForSubId(subInfo.getSubscriptionId())
+ .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+ logd("getSatelliteSubscriberInfo: subInfo: " + subInfo + ", subscriberId:"
+ + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
+ if (subscriberId.isEmpty()) {
+ logw("getSatelliteSubscriberInfo: not a satellite subscription.");
+ return null;
+ }
+ return new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
+ .setCarrierId(carrierId).setNiddApn(apn)
+ .setSubId(subInfo.getSubscriptionId())
+ .setSubscriberIdType(subscriberIdPair.second)
+ .build();
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("handleCarrierRoamingNtnAvailableServicesChanged: "
+ + "carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ updateLastNotifiedNtnAvailableServicesAndNotify(subId);
+ evaluateCarrierRoamingNtnEligibilityChange();
+ }
+
+ private void updateLastNotifiedNtnAvailableServicesAndNotify(int subId) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("notifyNtnAvailableServices: carrierRoamingNbIotNtn flag is disabled");
+ return;
+ }
+ Phone phone = SatelliteServiceUtils.getPhone(subId);
+ if (phone == null) {
+ plogd("notifyNtnAvailableServices: phone is null.");
+ return;
+ }
+ plogd("updateLastNotifiedNtnAvailableServicesAndNotify: phoneId= " + phone.getPhoneId());
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+ phone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
+ }
+
+ /** Return services that are supported on carrier roaming non-terrestrial network. */
+ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+ if (isSatelliteSupportedViaCarrier(subId)) {
+ // TODO: b/377367448 Cleanup get supported satellite services to align with starlink.
+ int[] services = getSupportedSatelliteServicesForCarrier(subId);
+ if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) {
+ services = Arrays.stream(services).filter(
+ value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray();
+ }
+ return services;
+ }
+ return new int[0];
+ }
+
+ /**
+ * Whether the P2P SMS over carrier roaming satellite is disallowed or not.
+ *
+ * @param subId Associated subscription ID
+ * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite
+ * {@code false} otherwise
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(int subId) {
+ int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
+ if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
+ // Manual Connected
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: manual connect");
+ if (!isNtnSmsSupportedByMessagesApp()
+ || !isApplicationSupportsP2P(mSatelliteGatewayServicePackageName)) {
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: APKs do not supports P2P");
+ return true;
+ }
+ }
+ plogd("isP2PSmsDisallowedOnCarrierRoamingNtn: P2P is supported");
+ return false;
+ }
+
+ @NonNull
+ private int[] getSupportedSatelliteServicesForCarrier(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ int[] availableServices = config.getIntArray(
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
+ if (availableServices == null) {
+ logd("getSupportedSatelliteServicesForCarrier: defaultCapabilities is null");
+ return new int[0];
+ }
+ logd("getSupportedSatelliteServicesForCarrier: subId=" + subId
+ + ", return default values " + Arrays.toString(availableServices));
+ return availableServices;
+ }
+
+ /**
+ * Whether application supports the P2P SMS to connect to carrier roaming non-terrestrial
+ * network.
+ *
+ * @param packageName application's default package name
+ * return {@code true} when the application supports P2P SMS over the roaming satellite
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isApplicationSupportsP2P(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ try {
+ applicationInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " is not installed.");
+ return false;
+ }
+ if (applicationInfo == null || applicationInfo.metaData == null) {
+ logd("isApplicationSupportsP2P pkgName: " + packageName + " meta-data info is empty.");
+ return false;
+ }
+ return applicationInfo.metaData.getBoolean(
+ SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT);
+ }
+
+ /**
+ * Registers for the applications state changed.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void registerApplicationStateChanged() {
+ mDefaultSmsPackageName = Telephony.Sms.getDefaultSmsPackage(mContext);
+ mSatelliteGatewayServicePackageName = getConfigSatelliteGatewayServicePackage();
+
+ IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(Telephony.Sms.Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageFilter.addDataScheme("package");
+ mContext.registerReceiver(mPackageStateChangedReceiver, packageFilter,
+ mContext.RECEIVER_EXPORTED);
+ }
+
+
+ private void notifyEnabledStateChanged(boolean isEnabled) {
+ TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
+ if (trm == null) {
+ loge("Telephony registry service is down!");
+ return;
+ }
+
+ trm.notifySatelliteStateChanged(isEnabled);
+ logd("notifyEnabledStateChanged to " + isEnabled);
+ }
+
+ private NtnSignalStrength getCarrierRoamingNtnSignalStrength(@NonNull Phone phone) {
+ NtnSignalStrength carrierRoamingNtnSignalStrength = new NtnSignalStrength(
+ NTN_SIGNAL_STRENGTH_NONE);
+
+ if (isInCarrierRoamingNbIotNtn(phone)) {
+ if (isInConnectedState()) {
+ synchronized (mNtnSignalsStrengthLock) {
+ carrierRoamingNtnSignalStrength = mNtnSignalStrength;
+ }
+ plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId()
+ + "]: in carrier roaming nb iot ntn mode.");
+ }
+ } else if (isInSatelliteModeForCarrierRoaming(phone)) {
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState.getState() != ServiceState.STATE_OUT_OF_SERVICE) {
+ carrierRoamingNtnSignalStrength = new NtnSignalStrength(
+ phone.getSignalStrength().getLevel());
+ plogd("getCarrierRoamingNtnSignalStrength[phoneId=" + phone.getPhoneId()
+ + "]: is in satellite mode for carrier roaming.");
+ }
+ }
+
+ return carrierRoamingNtnSignalStrength;
+ }
+
+ /**
+ * Returns satellite connected state from modem, return true if connected.
+ */
+ public boolean isInConnectedState() {
+ synchronized (mSatelliteModemStateLock) {
+ switch (mSatelliteModemState) {
+ case SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED: //fallthrough
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: //fallthrough
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
+ plogd("isInConnectedState: return true");
+ return true;
+ default:
+ plogd("isInConnectedState: return false");
+ return false;
+ }
+ }
+ }
+
+ protected void updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ @Nullable Phone phone) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) return;
+ if (phone == null) {
+ return;
+ }
+
+ NtnSignalStrength currSignalStrength = getCarrierRoamingNtnSignalStrength(phone);
+ int subId = phone.getSubId();
+ synchronized (mSatelliteConnectedLock) {
+ NtnSignalStrength lastNotifiedSignalStrength =
+ mLastNotifiedCarrierRoamingNtnSignalStrength.get(subId);
+ if (lastNotifiedSignalStrength == null
+ || lastNotifiedSignalStrength.getLevel() != currSignalStrength.getLevel()) {
+ mLastNotifiedCarrierRoamingNtnSignalStrength.put(subId, currSignalStrength);
+ phone.notifyCarrierRoamingNtnSignalStrengthChanged(currSignalStrength);
+ }
+ }
+ }
+
+ /** Returns whether to send SMS to DatagramDispatcher or not. */
+ public boolean shouldSendSmsToDatagramDispatcher(@Nullable Phone phone) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (!isInCarrierRoamingNbIotNtn(phone)) {
+ return false;
+ }
+
+ if (isDemoModeEnabled()) {
+ return false;
+ }
+
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(phone.getSubId());
+ return ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /** Returns whether to drop SMS or not. */
+ public boolean shouldDropSms(@Nullable Phone phone) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (!isInCarrierRoamingNbIotNtn(phone)) {
+ return false;
+ }
+
+ int[] services = getSupportedServicesOnCarrierRoamingNtn(phone.getSubId());
+ return !ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private boolean isWaitingForSatelliteModemOff() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ return mWaitingForSatelliteModemOff;
+ }
+ }
+
+ @Nullable
+ private Boolean getIsSatelliteSupported() {
+ synchronized (mIsSatelliteSupportedLock) {
+ return mIsSatelliteSupported;
+ }
+ }
+
+ private boolean isWaitingForDisableSatelliteModemResponse() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ return mWaitingForDisableSatelliteModemResponse;
+ }
+ }
+
+ @Nullable
+ private Boolean getIsSatelliteEnabled() {
+ synchronized (mIsSatelliteEnabledLock) {
+ return mIsSatelliteEnabled;
+ }
+ }
+
+ @Nullable
+ private RequestSatelliteEnabledArgument getSatelliteDisabledRequest() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ return mSatelliteDisabledRequest;
+ }
+ }
+
+ private SatelliteCapabilities getSatelliteCapabilities() {
+ synchronized (mSatelliteCapabilitiesLock) {
+ return mSatelliteCapabilities;
+ }
+ }
+
+ private void setBTEnabledState(boolean enabled) {
+ synchronized (mRadioStateLock) {
+ mBTStateEnabled = enabled;
+ }
+ }
+
+ private boolean getBTEnabledState() {
+ synchronized (mRadioStateLock) {
+ return mBTStateEnabled;
+ }
+ }
+
+ private void setNfcEnabledState(boolean enabled) {
+ synchronized (mRadioStateLock) {
+ mNfcStateEnabled = enabled;
+ }
+ }
+
+ private boolean getNfcEnabledState() {
+ synchronized (mRadioStateLock) {
+ return mNfcStateEnabled;
+ }
+ }
+
+ private void setUwbEnabledState(boolean enabled) {
+ synchronized (mRadioStateLock) {
+ mUwbStateEnabled = enabled;
+ }
+ }
+
+ private boolean getUwbEnabledState() {
+ synchronized (mRadioStateLock) {
+ return mUwbStateEnabled;
+ }
+ }
+
+ private void setWifiEnabledState(boolean enabled) {
+ synchronized (mRadioStateLock) {
+ mWifiStateEnabled = enabled;
+ }
+ }
+
+ private boolean getWifiEnabledState() {
+ synchronized (mRadioStateLock) {
+ return mWifiStateEnabled;
+ }
+ }
+
+ /**
+ * Method to return the current data plan for the registered plmn based on entitlement
+ * provisioning information. Note: If no information at
+ * provisioning is supported this is overridden with operator carrier config information.
+ *
+ * @param subId current subscription id
+ * @param plmn current registered plmn information
+ *
+ * @return Data supported modes {@link SatelliteController#SATELLITE_DATA_PLAN_METERED}
+ */
+ public int getSatelliteDataPlanForPlmn(int subId, String plmn) {
+ if (plmn != null) {
+ synchronized (mSupportedSatelliteServicesLock) {
+ Map<String, Integer> dataplanMap = mEntitlementDataPlanMapPerCarrier.get(subId);
+ logd("data plan available for sub id:" + dataplanMap);
+ if (dataplanMap != null && dataplanMap.containsKey(plmn)) {
+ return dataplanMap.get(plmn);
+ }
+ }
+ }
+ // TODO (Override with carrier config value when configuration defined)
+ return SATELLITE_DATA_PLAN_METERED;
+ }
+
+ /**
+ * Method to return the current satellite data service policy supported mode for the registered
+ * plmn based on entitlement provisioning information. Note: If no information at
+ * provisioning is supported this is overridden with operator carrier config information.
+ *
+ * @param subId current subscription id
+ * @param plmn current registered plmn information
+ *
+ * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
+ */
+ public int getSatelliteDataServicePolicyForPlmn(int subId, String plmn) {
+ if (plmn != null) {
+ synchronized (mSupportedSatelliteServicesLock) {
+ Map<String, Integer> dataServicePolicy =
+ mEntitlementDataServicePolicyMapPerCarrier.get(
+ subId);
+ logd("data policy available for sub id:" + dataServicePolicy);
+ if (dataServicePolicy != null && dataServicePolicy.containsKey(plmn)) {
+ return dataServicePolicy.get(plmn);
+ }
+ }
+ }
+ return getCarrierSatelliteDataSupportedMode(subId);
+ }
+
+ /**
+ * Method to return the current satellite voice service policy supported mode for the registered
+ * plmn based on entitlement provisioning information. Note: If no information at
+ * provisioning is supported this is overridden with operator carrier config information.
+ *
+ * @param subId current subscription id
+ * @param plmn current registered plmn information
+ *
+ * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
+ */
+ public int getSatelliteVoiceServicePolicyForPlmn(int subId, String plmn) {
+ if (plmn != null) {
+ synchronized (mSupportedSatelliteServicesLock) {
+ Map<String, Integer> voiceServicePolicy =
+ mEntitlementVoiceServicePolicyMapPerCarrier.get(
+ subId);
+ logd("voice policy available for sub id:" + voiceServicePolicy);
+ if (voiceServicePolicy != null && voiceServicePolicy.containsKey(plmn)) {
+ return voiceServicePolicy.get(plmn);
+ }
+ }
+ }
+ // TODO (Replace below code with related enum value, when voice service policy support mode
+ // is added)
+ return 0; // Restricted
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index a19f802..5b032e6 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -41,6 +41,7 @@
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteManager.SatelliteException;
import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SystemSelectionSpecifier;
import android.telephony.satellite.stub.INtnSignalStrengthConsumer;
import android.telephony.satellite.stub.ISatellite;
import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
@@ -104,6 +105,8 @@
new RegistrantList();
@NonNull private final RegistrantList mSatelliteRegistrationFailureRegistrants =
new RegistrantList();
+ @NonNull private final RegistrantList mTerrestrialNetworkAvailableChangedRegistrants =
+ new RegistrantList();
private class SatelliteListener extends ISatelliteListener.Stub {
@@ -192,6 +195,11 @@
mSatelliteRegistrationFailureRegistrants.notifyResult(causeCode);
}
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ mTerrestrialNetworkAvailableChangedRegistrants.notifyResult(isAvailable);
+ }
+
private boolean notifyResultIfExpectedListener() {
// Demo listener should notify results only during demo mode
// Vendor listener should notify result only during real mode
@@ -587,6 +595,27 @@
}
/**
+ * Registers for the terrestrial network available changed.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForTerrestrialNetworkAvailableChanged(
+ @NonNull Handler h, int what, @Nullable Object obj) {
+ mTerrestrialNetworkAvailableChangedRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for the terrestrial network available changed.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForTerrestrialNetworkAvailableChanged(@NonNull Handler h) {
+ mTerrestrialNetworkAvailableChangedRegistrants.remove(h);
+ }
+
+ /**
* Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
@@ -652,14 +681,14 @@
};
if (mSatelliteController.isDemoModeEnabled()) {
- mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn(
+ mDemoSimulator.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
enabled, errorCallback);
} else {
- mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(
+ mSatelliteService.enableTerrestrialNetworkScanWhileSatelliteModeIsOn(
enabled, errorCallback);
}
} catch (RemoteException e) {
- ploge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ ploge("enableTerrestrialNetworkScanWhileSatelliteModeIsOn: RemoteException " + e);
if (message != null) {
sendMessageWithResult(
message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
@@ -1355,6 +1384,42 @@
mExponentialBackoff.start();
}
+ /**
+ * Request to update system selection channels
+ *
+ * @param systemSelectionSpecifiers system selection specifiers
+ * @param message The Message to send to result of the operation to.
+ */
+ public void updateSystemSelectionChannels(
+ @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
+ @Nullable Message message) {
+ plogd("updateSystemSelectionChannels: SystemSelectionSpecifier: "
+ + systemSelectionSpecifiers.toString());
+ if (mSatelliteService != null) {
+ try {
+ mSatelliteService.updateSystemSelectionChannels(SatelliteServiceUtils
+ .toSystemSelectionSpecifier(systemSelectionSpecifiers),
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ int error = SatelliteServiceUtils.fromSatelliteError(result);
+ plogd("updateSystemSelectionChannels: " + error);
+ Binder.withCleanCallingIdentity(() ->
+ sendMessageWithResult(message, null, error));
+ }
+ });
+ } catch (RemoteException e) {
+ ploge("updateSystemSelectionChannels: RemoteException " + e);
+ sendMessageWithResult(message, null,
+ SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
+ }
+ } else {
+ ploge("updateSystemSelectionChannels: Satellite service is unavailable.");
+ sendMessageWithResult(message, null,
+ SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
+ }
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected static void sendMessageWithResult(@NonNull Message message, @Nullable Object result,
@SatelliteManager.SatelliteResult int error) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
index 7db9195..f101f18 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
@@ -16,6 +16,9 @@
package com.android.internal.telephony.satellite;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Data class of the satellite configuration received from the entitlement server.
*/
@@ -28,9 +31,21 @@
* 2. "metered"
* 3. empty string. */
public String mDataPlanType;
+ /** Stored the Allowed Services Info. with key as service type and value as service
+ * policy for the plmn
+ * Possible Service Type values: "data" and "voice".
+ * Possible Service Policy values: "constrained" and "unconstrained".
+ */
+ public Map<String,String> mAllowedServicesInfo;
- public SatelliteNetworkInfo(String plmn, String dataPlanType) {
+ public SatelliteNetworkInfo(String plmn, String dataPlanType,
+ Map<String,String> allowedServicesInfo) {
mPlmn = plmn;
mDataPlanType = dataPlanType;
+ if (allowedServicesInfo != null) {
+ mAllowedServicesInfo = new HashMap<>(allowedServicesInfo);
+ } else {
+ mAllowedServicesInfo = new HashMap<>();
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 50732fa..e924878 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -24,6 +24,9 @@
import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
import static com.android.internal.telephony.flags.Flags.satellitePersistentLogging;
import static com.android.internal.telephony.satellite.SatelliteController.INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
@@ -73,6 +76,7 @@
import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.SatelliteStats;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -262,6 +266,27 @@
return SmsApplication.getDefaultSendToApplication(mContext, false);
}
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean updateAndGetProvisionState() {
+ mSatelliteController.updateSatelliteProvisionedStatePerSubscriberId();
+ return isDeviceProvisioned();
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean isSatelliteAllowedByReasons() {
+ SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
+ int[] disallowedReasons = satelliteManager.getSatelliteDisallowedReasons();
+ if (Arrays.stream(disallowedReasons).anyMatch(r ->
+ (r == SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP
+ || r == SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED
+ || r == SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED))) {
+ plogd("isAllowedForDefaultMessageApp:false, disallowedReasons="
+ + Arrays.toString(disallowedReasons));
+ return false;
+ }
+ return true;
+ }
+
private void handleEmergencyCallStartedEvent(@NonNull Connection connection) {
plogd("handleEmergencyCallStartedEvent: connection=" + connection);
mSatelliteController.setLastEmergencyCallTime();
@@ -284,7 +309,8 @@
}
private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
- if (!provisioned) {
+ if (!provisioned
+ && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
cleanUpResources(false);
}
}
@@ -310,6 +336,8 @@
return;
}
+ updateAndGetProvisionState();
+
/*
* The device might be connected to satellite after the emergency call started. Thus, we
* need to do this check again so that we will have higher chance of sending the event
@@ -321,7 +349,7 @@
boolean isCellularAvailable = SatelliteServiceUtils.isCellularAvailable();
if (!isCellularAvailable
&& isSatelliteAllowed()
- && (isSatelliteViaOemAvailable()
+ && ((isDeviceProvisioned() && isSatelliteAllowedByReasons())
|| isSatelliteConnectedViaCarrierWithinHysteresisTime())
&& shouldTrackCall(mEmergencyConnection.getState())) {
plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
@@ -359,8 +387,8 @@
* @return {@code true} if satellite is provisioned via OEM else return {@code false}
*/
@VisibleForTesting
- public boolean isSatelliteViaOemAvailable() {
- Boolean satelliteProvisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ public boolean isDeviceProvisioned() {
+ Boolean satelliteProvisioned = mSatelliteController.isDeviceProvisioned();
return satelliteProvisioned != null ? satelliteProvisioned : false;
}
@@ -645,7 +673,7 @@
@NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage(
boolean isTestEmergencyNumber) {
- int handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
+ int handoverType = getEmergencyCallToSatelliteHandoverType();
Pair<String, String> oemSatelliteMessagingApp =
getOemEnabledSatelliteHandoverAppFromOverlayConfig(mContext);
String packageName = oemSatelliteMessagingApp.first;
@@ -653,10 +681,8 @@
String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext,
isTestEmergencyNumber);
- if (isSatelliteConnectedViaCarrierWithinHysteresisTime()
- || isEmergencyCallToSatelliteHandoverTypeT911Enforced()) {
+ if (handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911) {
ComponentName defaultSmsAppComponent = getDefaultSmsApp();
- handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
packageName = defaultSmsAppComponent.getPackageName();
className = defaultSmsAppComponent.getClassName();
}
@@ -737,7 +763,9 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public int getEmergencyCallToSatelliteHandoverType() {
- if (Flags.carrierRoamingNbIotNtn() && isSatelliteViaOemAvailable()
+ if (Flags.carrierRoamingNbIotNtn()
+ && isDeviceProvisioned()
+ && isSatelliteAllowedByReasons()
&& isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
@@ -799,7 +827,7 @@
}
private boolean isSatelliteViaOemProvisioned() {
- Boolean provisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ Boolean provisioned = mSatelliteController.isDeviceProvisioned();
return (provisioned != null) && provisioned;
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index 3936a7e..b55c622 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -36,13 +36,16 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.AntennaPosition;
+import android.telephony.satellite.EarfcnRange;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.PointingInfo;
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteInfo;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.telephony.satellite.SystemSelectionSpecifier;
import android.telephony.satellite.stub.NTRadioTechnology;
import android.telephony.satellite.stub.SatelliteModemState;
import android.telephony.satellite.stub.SatelliteResult;
@@ -542,6 +545,100 @@
return mcc + mnc;
}
+ @NonNull
+ private static android.telephony.satellite.stub
+ .SystemSelectionSpecifier convertSystemSelectionSpecifierToHALFormat(
+ @NonNull SystemSelectionSpecifier systemSelectionSpecifier) {
+ android.telephony.satellite.stub.SystemSelectionSpecifier convertedSpecifier =
+ new android.telephony.satellite.stub.SystemSelectionSpecifier();
+
+ convertedSpecifier.mMccMnc = systemSelectionSpecifier.getMccMnc();
+ convertedSpecifier.mBands = systemSelectionSpecifier.getBands();
+ convertedSpecifier.mEarfcs = systemSelectionSpecifier.getEarfcns();
+ SatelliteInfo[] satelliteInfos = systemSelectionSpecifier.getSatelliteInfos()
+ .toArray(new SatelliteInfo[0]);
+ android.telephony.satellite.stub.SatelliteInfo[] halSatelliteInfos =
+ new android.telephony.satellite.stub.SatelliteInfo[satelliteInfos.length];
+ for (int i = 0; i < satelliteInfos.length; i++) {
+ halSatelliteInfos[i] = new android.telephony.satellite.stub.SatelliteInfo();
+
+ halSatelliteInfos[i].id = new android.telephony.satellite.stub.UUID();
+ halSatelliteInfos[i].id.mostSigBits =
+ satelliteInfos[i].getSatelliteId().getMostSignificantBits();
+ halSatelliteInfos[i].id.leastSigBits =
+ satelliteInfos[i].getSatelliteId().getLeastSignificantBits();
+
+ halSatelliteInfos[i].position =
+ new android.telephony.satellite.stub.SatellitePosition();
+ halSatelliteInfos[i].position.longitudeDegree =
+ satelliteInfos[i].getSatellitePosition().getLongitudeDegrees();
+ halSatelliteInfos[i].position.altitudeKm =
+ satelliteInfos[i].getSatellitePosition().getAltitudeKm();
+
+ halSatelliteInfos[i].bands = satelliteInfos[i].getBands().stream().mapToInt(
+ Integer::intValue).toArray();
+
+ List<EarfcnRange> earfcnRangeList = satelliteInfos[i].getEarfcnRanges();
+ halSatelliteInfos[i].earfcnRanges =
+ new android.telephony.satellite.stub.EarfcnRange[earfcnRangeList.size()];
+ for (int j = 0; j < earfcnRangeList.size(); j++) {
+ halSatelliteInfos[i].earfcnRanges[j] =
+ new android.telephony.satellite.stub.EarfcnRange();
+ halSatelliteInfos[i].earfcnRanges[j].startEarfcn = earfcnRangeList.get(
+ j).getStartEarfcn();
+ halSatelliteInfos[i].earfcnRanges[j].endEarfcn = earfcnRangeList.get(
+ j).getEndEarfcn();
+ }
+ }
+ convertedSpecifier.satelliteInfos = halSatelliteInfos;
+ convertedSpecifier.tagIds = systemSelectionSpecifier.getTagIds();
+ return convertedSpecifier;
+ }
+
+ /**
+ * Convert SystemSelectionSpecifier from framework definition to service definition
+ * @param systemSelectionSpecifier The SystemSelectionSpecifier from the framework.
+ * @return The converted SystemSelectionSpecifier for the satellite service.
+ */
+ @NonNull
+ public static List<android.telephony.satellite.stub
+ .SystemSelectionSpecifier> toSystemSelectionSpecifier(
+ @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifier) {
+ return systemSelectionSpecifier.stream().map(
+ SatelliteServiceUtils::convertSystemSelectionSpecifierToHALFormat).collect(
+ Collectors.toList());
+ }
+
+ /**
+ * Expected format of the input dictionary bundle is:
+ * <ul>
+ * <li>Key: Regional satellite config Id string.</li>
+ * <li>Value: Integer arrays of earfcns in the corresponding regions."</li>
+ * </ul>
+ * @return The map of earfcns with key: regional satellite config Id,
+ * value: set of earfcns in the corresponding regions.
+ */
+ @NonNull
+ public static Map<String, Set<Integer>> parseRegionalSatelliteEarfcns(
+ @Nullable PersistableBundle earfcnsBundle) {
+ Map<String, Set<Integer>> earfcnsMap = new HashMap<>();
+ if (earfcnsBundle == null || earfcnsBundle.isEmpty()) {
+ logd("parseRegionalSatelliteEarfcns: earfcnsBundle is null or empty");
+ return earfcnsMap;
+ }
+
+ for (String configId : earfcnsBundle.keySet()) {
+ Set<Integer> earfcnsSet = new HashSet<>();
+ for (int earfcn : earfcnsBundle.getIntArray(configId)) {
+ earfcnsSet.add(earfcn);
+ }
+ logd("parseRegionalSatelliteEarfcns: configId = " + configId + ", earfcns ="
+ + earfcnsSet.stream().map(String::valueOf).collect(joining(",")));
+ earfcnsMap.put(configId, earfcnsSet);
+ }
+ return earfcnsMap;
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(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 4138df3..f2f4cac 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -40,19 +40,24 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncResult;
import android.os.Build;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PersistentLogger;
import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
@@ -63,7 +68,6 @@
import android.util.Log;
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;
@@ -72,6 +76,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
+import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.telephony.Rlog;
@@ -131,6 +136,7 @@
private static final int EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 12;
private static final int EVENT_SERVICE_STATE_CHANGED = 13;
protected static final int EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT = 14;
+
private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
private static final int REBIND_MULTIPLIER = 2;
@@ -176,15 +182,20 @@
boolean mIsScreenOn = true;
private boolean mIsDeviceAlignedWithSatellite = false;
- @GuardedBy("mLock")
- @NonNull private boolean mIsDisableCellularModemInProgress = false;
@NonNull private final SatelliteController mSatelliteController;
@NonNull private final DatagramController mDatagramController;
@Nullable private PersistentLogger mPersistentLogger = null;
@Nullable private DeviceStateMonitor mDeviceStateMonitor;
@NonNull private SessionMetricsStats mSessionMetricsStats;
-
@NonNull private FeatureFlags mFeatureFlags;
+ @NonNull private AlarmManager mAlarmManager;
+ private final AlarmManager.OnAlarmListener mAlarmListener = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ plogd("onAlarm: screen off timer expired");
+ sendMessage(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ }
+ };
/**
* @return The singleton instance of SatelliteSessionController.
@@ -296,20 +307,7 @@
}
mDeviceStateMonitor = satellitePhone.getDeviceStateMonitor();
mSessionMetricsStats = SessionMetricsStats.getInstance();
-
- if (mFeatureFlags.carrierRoamingNbIotNtn()) {
- // Register to received Cellular service state
- for (Phone phone : PhoneFactory.getPhones()) {
- if (phone == null) continue;
-
- phone.registerForServiceStateChanged(
- getHandler(), EVENT_SERVICE_STATE_CHANGED, null);
- if (DBG) {
- plogd("SatelliteSessionController: registerForServiceStateChanged phoneId "
- + phone.getPhoneId());
- }
- }
- }
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
addState(mUnavailableState);
addState(mPowerOffState);
@@ -594,6 +592,9 @@
plogd("cleanUpResource");
mIsDeviceAlignedWithSatellite = false;
unregisterForScreenStateChanged();
+ if (mAlarmManager != null) {
+ mAlarmManager.cancel(mAlarmListener);
+ }
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
// Register to received Cellular service state
@@ -621,6 +622,16 @@
sendMessage(EVENT_SERVICE_STATE_CHANGED, new AsyncResult(null, serviceState, null));
}
+ /**
+ * Uses this function to set AlarmManager object for testing.
+ *
+ * @param alarmManager The instance of AlarmManager.
+ */
+ @VisibleForTesting
+ public void setAlarmManager(AlarmManager alarmManager) {
+ mAlarmManager = alarmManager;
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -665,9 +676,6 @@
mPreviousState = mCurrentState;
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
mIsSendingTriggeredDuringTransferringState.set(false);
- synchronized (mLock) {
- mIsDisableCellularModemInProgress = false;
- }
unbindService();
stopNbIotInactivityTimer();
DemoSimulator.getInstance().onSatelliteModeOff();
@@ -866,10 +874,23 @@
stopNbIotInactivityTimer();
//Enable Cellular Modem scanning
- Message onCompleted =
+ boolean configSatelliteAllowTnScanningDuringSatelliteSession =
+ mContext.getResources().getBoolean(
+ R.bool.config_satellite_allow_tn_scanning_during_satellite_session);
+ if (configSatelliteAllowTnScanningDuringSatelliteSession) {
+ Message onCompleted =
obtainMessage(EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
- notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ mSatelliteModemInterface
+ .enableCellularModemWhileSatelliteModeIsOn(true, onCompleted);
+ } else {
+ plogd("Device does not allow cellular modem scanning");
+ }
+ if (isConcurrentTnScanningSupported()
+ || !configSatelliteAllowTnScanningDuringSatelliteSession) {
+ plogd("IDLE state is hidden from clients");
+ } else {
+ notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ }
}
@Override
@@ -884,7 +905,7 @@
break;
case EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
- (AsyncResult) msg.obj);
+ (AsyncResult) msg.obj);
break;
case EVENT_SATELLITE_ENABLEMENT_STARTED:
handleSatelliteEnablementStarted((boolean) msg.obj);
@@ -899,12 +920,7 @@
handleSatelliteModemStateChanged(msg);
break;
case EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE:
- if (!mIgnoreCellularServiceState) {
- handleEventEnableCellularModemWhileSatelliteModeIsOnDone();
- } else {
- plogd("IdleState: processing: ignore "
- + "EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE");
- }
+ plogd("EVENT_ENABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE");
break;
case EVENT_SERVICE_STATE_CHANGED:
if (!mIgnoreCellularServiceState) {
@@ -929,39 +945,19 @@
if ((datagramTransferState.sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) {
- if (mSatelliteController.isSatelliteAttachRequired()) {
- ploge("Unexpected transferring state received for NB-IOT NTN");
- } else {
- transitionTo(mTransferringState);
- }
+ transitionTo(mTransferringState);
} else if ((datagramTransferState.sendState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT)) {
if (mSatelliteController.isSatelliteAttachRequired()) {
- disableCellularModemWhileSatelliteModeIsOn();
+ transitionTo(mNotConnectedState);
} else {
ploge("Unexpected transferring state received for non-NB-IOT NTN");
}
}
}
- private void handleEventEnableCellularModemWhileSatelliteModeIsOnDone() {
- if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- Rlog.d(TAG, "handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
- + "carrierRoamingNbIotNtn is disabled");
- return;
- }
-
- ServiceState serviceState = mSatelliteController.getSatellitePhone().getServiceState();
- if (serviceState == null) {
- plogd("handleEventEnableCellularModemWhileSatelliteModeIsOnDone: "
- + "can't access ServiceState");
- return;
- }
- handleEventServiceStateChanged(serviceState);
- }
-
private void handleEventServiceStateChanged(ServiceState serviceState) {
boolean isInServiceOrEmergency =
serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
@@ -1003,49 +999,32 @@
private void handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
@NonNull AsyncResult result) {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- int error = SatelliteServiceUtils.getSatelliteError(
- result, "DisableCellularModemWhileSatelliteModeIsOnDone");
- if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- transitionTo(mNotConnectedState);
- }
- mIsDisableCellularModemInProgress = false;
- } else {
- ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
- }
- }
+ int error = SatelliteServiceUtils.getSatelliteError(
+ result, "DisableCellularModemWhileSatelliteModeIsOnDone");
+ plogd("Disable TN scanning done with result: " + error);
}
private void handleSatelliteModemStateChanged(@NonNull Message msg) {
int state = msg.arg1;
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
transitionTo(mPowerOffState);
- }
- }
-
- private void disableCellularModemWhileSatelliteModeIsOn() {
- synchronized (mLock) {
- if (mIsDisableCellularModemInProgress) {
- plogd("Cellular scanning is already being disabled");
- return;
+ } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED
+ || state == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED) {
+ if (isConcurrentTnScanningSupported()) {
+ plogd("Notifying the new state " + state + " to clients but still"
+ + " stay at IDLE state internally");
+ notifyStateChangedEvent(state);
+ } else {
+ plogd("Ignoring the modem state " + state);
}
-
- mIsDisableCellularModemInProgress = true;
- Message onCompleted =
- obtainMessage(EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE);
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false,
- onCompleted);
}
}
@Override
public void exit() {
if (DBG) plogd("Exiting IdleState");
- if (!mSatelliteController.isSatelliteAttachRequired()) {
- // Disable cellular modem scanning
- mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
- }
+ // Disable cellular modem scanning
+ mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
}
}
@@ -1319,6 +1298,8 @@
startNbIotInactivityTimer();
evaluateStartingEsosInactivityTimer();
evaluateStartingP2pSmsInactivityTimer();
+ mSatelliteController.updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
+ mSatelliteController.getSatellitePhone());
}
@Override
@@ -1669,16 +1650,42 @@
}
mIsScreenOn = screenOn;
+ if (mSatelliteController.getRequestIsEmergency()) {
+ if (DBG) logd("handleEventScreenStateChanged: Emergency mode");
+ // This is for coexistence
+ // emergency mode can be set after registerForScreenStateChanged() called for P2P-sms
+ return;
+ }
+
+ int subId = getSubId();
+ if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) {
+ if (DBG) plogd("handleEventScreenStateChanged: P2P_SMS is not supported");
+ return;
+ }
+
if (!screenOn) {
// Screen off, start timer
int timeoutMillis = getScreenOffInactivityTimeoutDurationSec() * 1000;
- sendMessageDelayed(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT, timeoutMillis);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to start timer");
+ return;
+ }
+
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeoutMillis,
+ TAG, new HandlerExecutor(getHandler()), new WorkSource(), mAlarmListener);
plogd("handleEventScreenStateChanged: start timer " + timeoutMillis);
} else {
// Screen on, stop timer
removeMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
+ if (mAlarmManager == null) {
+ plogd("handleEventScreenStateChanged: can not access AlarmManager to stop timer");
+ return;
+ }
+
+ mAlarmManager.cancel(mAlarmListener);
plogd("handleEventScreenStateChanged: stop timer");
}
}
@@ -1767,19 +1774,19 @@
}
if (isP2pSmsInActivityTimerStarted()) {
- plogd("isEsosInActivityTimerStarted: "
+ plogd("isP2pSmsInActivityTimerStarted: "
+ "P2P_SMS inactivity timer already started");
return;
}
int subId = getSubId();
- if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) {
- plogd("evaluateStartingEsosInactivityTimer: P2P_SMS is not supported");
+ if (!isP2pSmsSupportedOnCarrierRoamingNtn(subId)) {
+ if (DBG) plogd("evaluateStartingP2pSmsInactivityTimer: P2P_SMS is not supported");
return;
}
if (mIsDeviceAlignedWithSatellite) {
- plogd("evaluateStartingEsosInactivityTimer: "
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ "can't start P2P_SMS inactivity timer due to device aligned satellite");
return;
}
@@ -1789,10 +1796,10 @@
if (datagramController.isSendingInIdleState()
&& datagramController.isPollingInIdleState()) {
sendMessageDelayed(EVENT_P2P_SMS_INACTIVITY_TIMER_TIMED_OUT, timeOutMillis);
- plogd("evaluateStartingEsosInactivityTimer: start P2P_SMS inactivity timer "
+ plogd("evaluateStartingP2pSmsInactivityTimer: start P2P_SMS inactivity timer "
+ timeOutMillis);
} else {
- plogd("evaluateStartingEsosInactivityTimer: "
+ plogd("evaluateStartingP2pSmsInactivityTimer: "
+ "can't start P2P_SMS inactivity timer");
}
}
@@ -1810,6 +1817,15 @@
}
private void handleEventScreenOffInactivityTimerTimedOut() {
+ if (mSatelliteController.getRequestIsEmergency()) {
+ loge("handleEventScreenOffInactivityTimerTimedOut: Emergency mode");
+ /* This is for coexistence
+ * mIsEmergency can be set after
+ * EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT timer started
+ */
+ return;
+ }
+
plogd("handleEventScreenOffInactivityTimerTimedOut: request disable satellite");
mSatelliteController.requestSatelliteEnabled(
@@ -1905,6 +1921,25 @@
return true;
}
+ private boolean isP2pSmsSupportedOnCarrierRoamingNtn(int subId) {
+ if (!mSatelliteController.isSatelliteRoamingP2pSmSSupported(subId)) {
+ if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS is not supported");
+ return false;
+ }
+
+ int[] services = mSatelliteController.getSupportedServicesOnCarrierRoamingNtn(subId);
+ if (!ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_SMS)) {
+ if (DBG) {
+ plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2P_SMS service is not supported "
+ + "on carrier roaming ntn.");
+ }
+ return false;
+ }
+
+ if (DBG) plogd("isP2pSmsSupportedOnCarrierRoamingNtn: P2_SMS is supported");
+ return true;
+ }
+
private boolean isSatellitePersistentLoggingEnabled(
@NonNull Context context, @NonNull FeatureFlags featureFlags) {
if (featureFlags.satellitePersistentLogging()) {
@@ -1918,6 +1953,16 @@
}
}
+ private boolean isConcurrentTnScanningSupported() {
+ try {
+ return mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning);
+ } catch (RuntimeException e) {
+ plogd("isConcurrentTnScanningSupported: ex=" + e);
+ return false;
+ }
+ }
+
private void plogd(@NonNull String log) {
logd(log);
if (mPersistentLogger != null) {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
index 771432e..3138b16 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -325,13 +325,18 @@
return;
}
String simCountry = MccTable.countryCodeForMcc(subscriptionInfoInternal.getMcc());
- String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
- satelliteRegisteredPlmn.substring(0, 3));
- if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
- mIsNtnRoamingInHomeCountry = false;
- } else {
- // If device is connected to roaming non-terrestrial network, update to true.
- mIsNtnRoamingInHomeCountry = true;
+ mIsNtnRoamingInHomeCountry = true;
+ if (satelliteRegisteredPlmn != null
+ && satelliteRegisteredPlmn.length() >= 3) {
+ String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
+ satelliteRegisteredPlmn.substring(0, 3));
+ if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
+ mIsNtnRoamingInHomeCountry = true;
+ } else {
+ // If device is connected to roaming non-terrestrial network, then marking as
+ // roaming in external country
+ mIsNtnRoamingInHomeCountry = false;
+ }
}
logd("updateNtnRoamingInHomeCountry: mIsNtnRoamingInHomeCountry="
+ mIsNtnRoamingInHomeCountry);
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
index a234378..0a82b99 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
@@ -18,6 +18,7 @@
import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+import static android.telephony.satellite.SatelliteManager.KEY_SESSION_STATS_V2;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import android.annotation.NonNull;
@@ -46,9 +47,13 @@
private long mTerminationProcessingTimeMillis;
private int mSessionDurationSec;
private int mCountOfSuccessfulOutgoingDatagram;
+ private int mShadowCountOfSuccessfulOutgoingDatagram;
private int mCountOfFailedOutgoingDatagram;
+ private int mShadowCountOfFailedOutgoingDatagram;
private int mCountOfTimedOutUserMessagesWaitingForConnection;
+ private int mShadowCountOfTimedOutUserMessagesWaitingForConnection;
private int mCountOfTimedOutUserMessagesWaitingForAck;
+ private int mShadowCountOfTimedOutUserMessagesWaitingForAck;
private int mCountOfSuccessfulIncomingDatagram;
private int mCountOfIncomingDatagramFailed;
private boolean mIsDemoMode;
@@ -57,9 +62,11 @@
private int mCountOfSatelliteNotificationDisplayed;
private int mCountOfAutoExitDueToScreenOff;
private int mCountOfAutoExitDueToTnNetwork;
+ private SatelliteSessionStats datagramStats;
private SessionMetricsStats() {
initializeSessionMetricsParam();
+ datagramStats = new SatelliteSessionStats();
}
/**
@@ -124,13 +131,16 @@
/** Increase the count of successful outgoing datagram transmission. */
public SessionMetricsStats addCountOfSuccessfulOutgoingDatagram(
- @NonNull @SatelliteManager.DatagramType int datagramType) {
+ @NonNull @SatelliteManager.DatagramType int datagramType,
+ long datagramTransmissionTime) {
+ datagramStats.recordSuccessfulOutgoingDatagramStats(datagramType, datagramTransmissionTime);
if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
// Ignore KEEP_ALIVE messages
return this;
}
mCountOfSuccessfulOutgoingDatagram++;
+ mShadowCountOfSuccessfulOutgoingDatagram++;
logd("addCountOfSuccessfulOutgoingDatagram: current count="
+ mCountOfSuccessfulOutgoingDatagram);
return this;
@@ -140,12 +150,14 @@
public SessionMetricsStats addCountOfFailedOutgoingDatagram(
@NonNull @SatelliteManager.DatagramType int datagramType,
@NonNull @SatelliteManager.SatelliteResult int resultCode) {
+ datagramStats.addCountOfUnsuccessfulUserMessages(datagramType, resultCode);
if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
// Ignore KEEP_ALIVE messages
return this;
}
mCountOfFailedOutgoingDatagram++;
+ mShadowCountOfFailedOutgoingDatagram++;
logd("addCountOfFailedOutgoingDatagram: current count=" + mCountOfFailedOutgoingDatagram);
if (resultCode == SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE) {
@@ -166,6 +178,7 @@
}
mCountOfTimedOutUserMessagesWaitingForConnection++;
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection++;
logd("addCountOfTimedOutUserMessagesWaitingForConnection: current count="
+ mCountOfTimedOutUserMessagesWaitingForConnection);
return this;
@@ -180,6 +193,7 @@
}
mCountOfTimedOutUserMessagesWaitingForAck++;
+ mShadowCountOfTimedOutUserMessagesWaitingForAck++;
logd("addCountOfTimedOutUserMessagesWaitingForAck: current count="
+ mCountOfTimedOutUserMessagesWaitingForAck);
return this;
@@ -276,18 +290,23 @@
/** Returns {@link SatelliteSessionStats} of the satellite service. */
public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) {
+ Log.i(TAG, "requestSatelliteSessionStats called");
Bundle bundle = new Bundle();
SatelliteSessionStats sessionStats = new SatelliteSessionStats.Builder()
- .setCountOfSuccessfulUserMessages(mCountOfSuccessfulOutgoingDatagram)
- .setCountOfUnsuccessfulUserMessages(mCountOfFailedOutgoingDatagram)
+ .setCountOfSuccessfulUserMessages(mShadowCountOfSuccessfulOutgoingDatagram)
+ .setCountOfUnsuccessfulUserMessages(mShadowCountOfFailedOutgoingDatagram)
.setCountOfTimedOutUserMessagesWaitingForConnection(
- mCountOfTimedOutUserMessagesWaitingForConnection)
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection)
.setCountOfTimedOutUserMessagesWaitingForAck(
- mCountOfTimedOutUserMessagesWaitingForAck)
+ mShadowCountOfTimedOutUserMessagesWaitingForAck)
.setCountOfUserMessagesInQueueToBeSent(
DatagramDispatcher.getInstance().getPendingUserMessagesCount())
.build();
bundle.putParcelable(SatelliteManager.KEY_SESSION_STATS, sessionStats);
+
+ // TODO b/381007377 should retrieve MessagesInQueueToBeSent count per messageType and add
+ // to datagramStats
+ bundle.putParcelable(KEY_SESSION_STATS_V2, datagramStats);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
}
@@ -302,9 +321,9 @@
}
private void initializeSessionMetricsParam() {
- mInitializationResult = SatelliteManager.SATELLITE_RESULT_SUCCESS;
+ mInitializationResult = SATELLITE_RESULT_SUCCESS;
mRadioTechnology = SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN;
- mTerminationResult = SatelliteManager.SATELLITE_RESULT_SUCCESS;
+ mTerminationResult = SATELLITE_RESULT_SUCCESS;
mInitializationProcessingTimeMillis = 0;
mTerminationProcessingTimeMillis = 0;
mSessionDurationSec = 0;
@@ -322,6 +341,15 @@
mCountOfAutoExitDueToTnNetwork = 0;
}
+ public void resetSessionStatsShadowCounters() {
+ logd("resetTheStatsCounters");
+ mShadowCountOfSuccessfulOutgoingDatagram = 0;
+ mShadowCountOfFailedOutgoingDatagram = 0;
+ mShadowCountOfTimedOutUserMessagesWaitingForConnection = 0;
+ mShadowCountOfTimedOutUserMessagesWaitingForAck = 0;
+ datagramStats.clear();
+ }
+
private static void logd(@NonNull String log) {
if (DBG) {
Log.d(TAG, log);
diff --git a/src/java/com/android/internal/telephony/uicc/SimTypeInfo.java b/src/java/com/android/internal/telephony/uicc/SimTypeInfo.java
new file mode 100644
index 0000000..b19e42a
--- /dev/null
+++ b/src/java/com/android/internal/telephony/uicc/SimTypeInfo.java
@@ -0,0 +1,78 @@
+/*
+ * 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.uicc;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class contains the sim type information of active physical slot ids.
+ */
+public class SimTypeInfo {
+
+ /**
+ * SimType (bit mask)
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ SimType.SIM_TYPE_UNKNOWN,
+ SimType.SIM_TYPE_PHYSICAL,
+ SimType.SIM_TYPE_ESIM,
+ })
+ public @interface SimType {
+ /** Unknown SIM */
+ int SIM_TYPE_UNKNOWN = 0;
+ /** Physical SIM (Can have eUICC capabilities) */
+ int SIM_TYPE_PHYSICAL = 1 << 0;
+ /** Embedded SIM*/
+ int SIM_TYPE_ESIM = 1 << 1;
+ }
+
+ public @SimType int mCurrentSimType = SimType.SIM_TYPE_UNKNOWN;
+ // Bitmask of the supported {@code SimType}s
+ public int mSupportedSimTypes;
+
+ /**
+ * Set the current SimType according to the input type.
+ */
+ public void setCurrentSimType(int simType) {
+ switch(simType) {
+ case android.hardware.radio.config.SimType.UNKNOWN:
+ mCurrentSimType = SimType.SIM_TYPE_UNKNOWN;
+ break;
+ case android.hardware.radio.config.SimType.PHYSICAL:
+ mCurrentSimType = SimType.SIM_TYPE_PHYSICAL;
+ break;
+ case android.hardware.radio.config.SimType.ESIM:
+ mCurrentSimType = SimType.SIM_TYPE_ESIM;
+ break;
+ default:
+ throw new RuntimeException("Unrecognized RIL_SimType: " + simType);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("SimTypeInfo {activeSimType=").append(mCurrentSimType).append(",")
+ .append("supportedSimType=").append(mSupportedSimTypes);
+ sb.append("}");
+ return sb.toString();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index dd71c44..9db25b6 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -80,6 +80,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -162,8 +163,7 @@
// this needs to be here, because on bootup we dont know which index maps to which UiccSlot
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private CommandsInterface[] mCis;
- @VisibleForTesting
- public UiccSlot[] mUiccSlots;
+ private UiccSlot[] mUiccSlots;
private int[] mPhoneIdToSlotId;
private boolean mIsSlotStatusSupported = true;
@@ -491,6 +491,27 @@
}
/**
+ * Set UiccSlot object for a specific physical slot index on the device.
+ *
+ * This is only supposed to be used internally and by unit tests.
+ *
+ * @param slotId Slot index
+ * @param slot Slot object
+ */
+ @VisibleForTesting
+ public void setUiccSlot(int slotId, @NonNull UiccSlot slot) {
+ synchronized (mLock) {
+ if (!isValidSlotIndex(slotId)) {
+ throw new ArrayIndexOutOfBoundsException("Invalid slot index: " + slotId);
+ }
+ if (mUiccSlots[slotId] != null) {
+ mUiccSlots[slotId].dispose();
+ }
+ mUiccSlots[slotId] = Objects.requireNonNull(slot);
+ }
+ }
+
+ /**
* API to get UiccSlot object for a given phone id
* @return UiccSlot object for the given phone id
*/
@@ -1076,7 +1097,7 @@
log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = "
+ mUiccSlots.length);
}
- mUiccSlots[slotId] = new UiccSlot(mContext, true);
+ setUiccSlot(slotId, new UiccSlot(mContext, true));
}
mUiccSlots[slotId].update(mCis[index], status, index, slotId);
@@ -1353,7 +1374,7 @@
if (VDBG) {
log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length);
}
- mUiccSlots[i] = new UiccSlot(mContext, isActive);
+ setUiccSlot(i, new UiccSlot(mContext, isActive));
}
if (isActive) { // check isActive flag so that we don't have to iterate through all
@@ -1803,6 +1824,17 @@
return mCardStrings;
}
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ @VisibleForTesting
+ public void dispose() {
+ for (var slot : mUiccSlots) {
+ slot.dispose();
+ }
+ mUiccSlots = null;
+ }
+
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("mIsCdmaSupported=" + isCdmaSupported(mContext));
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPort.java b/src/java/com/android/internal/telephony/uicc/UiccPort.java
index 905db70..8118a12 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPort.java
@@ -33,6 +33,8 @@
import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.telephony.Rlog;
+import dalvik.system.CloseGuard;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -46,6 +48,7 @@
// The lock object is created by UiccSlot that owns this UiccCard - this is to share the lock
// between UiccSlot, UiccCard, EuiccCard, UiccPort, EuiccPort and UiccProfile for now.
protected final Object mLock;
+ private final CloseGuard mCloseGuard = CloseGuard.get();
private String mIccid;
protected String mCardId;
@@ -68,6 +71,7 @@
if (DBG) log("Creating");
mPhoneId = phoneId;
mLock = lock;
+ mCloseGuard.open("cleanup");
update(c, ci, ics, uiccCard);
}
@@ -97,6 +101,7 @@
public void dispose() {
synchronized (mLock) {
if (DBG) log("Disposing Port");
+ mCloseGuard.close();
if (mUiccProfile != null) {
mUiccProfile.dispose();
}
@@ -106,9 +111,14 @@
}
@Override
- protected void finalize() {
+ protected void finalize() throws Throwable {
if (DBG) log("UiccPort finalized");
- cleanupOpenLogicalChannelRecordsIfNeeded();
+ try {
+ if (mCloseGuard != null) mCloseGuard.warnIfOpen();
+ cleanupOpenLogicalChannelRecordsIfNeeded();
+ } finally {
+ super.finalize();
+ }
}
/**
@@ -440,7 +450,13 @@
* removal or modem reset. The obsoleted records may trigger a redundant release of logical
* channel that may have been assigned to other client.
*/
+ @SuppressWarnings("GuardedBy")
private void cleanupOpenLogicalChannelRecordsIfNeeded() {
+ // This check may raise GuardedBy warning, but we need it as long as this method is called
+ // from finalize(). We can remove it from there once UiccPort is fully protected against
+ // resource leak (e.g. with CloseGuard) and all (direct and indirect) users are fixed.
+ if (mOpenChannelRecords == null) return;
+
synchronized (mOpenChannelRecords) {
for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
if (DBG) log("Clean up " + record);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index db10271..d986c93 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -391,6 +391,13 @@
}
}
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ public void dispose() {
+ nullifyUiccCard(false);
+ }
+
public boolean isStateUnknown() {
// CardState is not specific to any port index, use default port.
CardState cardState = mCardState.get(TelephonyManager.DEFAULT_PORT_INDEX);
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 1d9dc68..309fe79 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
@@ -233,9 +233,17 @@
if (channel == IccOpenLogicalChannelResponse.INVALID_CHANNEL
|| status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR) {
mChannelOpened = false;
- resultCallback.onException(
- new ApduException("Failed to open logical channel for AID: "
- + mAid + ", with status: " + status));
+ returnRespnseOrException(
+ channel,
+ /* closeChannelImmediately= */ false,
+ /* response= */ null,
+ new ApduException(
+ "Failed to open logical channel for AID: "
+ + mAid
+ + ", with status: "
+ + status),
+ resultCallback,
+ handler);
return;
}
PreferenceManager.getDefaultSharedPreferences(mContext)
diff --git a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
index 4889187..c690ab4 100644
--- a/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/RcsConfigTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.telephony.ims;
+package android.telephony.ims;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -36,6 +36,7 @@
import com.android.internal.telephony.FakeTelephonyProvider;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -176,6 +177,11 @@
createFakeSimInfo();
}
+ @After
+ public void tearDown() {
+ mFakeTelephonyProvider.close();
+ }
+
@Test
@SmallTest
public void testLoadAndUpdateConfigForSub() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
index c7668ca..53719b1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
@@ -24,6 +24,8 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.telephony.flags.Flags;
+
/** Unit tests for {@link CellIdentityCdma}. */
public class CellIdentityCdmaTest extends AndroidTestCase {
@@ -44,6 +46,7 @@
@SmallTest
public void testConstructor() {
+ if (Flags.cleanupCdma()) return;
CellIdentityCdma ci =
new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
ALPHA_LONG, ALPHA_SHORT);
@@ -61,6 +64,7 @@
@SmallTest
public void testNullIsland() {
+ if (Flags.cleanupCdma()) return;
CellIdentityCdma ci =
new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, -1, 0,
ALPHA_LONG, ALPHA_SHORT);
@@ -71,6 +75,7 @@
@SmallTest
public void testEquals() {
+ if (Flags.cleanupCdma()) return;
CellIdentityCdma ciA =
new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
ALPHA_LONG, ALPHA_SHORT);
@@ -97,6 +102,7 @@
@SmallTest
public void testParcel() {
+ if (Flags.cleanupCdma()) return;
CellIdentityCdma ci =
new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
ALPHA_LONG, ALPHA_SHORT);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
index 3a20497..ab5e732 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
@@ -26,6 +26,8 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.telephony.flags.Flags;
+
/** Unit tests for {@link CellSignalStrengthCdma}. */
public class CellSignalStrengthCdmaTest extends AndroidTestCase {
@@ -38,6 +40,7 @@
@SmallTest
public void testConstructor() {
+ if (Flags.cleanupCdma()) return;
CellSignalStrengthCdma css = new CellSignalStrengthCdma(
CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR);
assertEquals(CDMA_DBM, css.getCdmaDbm());
@@ -49,6 +52,7 @@
@SmallTest
public void testInvalidConstructor() {
+ if (Flags.cleanupCdma()) return;
CellSignalStrengthCdma css = new CellSignalStrengthCdma(200, 2000, 20, 400, 200);
assertEquals(Integer.MAX_VALUE, css.getCdmaDbm());
assertEquals(Integer.MAX_VALUE, css.getCdmaEcio());
@@ -59,6 +63,7 @@
@SmallTest
public void testDefaultConstructor() {
+ if (Flags.cleanupCdma()) return;
CellSignalStrengthCdma css = new CellSignalStrengthCdma();
assertEquals(Integer.MAX_VALUE, css.getCdmaDbm());
assertEquals(Integer.MAX_VALUE, css.getCdmaEcio());
@@ -69,6 +74,7 @@
@SmallTest
public void testEquals() {
+ if (Flags.cleanupCdma()) return;
assertTrue(new CellSignalStrengthCdma(
CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR).equals(
new CellSignalStrengthCdma(
@@ -80,6 +86,7 @@
@SmallTest
public void testParcel() {
+ if (Flags.cleanupCdma()) return;
CellSignalStrengthCdma css = new CellSignalStrengthCdma(
CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index da4bf50..522cdac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -15,6 +15,12 @@
*/
package com.android.internal.telephony;
+import static android.telephony.CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI;
+import static android.telephony.CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST;
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.eq;
@@ -26,9 +32,11 @@
import android.telephony.CellIdentityGsm;
import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.DisconnectCause;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDisconnectCause;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
@@ -438,4 +446,46 @@
verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnEligibleStateChanged(
eq(subId), eq(true));
}
+
+ @Test
+ @SmallTest
+ public void testCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = mPhone.getSubId();
+ int[] testServices = {3, 6};
+ mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnAvailableServicesChanged(
+ mPhone, testServices);
+ verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnAvailableServicesChanged(
+ eq(subId), eq(testServices));
+ }
+
+ @Test
+ @SmallTest
+ public void testSecurityAlgorithmsChanged() {
+ doReturn(true).when(mFeatureFlags).securityAlgorithmsUpdateIndications();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ SecurityAlgorithmUpdate update =
+ new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+ mDefaultPhoneNotifierUT.notifySecurityAlgorithmsChanged(mPhone, update);
+ verify(mTelephonyRegistryManager).notifySecurityAlgorithmsChanged(
+ eq(phoneId), eq(subId), eq(update));
+ }
+
+ @Test
+ @SmallTest
+ public void testCellularIdentifierDisclosedChanged() {
+ doReturn(true).when(mFeatureFlags).cellularIdentifierDisclosureIndications();
+ int phoneId = mPhone.getPhoneId();
+ int subId = mPhone.getSubId();
+ CellularIdentifierDisclosure disclosure =
+ new CellularIdentifierDisclosure(NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CELLULAR_IDENTIFIER_IMSI,
+ "001001",
+ false);
+ mDefaultPhoneNotifierUT.notifyCellularIdentifierDisclosedChanged(mPhone, disclosure);
+ verify(mTelephonyRegistryManager).notifyCellularIdentifierDisclosedChanged(
+ eq(phoneId), eq(subId), eq(disclosure));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index c923f69..101c668 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -196,4 +196,11 @@
selectionArgs);
return count;
}
+
+ /**
+ * Release resources. Must be called each time this class is used.
+ */
+ public void close() {
+ mDbHelper.close();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index f92643a..a7923cf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1044,7 +1044,8 @@
doReturn(new TelephonyDisplayInfo(
mNetworkTypeController.getDataNetworkType(),
mNetworkTypeController.getOverrideNetworkType(),
- false)).when(mDisplayInfoController).getTelephonyDisplayInfo();
+ false, false, false))
+ .when(mDisplayInfoController).getTelephonyDisplayInfo();
return null;
}).when(mDisplayInfoController).updateTelephonyDisplayInfo();
mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index d8005e8..28d0318 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -1270,8 +1270,7 @@
doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
assertNotNull(impuList);
assertEquals(refImpuArray.length, impuList.size());
@@ -1288,8 +1287,7 @@
refImpuArray[2] = "tel:+91987754324";
doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
assertNotNull(impuList);
// Null or Empty string cannot be converted to URI
assertEquals(refImpuArray.length - 2, impuList.size());
@@ -1300,7 +1298,7 @@
doReturn(null).when(mPhone).getIsimRecords();
try {
- mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG, FEATURE_ID);
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
fail();
} catch (Exception ex) {
assertTrue(ex instanceof IllegalStateException);
@@ -1311,32 +1309,121 @@
@Test
public void getImsPublicUserIdentities_InValidSubIdCheck() {
try {
- mPhoneSubInfoControllerUT.getImsPublicUserIdentities(-1, TAG, FEATURE_ID);
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(-1, TAG);
fail();
} catch (Exception ex) {
assertTrue(ex instanceof IllegalArgumentException);
- assertTrue(ex.getMessage().contains("Invalid SubscriptionID"));
+ assertTrue(ex.getMessage().contains("Invalid subscription"));
}
}
@Test
public void getImsPublicUserIdentities_NoReadPrivilegedPermission() {
mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
- String[] refImpuArray = new String[3];
- refImpuArray[0] = "012345678";
- refImpuArray[1] = "sip:test@verify.com";
- refImpuArray[2] = "tel:+91987754324";
- doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
- doReturn(refImpuArray).when(mIsimUiccRecords).getIsimImpu();
- List<Uri> impuList = mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG,
- FEATURE_ID);
+ try {
+ mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof SecurityException);
+ assertTrue(ex.getMessage().contains("getImsPublicUserIdentities"));
+ }
- assertNotNull(impuList);
- assertEquals(refImpuArray.length, impuList.size());
- assertEquals(impuList.get(0).toString(), refImpuArray[0]);
- assertEquals(impuList.get(1).toString(), refImpuArray[1]);
- assertEquals(impuList.get(2).toString(), refImpuArray[2]);
mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
}
+
+ @Test
+ public void getImsPcscfAddresses() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = "127.0.0.1";
+ preDefinedPcscfs[1] = "192.168.0.1";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ assertEquals(preDefinedPcscfs.length, pcscfAddresses.size());
+ assertEquals(preDefinedPcscfs[0], pcscfAddresses.get(0).toString());
+ assertEquals(preDefinedPcscfs[1], pcscfAddresses.get(1).toString());
+ assertEquals(preDefinedPcscfs[2], pcscfAddresses.get(2).toString());
+ }
+
+ @Test
+ public void getImsPcscfAddresses_InvalidPcscf() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = null;
+ preDefinedPcscfs[2] = "";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ // Null or Empty string is not added to pcscf list
+ assertEquals(preDefinedPcscfs.length - 2, pcscfAddresses.size());
+ }
+
+ @Test
+ public void getImsPcscfAddresses_IsimNotLoadedError() {
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+ doReturn(null).when(mPhone).getIsimRecords();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IllegalStateException);
+ assertTrue(ex.getMessage().contains("ISIM is not loaded"));
+ }
+ }
+
+ @Test
+ public void getImsPcscfAddresses_InValidSubIdCheck() {
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(-1, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertTrue(ex.getMessage().contains("Invalid subscription"));
+ }
+ }
+
+ @Test
+ public void getImsPcscfAddresses_NoReadPrivilegedPermission() {
+ mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL);
+ doReturn(true).when(mFeatureFlags).supportIsimRecord();
+
+ try {
+ mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+ fail();
+ } catch (Exception ex) {
+ assertTrue(ex instanceof SecurityException);
+ assertTrue(ex.getMessage().contains("getImsPcscfAddresses"));
+ }
+
+ mContextFixture.addCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE);
+ }
+
+ @Test
+ public void getImsPcscfAddresses_FlagDisabled() {
+ String[] preDefinedPcscfs = new String[3];
+ preDefinedPcscfs[0] = "127.0.0.1";
+ preDefinedPcscfs[1] = "192.168.0.1";
+ preDefinedPcscfs[2] = "::1";
+ doReturn(false).when(mFeatureFlags).supportIsimRecord();
+ doReturn(mIsimUiccRecords).when(mPhone).getIsimRecords();
+ doReturn(preDefinedPcscfs).when(mIsimUiccRecords).getIsimPcscf();
+
+ List<String> pcscfAddresses = mPhoneSubInfoControllerUT.getImsPcscfAddresses(0, TAG);
+
+ assertNotNull(pcscfAddresses);
+ assertEquals(0, pcscfAddresses.size());
+ }
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 9bee1ac..404c1b2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -89,6 +89,8 @@
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatelliteModemStateCallback;
+import android.telephony.satellite.SatelliteManager;
import android.text.TextUtils;
import android.util.Pair;
@@ -185,6 +187,7 @@
private static final String[] CARRIER_CONFIG_PNN = new String[] {
String.format("%s,%s", HOME_PNN, "short"), "f2,s2"
};
+ private static final String SATELLITE_DISPLAY_NAME = "SatelliteTest";
private class ServiceStateTrackerTestHandler extends HandlerThread {
@@ -391,6 +394,11 @@
30 /* SIGNAL_STRENGTH_GREAT */
});
+ // satellite display name
+ mBundle.putString(
+ CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING,
+ SATELLITE_DISPLAY_NAME);
+
sendCarrierConfigUpdate(PHONE_ID);
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
@@ -3503,7 +3511,7 @@
doReturn(Arrays.asList("10123")).when(mSatelliteController).getSatellitePlmnsForCarrier(
anyInt());
doReturn(satelliteSupportedServiceList).when(mSatelliteController)
- .getSupportedSatelliteServices(sst.mSubId, "10123");
+ .getSupportedSatelliteServicesForPlmn(sst.mSubId, "10123");
assertFalse(sst.mSS.isUsingNonTerrestrialNetwork());
@@ -3546,4 +3554,42 @@
}
}
}
+
+ @Test
+ public void testSatelliteModemStateCallback() throws Exception {
+ ArgumentCaptor<ISatelliteModemStateCallback> captor =
+ ArgumentCaptor.forClass(ISatelliteModemStateCallback.class);
+ verify(mSatelliteController, times(1)).registerForSatelliteModemStateChanged(
+ captor.capture());
+ ISatelliteModemStateCallback callback = captor.getValue();
+
+ doReturn(1).when(mSatelliteController).getSelectedSatelliteSubId();
+ doReturn(1).when(mPhone).getSubId();
+
+ mSimulatedCommands.setVoiceRegState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
+ mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+ mSimulatedCommands.setDataRegState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
+ mSimulatedCommands.setDataRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+ doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
+ doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegistrationState();
+ sst.mSS = mServiceState;
+
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
+ sendCarrierConfigUpdate(PHONE_ID);
+
+ doReturn(true).when(mSatelliteController).isInConnectedState();
+ callback.onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+
+ // update the spn
+ sst.updateCarrierDisplayName();
+
+ Bundle b = getExtrasFromLastSpnUpdateIntent();
+ assertThat(b.getString(TelephonyManager.EXTRA_PLMN)).isEqualTo(SATELLITE_DISPLAY_NAME);
+ assertThat(b.getBoolean(TelephonyManager.EXTRA_SHOW_PLMN)).isTrue();
+ }
+
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
index 7e4cb08..b59c4de 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
@@ -64,6 +64,7 @@
import androidx.test.filters.MediumTest;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.util.ArrayUtils;
import org.junit.After;
@@ -470,19 +471,21 @@
assertEquals(mSsc.getSignalStrength(), ss);
assertEquals(mSsc.getSignalStrength().isGsm(), true);
- // Send in CDMA-only Signal Strength Info and expect isGsm == false
- ss = new SignalStrength(
- new CellSignalStrengthCdma(-90, -12,
- SignalStrength.INVALID, SignalStrength.INVALID, SignalStrength.INVALID),
- new CellSignalStrengthGsm(),
- new CellSignalStrengthWcdma(),
- new CellSignalStrengthTdscdma(),
- new CellSignalStrengthLte(),
- new CellSignalStrengthNr());
+ if (!Flags.cleanupCdma()) {
+ // Send in CDMA-only Signal Strength Info and expect isGsm == false
+ ss = new SignalStrength(
+ new CellSignalStrengthCdma(-90, -12,
+ SignalStrength.INVALID, SignalStrength.INVALID, SignalStrength.INVALID),
+ new CellSignalStrengthGsm(),
+ new CellSignalStrengthWcdma(),
+ new CellSignalStrengthTdscdma(),
+ new CellSignalStrengthLte(),
+ new CellSignalStrengthNr());
- sendSignalStrength(ss);
- assertEquals(mSsc.getSignalStrength(), ss);
- assertEquals(mSsc.getSignalStrength().isGsm(), false);
+ sendSignalStrength(ss);
+ assertEquals(mSsc.getSignalStrength(), ss);
+ assertEquals(mSsc.getSignalStrength().isGsm(), false);
+ }
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
index 8df4052..786bb94 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
@@ -137,7 +137,7 @@
ArrayList<Byte> NrCqiReport = new ArrayList<>(
Arrays.asList((byte) 3, (byte) 2 , (byte) 1));
SignalStrength s = new SignalStrength(
- new CellSignalStrengthCdma(-93, -132, -89, -125, 5),
+ new CellSignalStrengthCdma(),
new CellSignalStrengthGsm(-79, 2, 5),
new CellSignalStrengthWcdma(-94, 4, -102, -5),
new CellSignalStrengthTdscdma(-95, 2, -103),
@@ -175,7 +175,6 @@
public void testGetCellSignalStrengths() throws Exception {
CellSignalStrengthLte lte = new CellSignalStrengthLte(-85, -91, -6, -10, 1, 12, 1);
CellSignalStrengthGsm gsm = new CellSignalStrengthGsm(-79, 2, 5);
- CellSignalStrengthCdma cdma = new CellSignalStrengthCdma(-93, -132, -89, -125, 5);
CellSignalStrengthWcdma wcdma = new CellSignalStrengthWcdma(-94, 4, -102, -5);
CellSignalStrengthTdscdma tdscdma = new CellSignalStrengthTdscdma(-95, 2, -103);
@@ -194,16 +193,16 @@
// Test that a multiple objects are properly stored and returned by getCellSignalStrengths()
s = new SignalStrength(
- cdma,
+ new CellSignalStrengthCdma(),
new CellSignalStrengthGsm(),
- new CellSignalStrengthWcdma(),
+ wcdma,
new CellSignalStrengthTdscdma(),
lte,
new CellSignalStrengthNr());
css = s.getCellSignalStrengths();
assertEquals(2, css.size());
- assertTrue(css.contains(cdma));
+ assertTrue(css.contains(wcdma));
assertTrue(css.contains(lte));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 8f0cbbb..b8316cb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -1086,7 +1086,8 @@
@Test
public void testSendSmsToDatagramDispatcher() {
- when(mSatelliteController.isInCarrierRoamingNbIotNtn(any(Phone.class))).thenReturn(true);
+ when(mSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+ .thenReturn(true);
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
"test-app", mCallingUserId, false, 0, false, 10, false, 1L, false);
processAllMessages();
@@ -1391,6 +1392,6 @@
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);
+ false, 0, false, 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
index dc1ee63..1846bae 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsMessageBodyTest.java
@@ -16,13 +16,17 @@
package com.android.internal.telephony;
-import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import androidx.test.filters.SmallTest;
+import android.telephony.TelephonyManager;
import com.android.telephony.Rlog;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
/**
* Test cases to verify selection of the optimal 7 bit encoding tables
* (for all combinations of enabled national language tables) for messages
@@ -33,7 +37,7 @@
* Tests both encoding variations: unsupported characters mapped to space,
* and unsupported characters force entire message to UCS-2.
*/
-public class SmsMessageBodyTest extends AndroidTestCase {
+public class SmsMessageBodyTest extends TelephonyTest {
private static final String TAG = "SmsMessageBodyTest";
// ASCII chars in the GSM 7 bit default alphabet
@@ -250,7 +254,12 @@
*/
private static final int UDH_SEPTET_COST_CONCATENATED_MESSAGE = 6;
- @SmallTest
+ @Before
+ public void setUp() {
+ TelephonyManager.setupISmsForTest(Mockito.mock(ISms.class));
+ }
+
+ @Test
public void testCalcLengthAscii() throws Exception {
StringBuilder sb = new StringBuilder(320);
int[] values = {0, 0, 0, SmsConstants.ENCODING_7BIT, 0, 0};
@@ -282,7 +291,7 @@
}
}
- @SmallTest
+ @Test
public void testCalcLengthUnicode() throws Exception {
StringBuilder sb = new StringBuilder(160);
int[] values = {0, 0, 0, SmsConstants.ENCODING_16BIT, 0, 0};
@@ -482,7 +491,7 @@
}
}
- //@LargeTest
+ //@Test
/*public void testCalcLengthMixed7bit() throws Exception {
StringBuilder sb = new StringBuilder(320);
CounterHelper ch = new CounterHelper();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
index 3b637c9..1e1e43f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsUsageMonitorShortCodeTest.java
@@ -26,6 +26,8 @@
import android.os.Looper;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
+
import org.junit.Ignore;
/**
@@ -465,7 +467,8 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- SmsUsageMonitor monitor = new SmsUsageMonitor(TestApplication.getAppContext());
+ SmsUsageMonitor monitor = new SmsUsageMonitor(TestApplication.getAppContext(),
+ new FeatureFlagsImpl());
for (ShortCodeTest test : sShortCodeTests) {
assertEquals("country: " + test.countryIso + " number: " + test.address,
test.category, monitor.checkDestination(test.address, test.countryIso));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index ed45fac..e5aa541 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -15,7 +15,12 @@
*/
package com.android.internal.telephony;
+import static android.telephony.CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI;
+import static android.telephony.CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST;
import static android.telephony.PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
import static android.telephony.ServiceState.FREQUENCY_RANGE_LOW;
import static android.telephony.SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -42,6 +47,7 @@
import android.content.pm.UserInfo;
import android.net.LinkProperties;
import android.os.Build;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -50,17 +56,20 @@
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.BarringInfo;
+import android.telephony.CallState;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityGsm;
import android.telephony.CellIdentityLte;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
import android.telephony.CellLocation;
+import android.telephony.CellularIdentifierDisclosure;
import android.telephony.LinkCapacityEstimate;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -68,6 +77,7 @@
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
+import android.telephony.satellite.NtnSignalStrength;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
@@ -104,6 +114,7 @@
// Mocked classes
private SubscriptionInfo mMockSubInfo;
private TelephonyRegistry.ConfigurationProvider mMockConfigurationProvider;
+ private IBinder mMockIBinder;
private TelephonyCallbackWrapper mTelephonyCallback;
private List<LinkCapacityEstimate> mLinkCapacityEstimateList;
@@ -128,6 +139,10 @@
private long mCallbackModeDurationMillis;
private boolean mCarrierRoamingNtnMode;
private boolean mCarrierRoamingNtnEligible;
+ private int[] mCarrierRoamingNtnAvailableServices;
+ private NtnSignalStrength mCarrierRoamingNtnSignalStrength;
+ private boolean mIsSatelliteEnabled;
+ private final List<List<CallState>> mCallStateList = new ArrayList<>();
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -175,6 +190,10 @@
TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
+ READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
+ TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED);
+ READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
+ TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED);
}
// All events contribute to TelephonyRegistry#isActiveEmergencySessionPermissionRequired
@@ -205,7 +224,10 @@
TelephonyCallback.DataActivityListener,
TelephonyCallback.SimultaneousCellularCallingSupportListener,
TelephonyCallback.EmergencyCallbackModeListener,
- TelephonyCallback.CarrierRoamingNtnModeListener {
+ TelephonyCallback.CarrierRoamingNtnModeListener,
+ TelephonyCallback.SecurityAlgorithmsListener,
+ TelephonyCallback.CellularIdentifierDisclosedListener,
+ TelephonyCallback.CallAttributesListener {
// This class isn't mockable to get invocation counts because the IBinder is null and
// crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
public AtomicInteger invocationCount = new AtomicInteger(0);
@@ -333,6 +355,46 @@
invocationCount.incrementAndGet();
mCarrierRoamingNtnEligible = eligible;
}
+
+ @Override
+ public void onCarrierRoamingNtnAvailableServicesChanged(int[] services) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnAvailableServices = services;
+ }
+
+ @Override
+ public void onCarrierRoamingNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnSignalStrength = ntnSignalStrength;
+ }
+
+ @Override
+ public void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) {
+ invocationCount.incrementAndGet();
+ }
+
+ @Override
+ public void onCellularIdentifierDisclosedChanged(CellularIdentifierDisclosure disclosure) {
+ invocationCount.incrementAndGet();
+ }
+
+ @Override
+ public void onCallStatesChanged(List<CallState> callStateList) {
+ invocationCount.incrementAndGet();
+ mCallStateList.add(callStateList);
+ }
+ }
+
+ public class MySatelliteStateChangeListener implements ISatelliteStateChangeListener {
+ @Override
+ public void onSatelliteEnabledStateChanged(boolean isEnabled) throws RemoteException {
+ mIsSatelliteEnabled = isEnabled;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mMockIBinder;
+ }
}
private void addTelephonyRegistryService() {
@@ -347,6 +409,7 @@
super.setUp(getClass().getSimpleName());
mMockSubInfo = mock(SubscriptionInfo.class);
mMockConfigurationProvider = mock(TelephonyRegistry.ConfigurationProvider.class);
+ mMockIBinder = mock(IBinder.class);
when(mMockConfigurationProvider.getRegistrationLimit()).thenReturn(-1);
when(mMockConfigurationProvider.isRegistrationLimitEnabledInPlatformCompat(anyInt()))
.thenReturn(false);
@@ -374,6 +437,7 @@
processAllMessages();
assertEquals(mTelephonyRegistry.asBinder(),
ServiceManager.getService("telephony.registry"));
+ doReturn(new int[]{1}).when(mSubscriptionManager).getActiveSubscriptionIdList();
}
@After
@@ -393,6 +457,7 @@
mPhysicalChannelConfigs = null;
}
mCellLocation = null;
+ mCallStateList.clear();
super.tearDown();
}
@@ -1289,7 +1354,7 @@
TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
- false);
+ false, false, false);
// Notify with invalid subId on default phone. Should NOT trigger callback.
mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
@@ -1316,11 +1381,11 @@
TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
- false);
+ false, false, false);
TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
- false);
+ false, false, false);
// Notify with invalid subId on default phone. Should NOT trigger callback.
mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
@@ -1343,11 +1408,11 @@
TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
- false);
+ false, false, false);
TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
- false);
+ false, false, false);
TelephonyCallback telephonyCallback2 = new TelephonyCallbackWrapper() {
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfoNotify) {
@@ -1698,4 +1763,186 @@
processAllMessages();
assertTrue(mCarrierRoamingNtnEligible);
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnAvailableServicesChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ int[] services = {3, 6};
+ mTelephonyRegistry.notifyCarrierRoamingNtnAvailableServicesChanged(subId, services);
+ processAllMessages();
+ assertTrue(Arrays.equals(mCarrierRoamingNtnAvailableServices, services));
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_PASS_COPIED_CALL_STATE_LIST)
+ public void testNotifyPreciseCallStateChangedInProcess() {
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+
+ final int subId = 1;
+ int[] events = {TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ processAllMessages();
+
+ int[] callState = {0, 5, 0};
+ String[] imsCallId = {"0", "1", "0"};
+ int[] imsServiceType = {0, 1, 0};
+ int[] imsCallType = {0, 1, 0};
+ int[] callState2 = {0, 1, 0};
+ mTelephonyRegistry.notifyPreciseCallState(
+ /*phoneId*/ 0, subId, callState, imsCallId, imsServiceType, imsCallType);
+ mTelephonyRegistry.notifyPreciseCallState(
+ /*phoneId*/ 0, subId, callState2, imsCallId, imsServiceType, imsCallType);
+ processAllMessages();
+
+ assertEquals(2, mCallStateList.size());
+ //make sure the call state is from the first report(callState).
+ assertEquals(5, mCallStateList.get(0).getFirst().getCallState());
+ //make sure the call state is from the second report(callState2).
+ assertEquals(1, mCallStateList.get(1).getFirst().getCallState());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public void testNotifyCarrierRoamingNtnSignalStrengthChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_SIGNAL_STRENGTH_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ mTelephonyRegistry.notifyCarrierRoamingNtnSignalStrengthChanged(subId,
+ new NtnSignalStrength(NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD));
+ processAllMessages();
+ assertEquals(mCarrierRoamingNtnSignalStrength.getLevel(),
+ NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_onRegistration_getNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ processAllMessages();
+
+ // verify latest state is immediately available on registration
+ assertTrue(mIsSatelliteEnabled);
+ } finally {
+ // Clean up
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_duringRegistration_getNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+
+ // Satellite enabled state changed
+ mTelephonyRegistry.notifySatelliteStateChanged(false);
+ processAllMessages();
+ // We can receive the new state
+ assertFalse(mIsSatelliteEnabled);
+ } finally {
+ // Clean up
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_SATELLITE_STATE_CHANGE_LISTENER)
+ public void testNotifySatelliteStateChanged_removeRegistration_notNotified() {
+ MySatelliteStateChangeListener listener = new MySatelliteStateChangeListener();
+ // Set initial satellite enabled state to true
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+
+ try {
+ // Start monitoring
+ mTelephonyRegistry.addSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ mTelephonyRegistry.notifySatelliteStateChanged(false);
+ } finally {
+ // Stop monitoring from now on
+ mTelephonyRegistry.removeSatelliteStateChangeListener(listener,
+ mContext.getOpPackageName());
+ }
+
+ // Satellite enabled state changed again
+ mTelephonyRegistry.notifySatelliteStateChanged(true);
+ processAllMessages();
+ // We should not receive the new state change after monitoring end
+ assertFalse(mIsSatelliteEnabled);
+ }
+
+
+ @Test
+ @EnableFlags(Flags.FLAG_SECURITY_ALGORITHMS_UPDATE_INDICATIONS)
+ public void testNotifySecurityAlgorithmsChanged() {
+ int subId = 1;
+ int[] events = {TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+
+ SecurityAlgorithmUpdate update =
+ new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ int invocationCount = mTelephonyCallback.invocationCount.get();
+ mTelephonyRegistry.notifySecurityAlgorithmsChanged(0, 1, update);
+ processAllMessages();
+ assertEquals(invocationCount + 1, mTelephonyCallback.invocationCount.get());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS)
+ public void testNotifyCellularIdentifierDisclosedChanged() {
+ int subId = 1;
+ int[] events = {TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED};
+
+ CellularIdentifierDisclosure disclosure =
+ new CellularIdentifierDisclosure(NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+ CELLULAR_IDENTIFIER_IMSI,
+ "001001",
+ false);
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ int invocationCount = mTelephonyCallback.invocationCount.get();
+ mTelephonyRegistry.notifyCellularIdentifierDisclosedChanged(0, 1,
+ disclosure);
+ processAllMessages();
+ assertEquals(invocationCount + 1, mTelephonyCallback.invocationCount.get());
+ }
+
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index d80c9a2..0db881c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -747,6 +747,8 @@
doReturn(mDataRetryManager).when(mDataNetworkController).getDataRetryManager();
doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
doReturn(0).when(mPhone).getPhoneId();
+ doReturn(true).when(mPhone).hasCalling();
+ doReturn(true).when(mPhone2).hasCalling();
//mUiccController
doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(anyInt(),
@@ -809,7 +811,7 @@
doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
.getRilDataRadioTechnology();
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
doReturn(mPhone).when(mCT).getPhone();
doReturn(mImsEcbm).when(mImsManager).getEcbmInterface();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
index 0e2676e..d3f3050 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
@@ -101,9 +101,11 @@
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
mGoodTelephonyDisplayInfo = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false /*roaming*/);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false /*roaming*/,
+ false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/);
mBadTelephonyDisplayInfo = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UMTS,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false /*roaming*/);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false /*roaming*/,
+ false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/);
mMockedPhoneSwitcherCallback =
mock(AutoDataSwitchController.AutoDataSwitchControllerCallback.class);
mMockedAlarmManager = mock(AlarmManager.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 95cefd8..88dce51 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
@@ -126,20 +126,23 @@
doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(signalStrength).getLevel();
assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false/*isRoaming*/),
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false/*isRoaming*/,
+ false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
signalStrength)).isEqualTo(10227);
// Verify if entry contains any invalid negative scores, should yield 0.
doReturn(SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN).when(signalStrength).getLevel();
assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_LTE,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/),
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/,
+ false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
signalStrength))
.isEqualTo(0/*OUT_OF_SERVICE_AUTO_DATA_SWITCH_SCORE*/);
// Verify non-existent entry should yield -1
doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(signalStrength).getLevel();
assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_EDGE,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/),
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/,
+ false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
signalStrength))
.isEqualTo(0/*OUT_OF_SERVICE_AUTO_DATA_SWITCH_SCORE*/);
}
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 ee713c6..fad1d93 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -888,11 +888,8 @@
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn(new SubscriptionInfoInternal.Builder().setId(1).build())
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
-
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
doReturn(true).when(mFeatureFlags).satelliteInternet();
- doReturn(true).when(mFeatureFlags).simDisabledGracefulTearDown();
-
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
@@ -1991,6 +1988,194 @@
}
@Test
+ public void testIgnoreDataRoamingSettingForSatellite() throws Exception {
+ // set up satellite network and register data roaming
+ mIsNonTerrestrialNetwork = true;
+ doReturn(true).when(mServiceState).getDataRoaming();
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+ // Enable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+ // Set network request transport with Internet capability
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(true,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET,
+ NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED));
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Disable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+ processAllMessages();
+
+ // Verify internet is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Setup carrier to bypass data roaming off setting for satellite network
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+ carrierConfigChanged();
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // reset satellite network and roaming registration
+ mIsNonTerrestrialNetwork = false;
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ }
+
+ @Test
+ public void testIgnoreDataRoamingSettingForSatelliteWithBandwithConstrained() throws Exception {
+ // set up satellite network and register data roaming
+ mIsNonTerrestrialNetwork = true;
+ doReturn(true).when(mServiceState).getDataRoaming();
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+ // Enable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+ // Set network request transport with Internet capability
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Disable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+ processAllMessages();
+
+ // Verify internet is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Setup carrier to bypass data roaming off setting for satellite network
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+ carrierConfigChanged();
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // reset satellite network and roaming registration
+ mIsNonTerrestrialNetwork = false;
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ }
+
+ @Test
+ public void testIgnoreDataRoamingSettingForSatelliteForUnrestrictedNetwork() throws Exception {
+ // set up satellite network and register data roaming
+ mIsNonTerrestrialNetwork = true;
+ doReturn(true).when(mServiceState).getDataRoaming();
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+ // Disable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+
+ // Set network request transport with Internet capability
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+
+ // Verify internet is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Setup carrier to bypass data roaming off setting for satellite network
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+ carrierConfigChanged();
+ processAllMessages();
+
+ // Verify internet is still not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Setup satellite data support mode serve all network requests
+ mCarrierConfig.putInt(
+ CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+ CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL);
+ carrierConfigChanged();
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // reset satellite network and roaming registration
+ mIsNonTerrestrialNetwork = false;
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ }
+
+ @Test
+ public void testIgnoreDataRoamingSettingForSatelliteConfigForTerrestialNetwork() throws Exception {
+ // set up terrestrial network and roaming registration
+ mIsNonTerrestrialNetwork = false;
+ doReturn(true).when(mServiceState).getDataRoaming();
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+ // Enable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+ // Set network request transport with Internet capability
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+
+ // Verify internet is connected
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Disable data roaming setting
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+ processAllMessages();
+
+ // Verify internet is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Setup carrier to bypass data roaming off setting for satellite network
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+ carrierConfigChanged();
+ processAllMessages();
+
+ // Verify internet is still not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // Enable data roaming again
+ mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+ processAllMessages();
+
+ // Verify internet is connected again
+ verifyInternetConnected();
+ Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+ // reset roaming registration
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ }
+
+ @Test
public void testDataEnabledChanged() throws Exception {
mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
@@ -2481,7 +2666,7 @@
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
@@ -2524,7 +2709,7 @@
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
@@ -2580,7 +2765,7 @@
// Change data network type to NR
doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
.when(mDisplayInfoController).getTelephonyDisplayInfo();
dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
processAllMessages();
@@ -4311,7 +4496,7 @@
}
@Test
- public void testImsGracefulTearDownSimRemoval() throws Exception {
+ public void testImsGracefulTearDown() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
@@ -4357,52 +4542,6 @@
}
@Test
- public void testImsGracefulTearDownSimDisabled() throws Exception {
- setImsRegistered(true);
- setRcsRegistered(true);
-
- NetworkCapabilities netCaps = new NetworkCapabilities();
- netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
- netCaps.maybeMarkCapabilitiesRestricted();
- netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
-
- NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
- ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
- TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone, mFeatureFlags);
-
- mDataNetworkControllerUT.addNetworkRequest(networkRequest);
-
- processAllMessages();
- Mockito.clearInvocations(mPhone);
-
- // SIM disabled
- mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
- TelephonyManager.SIM_STATE_NOT_READY, 0).sendToTarget();
- processAllMessages();
-
- // Make sure data network enters disconnecting state
- ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
- ArgumentCaptor.forClass(PreciseDataConnectionState.class);
- verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
- PreciseDataConnectionState pdcs = pdcsCaptor.getValue();
- assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING);
-
- // IMS de-registered. Now data network is safe to be torn down.
- Mockito.clearInvocations(mPhone);
- setImsRegistered(false);
- setRcsRegistered(false);
- processAllMessages();
-
- // All data should be disconnected.
- verifyAllDataDisconnected();
- verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
- verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
- pdcs = pdcsCaptor.getValue();
- assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
- }
-
- @Test
public void testNoGracefulTearDownForEmergencyDataNetwork() throws Exception {
setImsRegistered(true);
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 f7990b9..6e41448 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -146,7 +146,7 @@
private AutoDataSwitchController.AutoDataSwitchControllerCallback mAutoDataSwitchCallback;
private TelephonyDisplayInfo mTelephonyDisplayInfo = new TelephonyDisplayInfo(
TelephonyManager.NETWORK_TYPE_NR,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false);
private SubscriptionManagerServiceCallback mSubscriptionManagerServiceCallback;
@Before
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 6694e98..9253fbf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -27,7 +27,6 @@
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WWAN;
-import static com.android.internal.telephony.emergency.EmergencyStateTracker.DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -106,6 +105,7 @@
private static final String TEST_SMS_ID = "1111";
private static final String TEST_SMS_ID_2 = "2222";
private static final int TEST_ECM_EXIT_TIMEOUT_MS = 500;
+ private static final int TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3000;
private static final EmergencyRegistrationResult E_REG_RESULT = new EmergencyRegistrationResult(
EUTRAN, REGISTRATION_STATE_HOME, DOMAIN_CS_PS, true, true, 0, 1, "001", "01", "US");
@@ -139,7 +139,8 @@
EmergencyStateTracker.getInstance();
});
- EmergencyStateTracker.make(mContext, true, mFeatureFlags);
+ EmergencyStateTracker
+ .make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS, mFeatureFlags);
assertNotNull(EmergencyStateTracker.getInstance());
}
@@ -147,7 +148,8 @@
@Test
@SmallTest
public void getInstance_returnsSameInstance() {
- EmergencyStateTracker.make(mContext, true, mFeatureFlags);
+ EmergencyStateTracker
+ .make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS, mFeatureFlags);
EmergencyStateTracker instance1 = EmergencyStateTracker.getInstance();
EmergencyStateTracker instance2 = EmergencyStateTracker.getInstance();
@@ -184,7 +186,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(false), eq(TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// isOkToCall() should return true when IN_SERVICE state
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -243,7 +245,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(false), eq(TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// onTimeout should return true when radion on
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
@@ -270,6 +272,7 @@
@Test
@SmallTest
public void startEmergencyCall_radioOff_turnOnRadioHangupCallTurnOffRadio() {
+ android.telecom.Connection testConnection = new android.telecom.Connection() {};
EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
true /* isSuplDdsSwitchRequiredForEmergencyCall */);
// Create test Phones and set radio off
@@ -285,16 +288,17 @@
.build();
doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(testPhone,
- mTestConnection1, false);
+ testConnection, false);
// startEmergencyCall should trigger radio on
ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
- eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS), eq(false));
+ eq(false), eq(TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// Hangup the call
- emergencyStateTracker.endCall(mTestConnection1);
+ testConnection.setDisconnected(null);
+ emergencyStateTracker.endCall(testConnection);
// onTimeout and isOkToCall should return true even in case radion is off
assertTrue(callback.getValue()
@@ -305,6 +309,7 @@
callback.getValue().onComplete(null, true);
assertFalse(future.isDone());
+ verify(testPhone).setRadioPower(true, false, false, true);
}
/**
@@ -327,7 +332,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(false), eq(TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF);
@@ -363,7 +368,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(false), eq(0));
// isOkToCall() should return true once satellite modem is off
assertFalse(callback.getValue()
.isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
@@ -404,7 +409,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(false), eq(0));
// Verify future completes with DisconnectCause.POWER_OFF if radio not ready
CompletableFuture<Void> unused = future.thenAccept((result) -> {
assertEquals((Integer) result, (Integer) DisconnectCause.SATELLITE_ENABLED);
@@ -432,7 +437,7 @@
// Radio already on so shouldn't trigger this
verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
- anyBoolean(), eq(0), eq(false));
+ anyBoolean(), eq(0));
// Carrier supports control-plane fallback, so no DDS switch
verify(mPhoneSwitcher, never()).overrideDefaultDataForEmergency(anyInt(), anyInt(), any());
}
@@ -1104,7 +1109,7 @@
verify(phone0, never()).exitEmergencyMode(any(Message.class));
verify(phone0, times(2)).startEmergencyCallbackMode(
eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
- verify(phone0, never()).stopEmergencyCallbackMode(
+ verify(phone0, times(1)).stopEmergencyCallbackMode(
eq(EMERGENCY_CALLBACK_MODE_CALL), anyInt());
}
@@ -3198,7 +3203,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), eq(false));
+ anyBoolean(), eq(0));
}
/**
@@ -3408,8 +3413,9 @@
doNothing().when(mPhoneSwitcher).overrideDefaultDataForEmergency(
anyInt(), anyInt(), any());
return new EmergencyStateTracker(mContext, mTestableLooper.getLooper(),
- isSuplDdsSwitchRequiredForEmergencyCall, mPhoneFactoryProxy, mPhoneSwitcherProxy,
- mTelephonyManagerProxy, mRadioOnHelper, TEST_ECM_EXIT_TIMEOUT_MS, mFeatureFlags);
+ isSuplDdsSwitchRequiredForEmergencyCall, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS,
+ mPhoneFactoryProxy, mPhoneSwitcherProxy, mTelephonyManagerProxy, mRadioOnHelper,
+ TEST_ECM_EXIT_TIMEOUT_MS, mFeatureFlags);
}
private Phone setupTestPhoneForEmergencyCall(boolean isRoaming, boolean isRadioOn) {
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 639a2a3..a29de0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -70,6 +70,7 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TelephonyTestUtils;
import com.android.internal.telephony.TestApplication;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.uicc.IsimUiccRecords;
@@ -377,23 +378,35 @@
any(ICarrierMessagingCallback.class));
}
- @Test
- @SmallTest
- @Ignore("b/256282780")
- public void testSendSmsByCarrierApp() throws Exception {
+ private int sendSmsWithCarrierAppResponse(int carrierAppResultCode) throws Exception {
mockCarrierApp();
- mockCarrierAppStubResults(CarrierMessagingService.SEND_STATUS_OK,
- mICarrierAppMessagingService, true);
+ mockCarrierAppStubResults(carrierAppResultCode, mICarrierAppMessagingService, true);
registerTestIntentReceiver();
- PendingIntent pendingIntent = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0,
- new Intent(TEST_INTENT)
- .setPackage(TestApplication.getAppContext().getPackageName()),
- PendingIntent.FLAG_MUTABLE);
+ PendingIntent pendingIntent =
+ PendingIntent.getBroadcast(
+ TestApplication.getAppContext(),
+ 0,
+ new Intent(TEST_INTENT)
+ .setPackage(TestApplication.getAppContext().getPackageName()),
+ PendingIntent.FLAG_MUTABLE);
mReceivedTestIntent = false;
- mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
- pendingIntent, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
+ mGsmSmsDispatcher.sendText(
+ "6501002000",
+ "121" /*scAddr*/,
+ "test sms",
+ pendingIntent,
+ null,
+ null,
+ null,
+ mCallingUserId,
+ false,
+ -1,
+ false,
+ -1,
+ false,
+ 0L);
processAllMessages();
synchronized (mLock) {
if (!mReceivedTestIntent) {
@@ -402,15 +415,48 @@
}
assertEquals(true, mReceivedTestIntent);
int resultCode = mTestReceiver.getResultCode();
- assertTrue("Unexpected result code: " + resultCode,
- resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK);
- verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(),
- any(Message.class));
+ verify(mSimulatedCommandsVerifier, times(0))
+ .sendSMS(anyString(), anyString(), any(Message.class));
+ return resultCode;
}
}
@Test
@SmallTest
+ @Ignore("b/256282780")
+ public void testSendSmsByCarrierApp() throws Exception {
+ int resultCode = sendSmsWithCarrierAppResponse(CarrierMessagingService.SEND_STATUS_OK);
+ assertTrue(
+ "Unexpected result code: " + resultCode,
+ resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK);
+ }
+
+ @Test
+ @SmallTest
+ public void testSendSmsByCarrierApp_PermanentFailure() throws Exception {
+ int resultCode = sendSmsWithCarrierAppResponse(CarrierMessagingService.SEND_STATUS_ERROR);
+ assertTrue(
+ "Unexpected result code: " + resultCode,
+ resultCode == SmsManager.RESULT_RIL_GENERIC_ERROR);
+ }
+
+ @Test
+ @SmallTest
+ public void testSendSmsByCarrierApp_FailureWithReason() throws Exception {
+ if (!Flags.temporaryFailuresInCarrierMessagingService()) {
+ return;
+ }
+ doReturn(true).when(mFeatureFlags).temporaryFailuresInCarrierMessagingService();
+ int resultCode =
+ sendSmsWithCarrierAppResponse(
+ CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE);
+ assertTrue(
+ "Unexpected result code: " + resultCode,
+ resultCode == SmsManager.RESULT_ERROR_NO_SERVICE);
+ }
+
+ @Test
+ @SmallTest
public void testSendSmsByCarrierAppNoResponse() throws Exception {
mockCarrierApp();
// do not mock result, instead reduce the timeout for test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 4abf33f..130fba8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -46,6 +47,7 @@
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyManager;
@@ -69,8 +71,10 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.stubbing.Answer;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -95,13 +99,14 @@
"TestCarrier2Pkg", "Carrier2ImsService");
private static final int NUM_MAX_SLOTS = 2;
- private static final String TAG = ImsResolverTest.class.getSimpleName();
+ private static final UserHandle TEST_USER_HANDLE = UserHandle.of(Integer.MAX_VALUE);
// Mocked classes
Context mMockContext;
PackageManager mMockPM;
ImsResolver.SubscriptionManagerProxy mTestSubscriptionManagerProxy;
ImsResolver.TelephonyManagerProxy mTestTelephonyManagerProxy;
+ ImsResolver.ActivityManagerProxy mTestActivityManagerProxy;
CarrierConfigManager mMockCarrierConfigManager;
UserManager mMockUserManager;
ImsResolver.ImsDynamicQueryManagerFactory mMockQueryManagerFactory;
@@ -112,6 +117,7 @@
private BroadcastReceiver mTestPackageBroadcastReceiver;
private BroadcastReceiver mTestCarrierConfigReceiver;
private BroadcastReceiver mTestBootCompleteReceiver;
+ private BroadcastReceiver mTestUserChangedReceiver;
private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener;
private PersistableBundle[] mCarrierConfigs;
private FeatureFlags mFeatureFlags;
@@ -124,12 +130,14 @@
mMockPM = mock(PackageManager.class);
mTestSubscriptionManagerProxy = mock(ImsResolver.SubscriptionManagerProxy.class);
mTestTelephonyManagerProxy = mock(ImsResolver.TelephonyManagerProxy.class);
+ mTestActivityManagerProxy = mock(ImsResolver.ActivityManagerProxy.class);
mMockCarrierConfigManager = mock(CarrierConfigManager.class);
mMockUserManager = mock(UserManager.class);
mMockQueryManagerFactory = mock(ImsResolver.ImsDynamicQueryManagerFactory.class);
mMockQueryManager = mock(ImsServiceFeatureQueryManager.class);
mMockRepo = mock(ImsFeatureBinderRepository.class);
mFeatureFlags = mock(FeatureFlags.class);
+ when(mFeatureFlags.imsResolverUserAware()).thenReturn(true);
}
@After
@@ -411,7 +419,7 @@
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(features), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(features), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
SparseIntArray compareMap = new SparseIntArray();
compareMap.put(0, 0);
@@ -469,11 +477,14 @@
when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, featuresAll, 1);
- verify(deviceController).bind(eq(featuresDevice), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(featuresDevice),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
- verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
+ verify(carrierController1).bind(eq(mContext.getUser()), eq(featuresMmTel),
+ any(SparseIntArray.class));
verify(carrierController1, never()).unbind();
- verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(featuresRcs),
+ any(SparseIntArray.class));
verify(carrierController2, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
@@ -521,11 +532,14 @@
when(mMockQueryManager.isQueryInProgress()).thenReturn(false);
setupDynamicQueryFeatures(TEST_CARRIER_2_DEFAULT_NAME, allFeatures, 1);
- verify(deviceController, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
- verify(carrierController1).bind(eq(featuresMmTel), any(SparseIntArray.class));
+ verify(carrierController1).bind(eq(mContext.getUser()), eq(featuresMmTel),
+ any(SparseIntArray.class));
verify(carrierController1, never()).unbind();
- verify(carrierController2).bind(eq(featuresRcs), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(featuresRcs),
+ any(SparseIntArray.class));
verify(carrierController2, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController1.getComponentName());
assertEquals(TEST_CARRIER_2_DEFAULT_NAME, carrierController2.getComponentName());
@@ -553,7 +567,7 @@
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
}
@@ -582,7 +596,7 @@
// We will not bind with FEATURE_EMERGENCY_MMTEL
features.remove(new ImsFeatureConfiguration.FeatureSlotPair(0,
ImsFeature.FEATURE_EMERGENCY_MMTEL));
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
}
@@ -606,20 +620,23 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
// Bind using default features
startBindNoCarrierConfig(1);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
convertToHashSet(featuresController1, 0);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(featuresController2, 0);
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
// simulate ImsServiceController binding and setup
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_EMERGENCY_MMTEL,
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_EMERGENCY_MMTEL,
deviceController1);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController1);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, deviceController2);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_MMTEL,
+ deviceController1);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_RCS, deviceController2);
mTestImsResolver.enableIms(0 /*slotId*/);
// Verify enableIms is only called once per controller.
@@ -651,7 +668,7 @@
// Bind without emergency calling
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, features, 1);
- verify(controller).bind(eq(features), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(features), any(SparseIntArray.class));
verify(controller, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, controller.getComponentName());
@@ -686,8 +703,8 @@
startBindCarrierConfigAlreadySet();
processAllMessages();
- verify(mMockQueryManager, never()).startQuery(any(), any());
- verify(controller, never()).bind(any(), any(SparseIntArray.class));
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
+ verify(controller, never()).bind(any(), any(), any(SparseIntArray.class));
verify(controller, never()).unbind();
}
@@ -719,7 +736,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
SparseIntArray compareMap = new SparseIntArray();
compareMap.put(0, 0);
@@ -729,7 +746,7 @@
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
}
@@ -763,7 +780,7 @@
featureSet.addAll(convertToHashSet(features, 1));
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
assertEquals(slotIdToSubIdMap.size(), 2);
SparseIntArray compareMap = new SparseIntArray();
@@ -774,7 +791,7 @@
assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
// Change number of SIMs and verify the features in the ImsServiceController are changed
@@ -823,7 +840,7 @@
ArgumentCaptor<SparseIntArray> arrayCaptor =
ArgumentCaptor.forClass(SparseIntArray.class);
- verify(controller).bind(eq(featureSet), arrayCaptor.capture());
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), arrayCaptor.capture());
SparseIntArray slotIdToSubIdMap = arrayCaptor.getValue();
assertEquals(slotIdToSubIdMap.size(), 1);
SparseIntArray compareMap = new SparseIntArray();
@@ -833,7 +850,7 @@
assertEquals(slotIdToSubIdMap.get(i), compareMap.get(i));
}
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
// Change number of SIMs and verify the features in the ImsServiceController are changed
@@ -895,17 +912,19 @@
processAllMessages();
// ensure that startQuery was called
verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE_DEFAULT_NAME),
- any(String.class));
+ any(UserHandle.class), any(String.class));
verify(mMockQueryManager, times(1)).startQuery(eq(TEST_DEVICE2_DEFAULT_NAME),
- any(String.class));
+ any(UserHandle.class), any(String.class));
mDynamicQueryListener.onComplete(TEST_DEVICE_DEFAULT_NAME, deviceFeatures1);
mDynamicQueryListener.onComplete(TEST_DEVICE2_DEFAULT_NAME, deviceFeatures2);
processAllMessages();
- verify(deviceController, times(2)).bind(eq(deviceFeatures1), any(SparseIntArray.class));
- verify(deviceController2, times(1)).bind(eq(deviceFeatures2), any(SparseIntArray.class));
+ verify(deviceController, times(2)).bind(eq(mContext.getUser()), eq(deviceFeatures1),
+ any(SparseIntArray.class));
+ verify(deviceController2, times(1)).bind(eq(mContext.getUser()), eq(deviceFeatures2),
+ any(SparseIntArray.class));
}
/**
@@ -942,7 +961,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -950,7 +970,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1006,7 +1027,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1015,7 +1037,8 @@
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 1));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1062,9 +1085,9 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet = convertToHashSet(features, 0);
// There is no carrier override set, so make sure that the ImsServiceController binds
// to all SIMs.
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
verify(controller, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, controller.getComponentName());
}
@@ -1100,7 +1123,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1108,7 +1132,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
}
@@ -1127,11 +1152,11 @@
// Callback from mock ImsServiceControllers
// All features on slot 1 should be the device default
- mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_MMTEL, deviceController);
- mTestImsResolver.imsServiceFeatureCreated(1, ImsFeature.FEATURE_RCS, deviceController);
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_MMTEL, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(1, 1, ImsFeature.FEATURE_MMTEL, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(1, 1, ImsFeature.FEATURE_RCS, deviceController);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_MMTEL, deviceController);
// The carrier override contains this feature
- mTestImsResolver.imsServiceFeatureCreated(0, ImsFeature.FEATURE_RCS, carrierController);
+ mTestImsResolver.imsServiceFeatureCreated(0, 0, ImsFeature.FEATURE_RCS, carrierController);
}
/**
@@ -1155,7 +1180,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
convertToHashSet(features, 0);
featureSet.addAll(convertToHashSet(features, 1));
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
// add RCS to features list
Set<String> newFeatures = new HashSet<>(features);
@@ -1191,7 +1216,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
// Bind using default features
startBindNoCarrierConfig(2);
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet1 =
@@ -1200,8 +1225,10 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(featuresController2, 0);
featureSet2.addAll(convertToHashSet(featuresController2, 1));
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
// add RCS to features list for device 1
Set<String> newFeatures1 = new HashSet<>(featuresController1);
@@ -1239,7 +1266,7 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet =
convertToHashSet(features, 0);
featureSet.addAll(convertToHashSet(features, 1));
- verify(controller).bind(eq(featureSet), any(SparseIntArray.class));
+ verify(controller).bind(eq(mContext.getUser()), eq(featureSet), any(SparseIntArray.class));
// add RCS to features list
Set<String> newFeatures = new HashSet<>(features);
@@ -1288,7 +1315,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1297,7 +1325,8 @@
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1356,13 +1385,13 @@
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
ImsServiceController carrierController = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, carrierController,
- null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, carrierController);
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1370,13 +1399,16 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet1 =
convertToHashSet(deviceFeatures1, 1);
deviceFeatureSet1.removeAll(carrierFeatures);
- verify(deviceController1).bind(eq(deviceFeatureSet1), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(deviceFeatureSet1),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet2 =
convertToHashSet(deviceFeatures2, 0);
deviceFeatureSet2.addAll(convertToHashSet(deviceFeatures2, 1));
+ deviceFeatureSet2.addAll(convertToHashSet(deviceFeatures2, 1));
deviceFeatureSet2.removeAll(carrierFeatures);
- verify(deviceController2).bind(eq(deviceFeatureSet2), any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(deviceFeatureSet2),
+ any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
@@ -1392,7 +1424,7 @@
verify(carrierController).changeImsServiceFeatures(eq(carrierFeatures),
any(SparseIntArray.class));
deviceFeatureSet1.removeAll(carrierFeatures);
- verify(deviceController1, times(2)).changeImsServiceFeatures(eq(deviceFeatureSet1),
+ verify(deviceController1).changeImsServiceFeatures(eq(deviceFeatureSet1),
any(SparseIntArray.class));
deviceFeatureSet2.removeAll(carrierFeatures);
verify(deviceController2).changeImsServiceFeatures(eq(deviceFeatureSet2),
@@ -1429,7 +1461,8 @@
startBindCarrierConfigAlreadySet();
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
assertEquals(TEST_CARRIER_DEFAULT_NAME, carrierController.getComponentName());
// Verify that all features that are not defined in the carrier override are bound in the
@@ -1438,7 +1471,8 @@
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
@@ -1497,14 +1531,20 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
// device features change
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 1);
deviceFeatureSet.addAll(convertToHashSet(deviceFeatures, 0));
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
- any(SparseIntArray.class));
+ if (mFeatureFlags.imsResolverUserAware()) {
+ verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ } else {
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ }
}
/**
@@ -1644,7 +1684,8 @@
assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
TEST_CARRIER_DEFAULT_NAME.getPackageName()));
// Verify that carrier 2 is bound
- verify(carrierController2).bind(eq(carrierFeatures2), any(SparseIntArray.class));
+ verify(carrierController2).bind(eq(mContext.getUser()), eq(carrierFeatures2),
+ any(SparseIntArray.class));
assertNotNull(mTestImsResolver.getImsServiceInfoFromCache(
TEST_CARRIER_2_DEFAULT_NAME.getPackageName()));
// device features change to accommodate for the features carrier 2 lacks
@@ -1692,7 +1733,8 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that all features that have been defined for the carrier override are bound
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
// device features change
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 1);
@@ -1733,13 +1775,15 @@
setupDynamicQueryFeaturesFailure(TEST_CARRIER_DEFAULT_NAME, 1);
// Verify that a bind never occurs for the carrier controller.
- verify(carrierController, never()).bind(any(), any(SparseIntArray.class));
+ verify(carrierController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
// Verify that all features are used to bind to the device ImsService since the carrier
// ImsService failed to bind properly.
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
}
@@ -1774,18 +1818,21 @@
setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
// Verify that a bind never occurs for the carrier controller.
- verify(carrierController).bind(eq(carrierFeatures), any(SparseIntArray.class));
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
verify(carrierController, never()).unbind();
// Verify that all features that are not defined in the carrier override are bound in the
// device controller (including emergency voice for slot 0)
HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
convertToHashSet(deviceFeatures, 0);
deviceFeatureSet.removeAll(carrierFeatures);
- verify(deviceController).bind(eq(deviceFeatureSet), any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
verify(deviceController, never()).unbind();
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController.getComponentName());
- mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME);
+ mTestImsResolver.imsServiceBindPermanentError(TEST_CARRIER_DEFAULT_NAME,
+ mContext.getUser());
processAllMessages();
verify(carrierController).unbind();
// Verify that the device ImsService features are changed to include the ones previously
@@ -1815,7 +1862,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1825,11 +1872,12 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
convertToHashSet(featureResult, 0);
featureResultSet.addAll(convertToHashSet(featureResult, 1));
- verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureResultSet),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
}
@@ -1852,7 +1900,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1862,11 +1910,12 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureResultSet =
convertToHashSet(featureResult, 0);
featureResultSet.addAll(convertToHashSet(featureResult, 1));
- verify(deviceController1).bind(eq(featureResultSet), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureResultSet),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
}
@@ -1893,7 +1942,7 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
@@ -1904,11 +1953,13 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> featureSet2 =
convertToHashSet(features2, 0);
featureSet2.addAll(convertToHashSet(features2, 1));
- verify(deviceController1).bind(eq(featureSet1), any(SparseIntArray.class));
+ verify(deviceController1).bind(eq(mContext.getUser()), eq(featureSet1),
+ any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2).bind(eq(featureSet2), any(SparseIntArray.class));
+ verify(deviceController2).bind(eq(mContext.getUser()), eq(featureSet2),
+ any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
assertEquals(TEST_DEVICE_DEFAULT_NAME, deviceController1.getComponentName());
assertEquals(TEST_DEVICE2_DEFAULT_NAME, deviceController2.getComponentName());
}
@@ -1934,16 +1985,134 @@
setupPackageQuery(info);
ImsServiceController deviceController1 = mock(ImsServiceController.class);
ImsServiceController deviceController2 = mock(ImsServiceController.class);
- setImsServiceControllerFactory(deviceController1, deviceController2, null, null);
+ setImsServiceControllerDDCFactory(deviceController1, deviceController2, null);
startBindNoCarrierConfig(1);
processAllMessages();
- verify(deviceController1, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController1, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController1, never()).unbind();
- verify(deviceController2, never()).bind(any(), any(SparseIntArray.class));
+ verify(deviceController2, never()).bind(any(), any(), any(SparseIntArray.class));
verify(deviceController2, never()).unbind();
- verify(mMockQueryManager, never()).startQuery(any(), any());
+ verify(mMockQueryManager, never()).startQuery(any(), any(), any());
+ }
+
+ /**
+ * Change the current active user while having ImsServices in system user. The ImsService config
+ * should not change.
+ */
+ @Test
+ @SmallTest
+ public void testChangeCurrentUserServicesInSystem() throws RemoteException {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return;
+ }
+ setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
+ TEST_DEVICE_DEFAULT_NAME.getPackageName());
+ List<ResolveInfo> info = new ArrayList<>();
+ Set<String> deviceFeatures = new HashSet<>();
+ deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
+ deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
+ // Set the carrier override package for slot 0
+ setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
+ // Carrier service doesn't support the voice feature.
+ carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
+ info.add(getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true));
+ info.add(getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true));
+ // Use device default package, which will load the ImsService that the device provides
+ setupPackageQuery(info);
+
+ ImsServiceController deviceController = mock(ImsServiceController.class);
+ ImsServiceController carrierController = mock(ImsServiceController.class);
+ setImsServiceControllerFactory(deviceController, carrierController);
+
+ startBindCarrierConfigAlreadySet();
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
+
+ // Perform a user switch
+ userChanged(TEST_USER_HANDLE);
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 2);
+
+
+ // Verify that all features that have been defined for the device/carrier override are bound
+ // and are not changed when the user changes.
+ verify(carrierController).bind(eq(mContext.getUser()), eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, atLeastOnce()).changeImsServiceFeatures(eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).unbind();
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
+ convertToHashSet(deviceFeatures, 0);
+ deviceFeatureSet.removeAll(carrierFeatures);
+ verify(deviceController).bind(eq(mContext.getUser()), eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, atLeastOnce()).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, never()).unbind();
+ }
+
+ /**
+ * Change the current active user while having a carrier ImsService installed for second user.
+ * The features should change when the current user changes to the second user and back.
+ */
+ @Test
+ @SmallTest
+ public void testChangeCurrentUserCarrierInSecondUser() throws RemoteException {
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ return;
+ }
+ setupResolver(1 /*numSlots*/, TEST_DEVICE_DEFAULT_NAME.getPackageName(),
+ TEST_DEVICE_DEFAULT_NAME.getPackageName());
+ Set<String> deviceFeatures = new HashSet<>();
+ deviceFeatures.add(ImsResolver.METADATA_MMTEL_FEATURE);
+ deviceFeatures.add(ImsResolver.METADATA_RCS_FEATURE);
+ // Set the carrier override package for slot 0
+ setConfigCarrierStringMmTelRcs(0, TEST_CARRIER_DEFAULT_NAME.getPackageName());
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> carrierFeatures = new HashSet<>();
+ // Carrier service doesn't support the voice feature.
+ carrierFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(0, ImsFeature.FEATURE_RCS));
+ // Use device default package, which will load the ImsService that the device provides
+ setupPackageQuery(Collections.singletonList(
+ getResolveInfo(TEST_DEVICE_DEFAULT_NAME, deviceFeatures, true)));
+ setupPackageQueryForUser(Collections.singletonList(
+ getResolveInfo(TEST_CARRIER_DEFAULT_NAME, new HashSet<>(), true)),
+ TEST_USER_HANDLE);
+
+ ImsServiceController deviceController = mock(ImsServiceController.class);
+ ImsServiceController carrierController = mock(ImsServiceController.class);
+ setImsServiceControllerFactory(deviceController, carrierController);
+
+ startBindCarrierConfigAlreadySet();
+
+ verify(carrierController, never()).bind(eq(mContext.getUser()), any(),
+ any(SparseIntArray.class));
+ verify(deviceController).bind(eq(mContext.getUser()),
+ eq(convertToHashSet(deviceFeatures, 0)), any(SparseIntArray.class));
+
+ // Perform a user switch
+ setBoundImsServiceControllerUser(carrierController, TEST_USER_HANDLE);
+ userChanged(TEST_USER_HANDLE);
+ setupDynamicQueryFeatures(TEST_CARRIER_DEFAULT_NAME, carrierFeatures, 1);
+
+
+ // Verify the carrier controller was bound only when the user changed
+ verify(carrierController).bind(eq(TEST_USER_HANDLE), eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).changeImsServiceFeatures(eq(carrierFeatures),
+ any(SparseIntArray.class));
+ verify(carrierController, never()).unbind();
+
+ HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatureSet =
+ convertToHashSet(deviceFeatures, 0);
+ deviceFeatureSet.removeAll(carrierFeatures);
+ verify(deviceController).changeImsServiceFeatures(eq(deviceFeatureSet),
+ any(SparseIntArray.class));
+ verify(deviceController, never()).unbind();
+ }
+
+ private void setCurrentUser(UserHandle handle) {
+ when(mTestActivityManagerProxy.getCurrentUser()).thenReturn(handle);
}
private void setupResolver(int numSlots, String deviceMmTelPkgName,
@@ -1970,12 +2139,15 @@
when(mTestTelephonyManagerProxy.getSimState(any(Context.class), eq(i))).thenReturn(
TelephonyManager.SIM_STATE_READY);
}
+ when(mMockContext.getUser()).thenReturn(mContext.getUser());
+ when(mTestActivityManagerProxy.getCurrentUser()).thenReturn(mContext.getUser());
mTestImsResolver = new ImsResolver(mMockContext, deviceMmTelPkgName, deviceRcsPkgName,
numSlots, mMockRepo, Looper.myLooper(), mFeatureFlags);
mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
+ mTestImsResolver.setActivityManagerProxy(mTestActivityManagerProxy);
when(mMockQueryManagerFactory.create(any(Context.class),
any(ImsServiceFeatureQueryManager.Listener.class))).thenReturn(mMockQueryManager);
mTestImsResolver.setImsDynamicQueryManagerFactory(mMockQueryManagerFactory);
@@ -1983,24 +2155,55 @@
}
private void setupPackageQuery(List<ResolveInfo> infos) {
- // Only return info if not using the compat argument
- when(mMockPM.queryIntentServicesAsUser(
+ doAnswer((Answer<List<ResolveInfo>>) invocation -> {
+ Intent intent = (Intent) invocation.getArguments()[0];
+ String pkg = intent.getPackage();
+ if (pkg == null) {
+ return infos;
+ } else {
+ for (ResolveInfo info : infos) {
+ if (pkg.equals(info.serviceInfo.packageName)) {
+ return Collections.singletonList(info);
+ }
+ }
+ }
+ return Collections.emptyList();
+ }).when(mMockPM).queryIntentServicesAsUser(
+ // Only return info if not using the compat argument
argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
- anyInt(), any())).thenReturn(infos);
+ anyInt(), any());
+ }
+
+ private void setupPackageQueryForUser(List<ResolveInfo> infos, UserHandle user) {
+ doAnswer((Answer<List<ResolveInfo>>) invocation -> {
+ Intent intent = (Intent) invocation.getArguments()[0];
+ String pkg = intent.getPackage();
+ if (pkg == null) {
+ return infos;
+ } else {
+ for (ResolveInfo info : infos) {
+ if (pkg.equals(info.serviceInfo.packageName)) {
+ return Collections.singletonList(info);
+ }
+ }
+ }
+ return Collections.emptyList();
+ }).when(mMockPM).queryIntentServicesAsUser(
+ // Only return info if not using the compat argument
+ argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
+ anyInt(), eq(user));
}
private void setupPackageQuery(ComponentName name, Set<String> features,
boolean isPermissionGranted) {
List<ResolveInfo> info = new ArrayList<>();
info.add(getResolveInfo(name, features, isPermissionGranted));
- // Only return info if not using the compat argument
- when(mMockPM.queryIntentServicesAsUser(
- argThat(argument -> ImsService.SERVICE_INTERFACE.equals(argument.getAction())),
- anyInt(), any())).thenReturn(info);
+ setupPackageQuery(info);
}
private ImsServiceController setupController() {
ImsServiceController controller = mock(ImsServiceController.class);
+ when(controller.getBoundUser()).thenReturn(mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2028,15 +2231,25 @@
processAllMessages();
ArgumentCaptor<BroadcastReceiver> receiversCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
- mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
- mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
- mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ } else {
+ verify(mMockContext, times(4)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestUserChangedReceiver = receiversCaptor.getAllValues().get(1);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(2);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(3);
+
+ }
ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
mDynamicQueryListener = queryManagerCaptor.getValue();
- when(mMockQueryManager.startQuery(any(ComponentName.class), any(String.class)))
+ when(mMockQueryManager.startQuery(any(ComponentName.class), any(UserHandle.class),
+ any(String.class)))
.thenReturn(true);
processAllMessages();
}
@@ -2050,10 +2263,18 @@
processAllMessages();
ArgumentCaptor<BroadcastReceiver> receiversCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
- mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
- mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
- mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ if (!mFeatureFlags.imsResolverUserAware()) {
+ verify(mMockContext, times(3)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(1);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(2);
+ } else {
+ verify(mMockContext, times(4)).registerReceiver(receiversCaptor.capture(), any());
+ mTestPackageBroadcastReceiver = receiversCaptor.getAllValues().get(0);
+ mTestUserChangedReceiver = receiversCaptor.getAllValues().get(1);
+ mTestCarrierConfigReceiver = receiversCaptor.getAllValues().get(2);
+ mTestBootCompleteReceiver = receiversCaptor.getAllValues().get(3);
+ }
ArgumentCaptor<ImsServiceFeatureQueryManager.Listener> queryManagerCaptor =
ArgumentCaptor.forClass(ImsServiceFeatureQueryManager.Listener.class);
verify(mMockQueryManagerFactory).create(any(Context.class), queryManagerCaptor.capture());
@@ -2069,7 +2290,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
processAllMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
mDynamicQueryListener.onComplete(name, features);
processAllMessages();
}
@@ -2078,7 +2300,8 @@
HashSet<ImsFeatureConfiguration.FeatureSlotPair> features, int times) {
processAllFutureMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
mDynamicQueryListener.onComplete(name, features);
processAllMessages();
}
@@ -2086,8 +2309,19 @@
private void setupDynamicQueryFeaturesFailure(ComponentName name, int times) {
processAllMessages();
// ensure that startQuery was called
- verify(mMockQueryManager, times(times)).startQuery(eq(name), any(String.class));
- mDynamicQueryListener.onPermanentError(name);
+ verify(mMockQueryManager, times(times)).startQuery(eq(name), any(UserHandle.class),
+ any(String.class));
+ mDynamicQueryListener.onPermanentError(name, mContext.getUser());
+ processAllMessages();
+ }
+
+ public void userChanged(UserHandle newUser) {
+ setCurrentUser(newUser);
+ // Tell the package manager that a new device feature is installed
+ Intent userSwitchedIntent = new Intent();
+ userSwitchedIntent.setAction(Intent.ACTION_USER_SWITCHED);
+ userSwitchedIntent.putExtra(Intent.EXTRA_USER, newUser);
+ mTestUserChangedReceiver.onReceive(null, userSwitchedIntent);
processAllMessages();
}
@@ -2110,7 +2344,14 @@
processAllMessages();
}
+ private void setBoundImsServiceControllerUser(ImsServiceController controller,
+ UserHandle handle) {
+ when(controller.getBoundUser()).thenReturn(handle);
+ }
+
private void setImsServiceControllerFactory(Map<String, ImsServiceController> controllerMap) {
+ controllerMap.values()
+ .forEach(c -> setBoundImsServiceControllerUser(c, mContext.getUser()));
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2129,6 +2370,8 @@
private void setImsServiceControllerFactory(ImsServiceController deviceController,
ImsServiceController carrierController) {
+ setBoundImsServiceControllerUser(deviceController, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController, mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2156,6 +2399,9 @@
private void setImsServiceControllerFactory(ImsServiceController deviceController,
ImsServiceController carrierController1, ImsServiceController carrierController2) {
+ setBoundImsServiceControllerUser(deviceController, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController1, mContext.getUser());
+ setBoundImsServiceControllerUser(carrierController2, mContext.getUser());
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2185,9 +2431,13 @@
});
}
- private void setImsServiceControllerFactory(ImsServiceController deviceController1,
- ImsServiceController deviceController2, ImsServiceController carrierController1,
- ImsServiceController carrierController2) {
+ private void setImsServiceControllerDDCFactory(ImsServiceController deviceController1,
+ ImsServiceController deviceController2, ImsServiceController carrierController1) {
+ setBoundImsServiceControllerUser(deviceController1, mContext.getUser());
+ setBoundImsServiceControllerUser(deviceController2, mContext.getUser());
+ if (carrierController1 != null) {
+ setBoundImsServiceControllerUser(carrierController1, mContext.getUser());
+ }
mTestImsResolver.setImsServiceControllerFactory(
new ImsResolver.ImsServiceControllerFactory() {
@Override
@@ -2211,10 +2461,6 @@
componentName.getPackageName())) {
when(carrierController1.getComponentName()).thenReturn(componentName);
return carrierController1;
- } else if (TEST_CARRIER_2_DEFAULT_NAME.getPackageName().equals(
- componentName.getPackageName())) {
- when(carrierController2.getComponentName()).thenReturn(componentName);
- return carrierController2;
}
return null;
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
index 2544fc1..aa6bd7f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerCompatTest.java
@@ -108,9 +108,9 @@
mMmTelCompatAdapterSpy = spy(new MmTelFeatureCompatAdapter(mMockContext, SLOT_0,
mMockMmTelInterfaceAdapter));
mTestImsServiceController = new ImsServiceControllerCompat(mMockContext, mTestComponentName,
- mMockCallbacks, mHandler, REBIND_RETRY, mRepo,
+ mMockCallbacks, mHandler, REBIND_RETRY, mRepo,
(a, b, c) -> mMmTelCompatAdapterSpy);
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
when(mMockServiceControllerBinder.createMMTelFeature(anyInt()))
.thenReturn(mMockRemoteMMTelFeature);
when(mMockRemoteMMTelFeature.getConfigInterface()).thenReturn(mMockImsConfig);
@@ -146,8 +146,8 @@
verify(mMockServiceControllerBinder).createMMTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_1),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
// Remove the feature
conn.onBindingDied(mTestComponentName);
@@ -191,8 +191,9 @@
SparseIntArray slotIdToSubIdMap) {
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap));
- verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt());
+ assertTrue(mTestImsServiceController.bind(mContext.getUser(), testFeatures,
+ slotIdToSubIdMap));
+ verify(mMockContext).bindServiceAsUser(any(), serviceCaptor.capture(), anyInt(), any());
return serviceCaptor.getValue();
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 65b73fb..5f16d9b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -39,6 +39,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
@@ -135,6 +136,7 @@
private final Handler mHandler = new Handler(Looper.getMainLooper());
private ImsServiceController mTestImsServiceController;
private ImsFeatureBinderRepository mRepo;
+ private UserHandle mUser;
@Before
@Override
@@ -150,11 +152,12 @@
mMockCallbacks = mock(ImsServiceController.ImsServiceControllerCallbacks.class);
mFeatureFlags = mock(FeatureFlags.class);
mMockContext = mock(Context.class);
+ mUser = UserHandle.of(UserHandle.myUserId());
mRepo = new ImsFeatureBinderRepository();
mTestImsServiceController = new ImsServiceController(mMockContext, mTestComponentName,
mMockCallbacks, mHandler, REBIND_RETRY, mRepo, mFeatureFlags);
- when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
+ when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
when(mMockServiceControllerBinder.createMmTelFeature(anyInt(), anyInt()))
.thenReturn(mMockMmTelFeature);
when(mMockServiceControllerBinder.createRcsFeature(anyInt(), anyInt()))
@@ -198,11 +201,12 @@
SparseIntArray slotIdToSubIdMap = new SparseIntArray();
slotIdToSubIdMap.put(SLOT_0, SUB_2);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone()));
+ assertTrue(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone()));
int expectedFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_IMPORTANT;
- verify(mMockContext).bindService(intentCaptor.capture(), any(), eq(expectedFlags));
+ verify(mMockContext).bindServiceAsUser(intentCaptor.capture(), any(), eq(expectedFlags),
+ any());
Intent testIntent = intentCaptor.getValue();
assertEquals(ImsService.SERVICE_INTERFACE, testIntent.getAction());
assertEquals(mTestComponentName, testIntent.getComponent());
@@ -222,9 +226,9 @@
bindAndConnectService(testFeatures, slotIdToSubIdMap.clone());
// already bound, should return false
- assertFalse(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone()));
+ assertFalse(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone()));
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -250,10 +254,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
}
@@ -282,10 +286,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -313,9 +317,9 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_3);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_3),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_3),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -341,13 +345,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -373,12 +377,12 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_5);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_5),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -411,13 +415,14 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
validateMmTelFeatureContainerExistsWithEmergency(SLOT_1);
@@ -437,8 +442,9 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_1);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_1),
- eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
+ eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
validateMmTelFeatureContainerExistsWithEmergency(SLOT_1);
@@ -470,10 +476,10 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateFeatureContainerExistsWithSipDelegate(ImsFeature.FEATURE_MMTEL, SLOT_0);
validateFeatureContainerExistsWithSipDelegate(ImsFeature.FEATURE_RCS, SLOT_0);
}
@@ -499,7 +505,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
// verify CAPABILITY_SIP_DELEGATE_CREATION is not set because MMTEL and RCS are not set.
validateFeatureContainerDoesNotHaveSipDelegate(ImsFeature.FEATURE_MMTEL, SLOT_0);
@@ -525,9 +532,9 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
// Make sure this callback happens, which will notify the framework of emergency calling
// availability.
@@ -553,9 +560,11 @@
verify(mMockServiceControllerBinder).createEmergencyOnlyMmTelFeature(SLOT_0);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID), eq(ImsFeature.FEATURE_MMTEL),
eq(mTestImsServiceController));
verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
// Make sure this callback happens, which will notify the framework of emergency calling
// availability.
@@ -584,17 +593,17 @@
verify(mMockServiceControllerBinder, never()).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder, never()).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
// verify RCS feature is created
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerExists(SLOT_0);
}
@@ -798,9 +807,9 @@
long delay = mTestImsServiceController.getRebindDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(anyInt(), anyInt(), anyInt(),
eq(mTestImsServiceController));
- verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName));
+ verify(mMockCallbacks).imsServiceBindPermanentError(eq(mTestComponentName), eq(mUser));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
validateRcsFeatureContainerDoesntExist(SLOT_0);
}
@@ -822,8 +831,8 @@
bindAndConnectService(testFeatures, slotIdToSubIdMap.clone());
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerDoesntExist(SLOT_0);
}
@@ -843,8 +852,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
@@ -859,8 +868,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
}
@@ -880,8 +889,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
// Create a new list with an additional item
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
testFeatures);
@@ -895,8 +904,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
}
@@ -918,8 +927,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
assertEquals(mMockMmTelBinder, cb.container.imsFeature);
assertTrue((ImsService.CAPABILITY_EMERGENCY_OVER_MMTEL
@@ -934,9 +943,8 @@
mTestImsServiceController.changeImsServiceFeatures(testFeaturesWithAddition,
slotIdToSubIdMap.clone());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0),
- eq(ImsFeature.FEATURE_EMERGENCY_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_EMERGENCY_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExistsWithEmergency(SLOT_0);
assertEquals(mMockMmTelBinder, cb.container.imsFeature);
@@ -972,8 +980,8 @@
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateRcsFeatureContainerExists(SLOT_0);
// Add FEATURE_EMERGENCY_MMTEL and ensure it doesn't cause MMTEL bind
HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeaturesWithAddition = new HashSet<>(
@@ -988,9 +996,8 @@
verify(mMockServiceControllerBinder, never()).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder, never()).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_1),
- eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_1);
}
@@ -1010,8 +1017,8 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
// Call change with the same features and make sure it is disregarded
@@ -1027,7 +1034,7 @@
verify(mMockServiceControllerBinder, never()).removeFeatureStatusCallback(anyInt(),
anyInt(), any());
verify(mMockCallbacks, times(1)).imsServiceFeatureCreated(eq(SLOT_0),
- eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
+ eq(SUB_2), eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockCallbacks, never()).imsServiceFeatureRemoved(anyInt(), anyInt(), any());
validateMmTelFeatureContainerExists(SLOT_0);
}
@@ -1050,13 +1057,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
// Create a new list with one less item
@@ -1098,13 +1105,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
// Create a new list with one less item
@@ -1149,23 +1156,23 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_RCS),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
validateRcsFeatureContainerExists(SLOT_0);
@@ -1205,12 +1212,12 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createRcsFeature(SLOT_0, SUB_4);
verify(mMockServiceControllerBinder, times(2)).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, times(2)).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_4),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateRcsFeatureContainerExists(SLOT_0);
@@ -1235,13 +1242,13 @@
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
verify(mMockServiceControllerBinder).createMmTelFeature(SLOT_1, SUB_3);
verify(mMockServiceControllerBinder).addFeatureStatusCallback(eq(SLOT_1),
eq(ImsFeature.FEATURE_MMTEL), any());
- verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(ImsFeature.FEATURE_MMTEL),
- eq(mTestImsServiceController));
+ verify(mMockCallbacks).imsServiceFeatureCreated(eq(SLOT_1), eq(SUB_3),
+ eq(ImsFeature.FEATURE_MMTEL), eq(mTestImsServiceController));
validateMmTelFeatureContainerExists(SLOT_0);
validateMmTelFeatureContainerExists(SLOT_1);
@@ -1291,7 +1298,7 @@
verify(mMockServiceControllerBinder, never()).createRcsFeature(SLOT_0, SUB_2);
verify(mMockServiceControllerBinder, never()).removeFeatureStatusCallback(eq(SLOT_0),
eq(ImsFeature.FEATURE_RCS), any());
- verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0),
+ verify(mMockCallbacks, never()).imsServiceFeatureCreated(eq(SLOT_0), eq(SUB_2),
eq(ImsFeature.FEATURE_RCS), eq(mTestImsServiceController));
validateMmTelFeatureContainerDoesntExist(SLOT_0);
validateRcsFeatureContainerDoesntExist(SLOT_0);
@@ -1318,7 +1325,7 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// The service should autobind after rebind event occurs
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1344,7 +1351,7 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// The service should autobind after rebind event occurs
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1365,7 +1372,7 @@
conn.onBindingDied(null /*null*/);
// Be sure that there are no binds before the RETRY_TIMEOUT expires
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1390,7 +1397,7 @@
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
// Unbind should stop the autobind from occurring.
- verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(1)).bindServiceAsUser(any(), any(), anyInt(), any());
}
/**
@@ -1412,10 +1419,10 @@
long delay = REBIND_RETRY.getStartDelay();
waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
- mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap.clone());
+ mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap.clone());
// Should only see two binds, not three from the auto rebind that occurs.
- verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+ verify(mMockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any());
}
private void validateMmTelFeatureContainerExists(int slotId) {
@@ -1504,8 +1511,8 @@
SparseIntArray slotIdToSubIdMap) {
ArgumentCaptor<ServiceConnection> serviceCaptor =
ArgumentCaptor.forClass(ServiceConnection.class);
- assertTrue(mTestImsServiceController.bind(testFeatures, slotIdToSubIdMap));
- verify(mMockContext).bindService(any(), serviceCaptor.capture(), anyInt());
+ assertTrue(mTestImsServiceController.bind(mUser, testFeatures, slotIdToSubIdMap));
+ verify(mMockContext).bindServiceAsUser(any(), serviceCaptor.capture(), anyInt(), any());
return serviceCaptor.getValue();
}
}
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 110dade..e6e4c30 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -4370,94 +4370,95 @@
public void addSatelliteControllerStats_withExistingEntries() throws Exception {
createEmptyTestFile();
mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
- mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController1);
- mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController2);
+ mPersistAtomsStorage.addSatelliteControllerStats(copyOf(mSatelliteController1));
+ mPersistAtomsStorage.addSatelliteControllerStats(copyOf(mSatelliteController1));
mPersistAtomsStorage.incTimeMillis(100L);
SatelliteController expected = new SatelliteController();
expected.countOfSatelliteServiceEnablementsSuccess =
- mSatelliteController1.countOfSatelliteServiceEnablementsSuccess
- + mSatelliteController2.countOfSatelliteServiceEnablementsSuccess;
+ mSatelliteController1.countOfSatelliteServiceEnablementsSuccess * 2;
expected.countOfSatelliteServiceEnablementsFail =
- mSatelliteController1.countOfSatelliteServiceEnablementsFail
- + mSatelliteController2.countOfSatelliteServiceEnablementsFail;
+ mSatelliteController1.countOfSatelliteServiceEnablementsFail * 2;
expected.countOfOutgoingDatagramSuccess =
- mSatelliteController1.countOfOutgoingDatagramSuccess
- + mSatelliteController2.countOfOutgoingDatagramSuccess;
+ mSatelliteController1.countOfOutgoingDatagramSuccess * 2;
expected.countOfOutgoingDatagramFail =
- mSatelliteController1.countOfOutgoingDatagramFail
- + mSatelliteController2.countOfOutgoingDatagramFail;
+ mSatelliteController1.countOfOutgoingDatagramFail * 2;
expected.countOfIncomingDatagramSuccess =
- mSatelliteController1.countOfIncomingDatagramSuccess
- + mSatelliteController2.countOfIncomingDatagramSuccess;
+ mSatelliteController1.countOfIncomingDatagramSuccess * 2;
expected.countOfIncomingDatagramFail =
- mSatelliteController1.countOfIncomingDatagramFail
- + mSatelliteController2.countOfIncomingDatagramFail;
+ mSatelliteController1.countOfIncomingDatagramFail * 2;
expected.countOfDatagramTypeSosSmsSuccess =
- mSatelliteController1.countOfDatagramTypeSosSmsSuccess
- + mSatelliteController2.countOfDatagramTypeSosSmsSuccess;
+ mSatelliteController1.countOfDatagramTypeSosSmsSuccess * 2;
expected.countOfDatagramTypeSosSmsFail =
- mSatelliteController1.countOfDatagramTypeSosSmsFail
- + mSatelliteController2.countOfDatagramTypeSosSmsFail;
+ mSatelliteController1.countOfDatagramTypeSosSmsFail * 2;
expected.countOfDatagramTypeLocationSharingSuccess =
- mSatelliteController1.countOfDatagramTypeLocationSharingSuccess
- + mSatelliteController2.countOfDatagramTypeLocationSharingSuccess;
+ mSatelliteController1.countOfDatagramTypeLocationSharingSuccess * 2;
expected.countOfDatagramTypeLocationSharingFail =
- mSatelliteController1.countOfDatagramTypeLocationSharingFail
- + mSatelliteController2.countOfDatagramTypeLocationSharingFail;
+ mSatelliteController1.countOfDatagramTypeLocationSharingFail * 2;
expected.countOfProvisionSuccess =
- mSatelliteController1.countOfProvisionSuccess
- + mSatelliteController2.countOfProvisionSuccess;
+ mSatelliteController1.countOfProvisionSuccess * 2;
expected.countOfProvisionFail =
- mSatelliteController1.countOfProvisionFail
- + mSatelliteController2.countOfProvisionFail;
+ mSatelliteController1.countOfProvisionFail * 2;
expected.countOfDeprovisionSuccess =
- mSatelliteController1.countOfDeprovisionSuccess
- + mSatelliteController2.countOfDeprovisionSuccess;
+ mSatelliteController1.countOfDeprovisionSuccess * 2;
expected.countOfDeprovisionFail =
- mSatelliteController1.countOfDeprovisionFail
- + mSatelliteController2.countOfDeprovisionFail;
+ mSatelliteController1.countOfDeprovisionFail * 2;
expected.totalServiceUptimeSec =
- mSatelliteController1.totalServiceUptimeSec
- + mSatelliteController2.totalServiceUptimeSec;
+ mSatelliteController1.totalServiceUptimeSec * 2;
expected.totalBatteryConsumptionPercent =
- mSatelliteController1.totalBatteryConsumptionPercent
- + mSatelliteController2.totalBatteryConsumptionPercent;
+ mSatelliteController1.totalBatteryConsumptionPercent * 2;
expected.totalBatteryChargedTimeSec =
- mSatelliteController1.totalBatteryChargedTimeSec
- + mSatelliteController2.totalBatteryChargedTimeSec;
+ mSatelliteController1.totalBatteryChargedTimeSec * 2;
expected.countOfDemoModeSatelliteServiceEnablementsSuccess =
- mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess
- + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsSuccess;
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess * 2;
expected.countOfDemoModeSatelliteServiceEnablementsFail =
- mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail
- + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsFail;
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail * 2;
expected.countOfDemoModeOutgoingDatagramSuccess =
- mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess
- + mSatelliteController2.countOfDemoModeOutgoingDatagramSuccess;
+ mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess * 2;
expected.countOfDemoModeOutgoingDatagramFail =
- mSatelliteController1.countOfDemoModeOutgoingDatagramFail
- + mSatelliteController2.countOfDemoModeOutgoingDatagramFail;
+ mSatelliteController1.countOfDemoModeOutgoingDatagramFail * 2;
expected.countOfDemoModeIncomingDatagramSuccess =
- mSatelliteController1.countOfDemoModeIncomingDatagramSuccess
- + mSatelliteController2.countOfDemoModeIncomingDatagramSuccess;
+ mSatelliteController1.countOfDemoModeIncomingDatagramSuccess * 2;
expected.countOfDemoModeIncomingDatagramFail =
- mSatelliteController1.countOfDemoModeIncomingDatagramFail
- + mSatelliteController2.countOfDemoModeIncomingDatagramFail;
+ mSatelliteController1.countOfDemoModeIncomingDatagramFail * 2;
expected.countOfDatagramTypeKeepAliveSuccess =
- mSatelliteController1.countOfDatagramTypeKeepAliveSuccess
- + mSatelliteController2.countOfDatagramTypeKeepAliveSuccess;
+ mSatelliteController1.countOfDatagramTypeKeepAliveSuccess * 2;
expected.countOfDatagramTypeKeepAliveFail =
- mSatelliteController1.countOfDatagramTypeKeepAliveFail
- + mSatelliteController2.countOfDatagramTypeKeepAliveFail;
- expected.isProvisioned = mSatelliteController2.isProvisioned;
- expected.carrierId = mSatelliteController2.carrierId;
+ mSatelliteController1.countOfDatagramTypeKeepAliveFail * 2;
+ expected.isProvisioned = mSatelliteController1.isProvisioned;
+ expected.carrierId = mSatelliteController1.carrierId;
+ expected.countOfSatelliteAllowedStateChangedEvents =
+ mSatelliteController1.countOfSatelliteAllowedStateChangedEvents * 2;
+ expected.countOfSuccessfulLocationQueries =
+ mSatelliteController1.countOfSuccessfulLocationQueries * 2;
+ expected.countOfFailedLocationQueries =
+ mSatelliteController1.countOfFailedLocationQueries * 2;
// Service state and service switch should be added successfully
verifyCurrentStateSavedToFileOnce();
SatelliteController[] output =
mPersistAtomsStorage.getSatelliteControllerStats(0L);
- assertHasStats(output, expected);
+ assertHasStats(output, expected, 1);
+ }
+
+ @Test
+ public void addSatelliteControllerStats_addNewCarrierId() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController1);
+ mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ SatelliteController expected1 = mSatelliteController1;
+ SatelliteController expected2 = mSatelliteController2;
+
+ // Service state and service switch should be added successfully
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteController[] output =
+ mPersistAtomsStorage.getSatelliteControllerStats(0L);
+
+ assertHasStats(output, expected1, 1);
+ assertHasStats(output, expected2, 1);
}
@Test
@@ -5829,60 +5830,71 @@
assertEquals(expectedCount, actualCount);
}
- private static void assertHasStats(
- SatelliteController[] tested,
- @Nullable SatelliteController expectedStats) {
+ private static void assertHasStats(SatelliteController[] tested,
+ @Nullable SatelliteController expectedStats, int expectedCount) {
assertNotNull(tested);
- assertEquals(tested[0].countOfSatelliteServiceEnablementsSuccess,
- expectedStats.countOfSatelliteServiceEnablementsSuccess);
- assertEquals(tested[0].countOfSatelliteServiceEnablementsFail,
- expectedStats.countOfSatelliteServiceEnablementsFail);
- assertEquals(tested[0].countOfOutgoingDatagramSuccess,
- expectedStats.countOfOutgoingDatagramSuccess);
- assertEquals(tested[0].countOfOutgoingDatagramFail,
- expectedStats.countOfOutgoingDatagramFail);
- assertEquals(tested[0].countOfIncomingDatagramSuccess,
- expectedStats.countOfIncomingDatagramSuccess);
- assertEquals(tested[0].countOfIncomingDatagramFail,
- expectedStats.countOfIncomingDatagramFail);
- assertEquals(tested[0].countOfDatagramTypeSosSmsSuccess,
- expectedStats.countOfDatagramTypeSosSmsSuccess);
- assertEquals(tested[0].countOfDatagramTypeSosSmsFail,
- expectedStats.countOfDatagramTypeSosSmsFail);
- assertEquals(tested[0].countOfDatagramTypeLocationSharingSuccess,
- expectedStats.countOfDatagramTypeLocationSharingSuccess);
- assertEquals(tested[0].countOfDatagramTypeLocationSharingFail,
- expectedStats.countOfDatagramTypeLocationSharingFail);
- assertEquals(tested[0].totalServiceUptimeSec,
- expectedStats.totalServiceUptimeSec);
- assertEquals(tested[0].totalBatteryConsumptionPercent,
- expectedStats.totalBatteryConsumptionPercent);
- assertEquals(tested[0].totalBatteryChargedTimeSec,
- expectedStats.totalBatteryChargedTimeSec);
- assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsSuccess,
- expectedStats.countOfDemoModeSatelliteServiceEnablementsSuccess);
- assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsFail,
- expectedStats.countOfDemoModeSatelliteServiceEnablementsFail);
- assertEquals(tested[0].countOfDemoModeOutgoingDatagramSuccess,
- expectedStats.countOfDemoModeOutgoingDatagramSuccess);
- assertEquals(tested[0].countOfDemoModeOutgoingDatagramFail,
- expectedStats.countOfDemoModeOutgoingDatagramFail);
- assertEquals(tested[0].countOfDemoModeIncomingDatagramSuccess,
- expectedStats.countOfDemoModeIncomingDatagramSuccess);
- assertEquals(tested[0].countOfDemoModeIncomingDatagramFail,
- expectedStats.countOfDemoModeIncomingDatagramFail);
- assertEquals(tested[0].countOfDatagramTypeKeepAliveSuccess,
- expectedStats.countOfDatagramTypeKeepAliveSuccess);
- assertEquals(tested[0].countOfDatagramTypeKeepAliveFail,
- expectedStats.countOfDatagramTypeKeepAliveFail);
- assertEquals(tested[0].countOfAllowedSatelliteAccess,
- expectedStats.countOfAllowedSatelliteAccess);
- assertEquals(tested[0].countOfDisallowedSatelliteAccess,
- expectedStats.countOfDisallowedSatelliteAccess);
- assertEquals(tested[0].countOfSatelliteAccessCheckFail,
- expectedStats.countOfSatelliteAccessCheckFail);
- assertEquals(tested[0].isProvisioned, expectedStats.isProvisioned);
- assertEquals(tested[0].carrierId, expectedStats.carrierId);
+ int actualCount = 0;
+ int i = 0;
+ for (SatelliteController stats : tested) {
+ if (expectedStats.carrierId == stats.carrierId) {
+ assertEquals(expectedStats.countOfSatelliteServiceEnablementsSuccess,
+ stats.countOfSatelliteServiceEnablementsSuccess);
+ assertEquals(expectedStats.countOfSatelliteServiceEnablementsFail,
+ stats.countOfSatelliteServiceEnablementsFail);
+ assertEquals(expectedStats.countOfOutgoingDatagramSuccess,
+ stats.countOfOutgoingDatagramSuccess);
+ assertEquals(expectedStats.countOfOutgoingDatagramFail,
+ stats.countOfOutgoingDatagramFail);
+ assertEquals(expectedStats.countOfIncomingDatagramSuccess,
+ stats.countOfIncomingDatagramSuccess);
+ assertEquals(expectedStats.countOfIncomingDatagramFail,
+ stats.countOfIncomingDatagramFail);
+ assertEquals(expectedStats.countOfDatagramTypeSosSmsSuccess,
+ stats.countOfDatagramTypeSosSmsSuccess);
+ assertEquals(expectedStats.countOfDatagramTypeSosSmsFail,
+ stats.countOfDatagramTypeSosSmsFail);
+ assertEquals(expectedStats.countOfDatagramTypeLocationSharingSuccess,
+ stats.countOfDatagramTypeLocationSharingSuccess);
+ assertEquals(expectedStats.countOfDatagramTypeLocationSharingFail,
+ stats.countOfDatagramTypeLocationSharingFail);
+ assertEquals(expectedStats.totalServiceUptimeSec, stats.totalServiceUptimeSec);
+ assertEquals(expectedStats.totalBatteryConsumptionPercent,
+ stats.totalBatteryConsumptionPercent);
+ assertEquals(expectedStats.totalBatteryChargedTimeSec,
+ stats.totalBatteryChargedTimeSec);
+ assertEquals(expectedStats.countOfDemoModeSatelliteServiceEnablementsSuccess,
+ stats.countOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(expectedStats.countOfDemoModeSatelliteServiceEnablementsFail,
+ stats.countOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(expectedStats.countOfDemoModeOutgoingDatagramSuccess,
+ stats.countOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(expectedStats.countOfDemoModeOutgoingDatagramFail,
+ stats.countOfDemoModeOutgoingDatagramFail);
+ assertEquals(expectedStats.countOfDemoModeIncomingDatagramSuccess,
+ stats.countOfDemoModeIncomingDatagramSuccess);
+ assertEquals(expectedStats.countOfDemoModeIncomingDatagramFail,
+ stats.countOfDemoModeIncomingDatagramFail);
+ assertEquals(expectedStats.countOfDatagramTypeKeepAliveSuccess,
+ stats.countOfDatagramTypeKeepAliveSuccess);
+ assertEquals(expectedStats.countOfDatagramTypeKeepAliveFail,
+ stats.countOfDatagramTypeKeepAliveFail);
+ assertEquals(expectedStats.countOfAllowedSatelliteAccess,
+ stats.countOfAllowedSatelliteAccess);
+ assertEquals(expectedStats.countOfDisallowedSatelliteAccess,
+ stats.countOfDisallowedSatelliteAccess);
+ assertEquals(expectedStats.countOfSatelliteAccessCheckFail,
+ stats.countOfSatelliteAccessCheckFail);
+ assertEquals(expectedStats.isProvisioned, stats.isProvisioned);
+ assertEquals(expectedStats.countOfSatelliteAllowedStateChangedEvents,
+ stats.countOfSatelliteAllowedStateChangedEvents);
+ assertEquals(expectedStats.countOfSuccessfulLocationQueries,
+ stats.countOfSuccessfulLocationQueries);
+ assertEquals(expectedStats.countOfFailedLocationQueries,
+ stats.countOfFailedLocationQueries);
+ actualCount++;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
}
private static void assertHasStatsAndCount(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
index 21731f0..271e0ad 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -16,10 +16,12 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@@ -44,6 +46,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.R;
import com.android.internal.telephony.TelephonyTest;
import org.junit.After;
@@ -187,6 +190,76 @@
}
}
+ @Test
+ public void testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_returnsFalse()
+ throws Exception {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ boolean result =
+ mDatagramControllerUT.needsWaitingForSatelliteConnected(
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+ assertFalse(result);
+ }
+
+ @Test
+ public void testNeedsWaitingForSatelliteConnected_regularSmsInNotConnected_returnsTrue()
+ throws Exception {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ boolean result =
+ mDatagramControllerUT.needsWaitingForSatelliteConnected(
+ DATAGRAM_TYPE_SMS);
+
+ assertTrue(result);
+ }
+
+ @Test
+ public void
+ testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_allowCheckMessageFalse_returnsTrue()
+ throws Exception {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, false);
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ boolean result =
+ mDatagramControllerUT.needsWaitingForSatelliteConnected(
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+ assertTrue(result);
+ }
+
+ @Test
+ public void
+ testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_carrierRoamingNbIotNtnFalse_returnsTrue()
+ throws Exception {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ boolean result =
+ mDatagramControllerUT.needsWaitingForSatelliteConnected(
+ DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+ assertTrue(result);
+ }
+
private void testUpdateSendStatus(boolean isDemoMode, int datagramType, int sendState) {
mDatagramControllerUT.setDemoMode(isDemoMode);
clearAllInvocations();
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 142e70a..566e5b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -31,6 +31,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
@@ -59,6 +60,7 @@
import android.testing.TestableLooper;
import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SmsDispatchersController;
@@ -257,7 +259,7 @@
eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(eq(datagramType));
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramType), anyLong());
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
@@ -398,7 +400,7 @@
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(anyInt());
+ .addCountOfSuccessfulOutgoingDatagram(anyInt(), anyLong());
clearInvocations(mMockSatelliteModemInterface);
clearInvocations(mMockDatagramController);
clearInvocations(mMockSessionMetricsStats);
@@ -523,7 +525,7 @@
eq(SATELLITE_RESULT_SUCCESS));
assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(eq(datagramType));
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramType), anyLong());
mDatagramDispatcherUT.setDemoMode(false);
mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
}
@@ -618,7 +620,7 @@
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(eq(DATAGRAM_TYPE2));
+ .addCountOfSuccessfulOutgoingDatagram(eq(DATAGRAM_TYPE2), anyLong());
mDatagramDispatcherUT.setDemoMode(false);
mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
@@ -731,7 +733,7 @@
anyInt(), any(SatelliteDatagram.class));
verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any());
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(anyInt());
+ .addCountOfSuccessfulOutgoingDatagram(anyInt(), anyLong());
// Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is
// false
@@ -1041,7 +1043,7 @@
eq(1),
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos));
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos), anyLong());
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
@@ -1133,12 +1135,172 @@
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
eq(SATELLITE_RESULT_SUCCESS));
verify(mMockSessionMetricsStats, times(1))
- .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos));
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramTypeSos), anyLong());
verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
}
+ @Test
+ public void testHandleMessage_eventMtSmsPollingThrottleTimedOut_sendsMtSmsPollInNotConnected() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.handleMessage(
+ mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+ new AsyncResult(null, null, null)));
+
+ verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+ }
+
+ @Test
+ public void
+ testHandleMessage_eventMtSmsPollingThrottleTimedOut_configDisabled_doesNotSendMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ // Set config_satellite_allow_check_message_in_not_connected to false
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, false);
+
+ mDatagramDispatcherUT.handleMessage(
+ mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+ new AsyncResult(null, null, null)));
+
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ }
+
+ @Test
+ public void
+ testHandleMessage_eventMtSmsPollingThrottleTimedOut_flagDisabled_doesNotSendMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ // Set flag to false
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.handleMessage(
+ mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+ new AsyncResult(null, null, null)));
+
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ }
+
+
+
+ @Test
+ public void testSetDeviceAlignedWithSatellite_isAligned_notConnected_sendsMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+
+ verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+ }
+
+ @Test
+ public void testSetDeviceAlignedWithSatellite_notAligned_doesNotSendsMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+
+ verifyZeroInteractions(mMockSmsDispatchersController);
+ }
+
+ @Test
+ public void testOnSatelliteModemStateChanged_notConnected_sendsMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+ }
+
+ @Test
+ public void testOnSatelliteModemStateChanged_connected_sendsMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+
+ verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+ }
+
+ @Test
+ public void testOnSatelliteModemStateChanged_transferring_sendsMtSmsPoll() {
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+
+ verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+ }
+
+ @Test
+ public void testOnSatelliteModemStateChanged_throttled_doesNotSendMtSmsPoll() {
+ startMtSmsPollingThrottle();
+ setShouldPollMtSmsTrue();
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
+ }
+
+ private void setModemState(int state) {
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(state);
+ }
+
+ private void setShouldPollMtSmsTrue() {
+ // Set mHasEnteredConnectedState true
+ setModemState(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ // Set the following so shouldPollMtSms returns true
+ mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
+ when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+ .thenReturn(true);
+ // This will trigger mShouldPollMtSms = shouldPollMtSms
+ setModemState(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ }
+
+ private void startMtSmsPollingThrottle() {
+ // Call sendSms to put message in mPendingSmsMap with isMtSmsPolling=true
+ PendingRequest pendingRequest = 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, /* isMtSmsPolling= */ true);
+ mDatagramDispatcherUT.sendSms(pendingRequest);
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = mPhone.getSubId();
+ args.arg2 = pendingRequest.uniqueMessageId;
+ args.arg3 = true;
+ // EVENT_SEND_SMS_DONE to trigger handleEventSendSmsDone which will start the throttle
+ mDatagramDispatcherUT.handleMessage(
+ mDatagramDispatcherUT.obtainMessage(9 /*EVENT_SEND_SMS_DONE*/, args));
+ }
+
private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
try {
@@ -1204,6 +1366,6 @@
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);
+ 10, 100L, false, false);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
index 873078e..354b20f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
@@ -80,7 +80,7 @@
doReturn(Arrays.asList(SATELLITE_PLMN_ARRAY))
.when(mMockSatelliteController).getSatellitePlmnsForCarrier(anyInt());
doReturn(mSatelliteSupportedServiceList).when(mMockSatelliteController)
- .getSupportedSatelliteServices(SUB_ID, SATELLITE_PLMN);
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, SATELLITE_PLMN);
}
@After
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 0a96f8c..6f716b5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -16,12 +16,14 @@
package com.android.internal.telephony.satellite;
-import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_INNER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_CLOSED;
import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_HARDWARE_CONFIGURATION_FOLD_IN_OPEN;
import static android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_MIGRATION;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
+import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
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;
@@ -31,7 +33,12 @@
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GREAT;
@@ -49,6 +56,7 @@
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_EMTC_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
import static android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NR_NTN;
@@ -79,16 +87,20 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.SatelliteController.DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS;
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_METERED;
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_UNMETERED;
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_FALSE;
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_TRUE;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -97,6 +109,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyVararg;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -112,11 +125,16 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.devicestate.DeviceState;
+import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -138,8 +156,10 @@
import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.satellite.EarfcnRange;
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -147,17 +167,22 @@
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
+import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteInfo;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteManager.SatelliteException;
import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SatellitePosition;
import android.telephony.satellite.SatelliteSubscriberInfo;
import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.telephony.satellite.SystemSelectionSpecifier;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.IntArray;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -195,9 +220,12 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -220,6 +248,7 @@
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>>
mCarrierConfigChangedListenerList = new ArrayList<>();
@@ -251,6 +280,7 @@
@Mock private Resources mResources;
@Mock private SubscriptionManager mSubscriptionManager;
@Mock private SubscriptionInfo mSubscriptionInfo;
+ @Mock private PackageManager mMockPManager;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -527,6 +557,22 @@
}
};
+ private int mQueriedSystemSelectionChannelUpdatedResultCode = SATELLITE_RESULT_SUCCESS;
+ private Semaphore mSystemSelectionChannelUpdatedSemaphore = new Semaphore(0);
+ private ResultReceiver mSystemSelectionChannelUpdatedReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mQueriedSystemSelectionChannelUpdatedResultCode = resultCode;
+ try {
+ mSystemSelectionChannelUpdatedSemaphore.release();
+ } catch (Exception ex) {
+ fail("mSystemSelectionChannelUpdatedReceiver: Got exception in releasing "
+ + "semaphore, ex="
+ + ex);
+ }
+ }
+ };
+
@Rule
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -566,9 +612,11 @@
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getSubId()).thenReturn(SUB_ID);
when(mPhone.getPhoneId()).thenReturn(0);
+ when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getSubId()).thenReturn(SUB_ID1);
when(mPhone2.getPhoneId()).thenReturn(1);
+ when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
mContextFixture.putStringArrayResource(
R.array.config_satellite_providers,
@@ -640,7 +688,7 @@
doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics();
doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
doReturn(mSST).when(mPhone).getServiceStateTracker();
doReturn(mSST).when(mPhone2).getServiceStateTracker();
doReturn(mServiceState).when(mSST).getServiceState();
@@ -943,6 +991,7 @@
@Test
public void testRequestSatelliteEnabled() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.satelliteStateChangeListener()).thenReturn(true);
mIsSatelliteEnabledSemaphore.drainPermits();
// Fail to enable satellite when SatelliteController is not fully loaded yet.
@@ -999,6 +1048,7 @@
doReturn(false).when(mTelecomManager).isInEmergencyCall();
// Successfully enable satellite
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -1020,12 +1070,14 @@
verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementSuccessCount();
+ verify(mTelephonyRegistryManager).notifySatelliteStateChanged(eq(true));
// Successfully disable satellite when radio is turned off.
+ reset(mTelephonyRegistryManager);
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -1044,7 +1096,8 @@
verify(mMockSatelliteSessionController, times(2)).setDemoMode(eq(false));
verify(mMockDatagramController, times(2)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(1)).onSatelliteDisabled();
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
+ verify(mTelephonyRegistryManager, atLeastOnce()).notifySatelliteStateChanged(eq(false));
// Fail to enable satellite when radio is off.
mIIntegerConsumerResults.clear();
@@ -1080,6 +1133,7 @@
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementFailCount();
// Successfully enable satellite when radio is on.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
@@ -1098,6 +1152,7 @@
verify(mMockDatagramController, times(3)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(2)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(2)).reportServiceEnablementSuccessCount();
+ verify(mTelephonyRegistryManager).notifySatelliteStateChanged(eq(true));
// Successfully enable satellite when it is already enabled.
mIIntegerConsumerResults.clear();
@@ -1118,6 +1173,7 @@
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
// Successfully disable satellite.
+ reset(mTelephonyRegistryManager);
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -1126,6 +1182,7 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mTelephonyRegistryManager, atLeastOnce()).notifySatelliteStateChanged(eq(false));
// Disable satellite when satellite is already disabled.
mIIntegerConsumerResults.clear();
@@ -1192,7 +1249,7 @@
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -1201,7 +1258,7 @@
mIIntegerConsumerResults.clear();
mIIntegerConsumerSemaphore.drainPermits();
resetSatelliteControllerUTToOffAndProvisionedState();
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
@@ -1624,6 +1681,11 @@
public void onRegistrationFailure(int causeCode) {
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
int errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(callback);
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
@@ -1655,6 +1717,11 @@
public void onRegistrationFailure(int causeCode) {
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
mSatelliteControllerUT.unregisterForModemStateChanged(callback);
verify(mMockSatelliteSessionController, never())
@@ -1668,6 +1735,7 @@
@Test
public void testRegisterForSatelliteProvisionStateChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
Semaphore semaphore = new Semaphore(0);
ISatelliteProvisionStateCallback callback =
new ISatelliteProvisionStateCallback.Stub() {
@@ -1689,12 +1757,7 @@
}
};
int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
-
- setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
- assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
resetSatelliteControllerUT();
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
@@ -1705,6 +1768,14 @@
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+ try {
+ setSatelliteSubscriberTesting();
+ } catch (Exception ex) {
+ fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
+ }
+ doReturn(true).when(mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(
+ anyInt());
+
String mText = "This is test provision data.";
byte[] testProvisionData = mText.getBytes();
CancellationSignal cancellationSignal = new CancellationSignal();
@@ -1716,8 +1787,8 @@
processAllMessages();
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteProvisionStateChanged"));
-
mSatelliteControllerUT.unregisterForSatelliteProvisionStateChanged(callback);
+ semaphore.drainPermits();
cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -1851,6 +1922,8 @@
@Test
public void testProvisionSatelliteService() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+
String mText = "This is test provision data.";
byte[] testProvisionData = mText.getBytes();
CancellationSignal cancellationSignal = new CancellationSignal();
@@ -1935,6 +2008,7 @@
@Test
public void testDeprovisionSatelliteService() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
mIIntegerConsumerSemaphore.drainPermits();
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
@@ -2006,7 +2080,7 @@
SUB_ID);
assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
List<Integer> supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
String[] satelliteProviderStrArray = {"00101", "00102"};
@@ -2033,7 +2107,7 @@
satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
// Add entitlement provided PLMNs.
@@ -2049,16 +2123,16 @@
processAllMessages();
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(supportedSatelliteServices.isEmpty());
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(supportedSatelliteServices.isEmpty());
// Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
@@ -2077,27 +2151,27 @@
assertTrue(Arrays.equals(
expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
// "00101" should return carrier config assigned value, though it is in allowed list.
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00103");
+ mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -2118,33 +2192,33 @@
assertTrue(satellitePlmnList.isEmpty());
// "00102" and "00103" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
// "00104", and "00105" should return default supported service for SUB_ID.
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00102");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00102");
assertNotNull(supportedSatelliteServices);
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
@@ -2152,20 +2226,20 @@
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00103");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00103");
assertTrue(Arrays.equals(expectedSupportedServices3,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
/* "00104", and "00105" should return default supported service. */
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00104");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00104");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
supportedSatelliteServices =
- testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00105");
+ testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00105");
assertTrue(Arrays.equals(defaultSupportedServices,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -2513,6 +2587,7 @@
assertTrue(
mQueriedSatelliteCapabilities.getSupportedRadioTechnologies().contains(
satelliteController.getSupportedNtnRadioTechnology()));
+ assertEquals(mQueriedSatelliteCapabilities.getMaxBytesPerOutgoingDatagram(), 255);
assertTrue(satelliteController.isSatelliteAttachRequired());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
@@ -2539,14 +2614,14 @@
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(true);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = true;
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
processAllMessages();
verify(mMockSatelliteSessionController, times(1)).onSatelliteModemStateChanged(
SATELLITE_MODEM_STATE_NOT_CONNECTED);
clearInvocations(mMockSatelliteSessionController);
- when(mMockSatelliteSessionController.isInDisablingState()).thenReturn(false);
+ mSatelliteControllerUT.isSatelliteBeingDisabled = false;
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_NOT_CONNECTED, null);
processAllMessages();
verify(mMockSatelliteSessionController, never()).onSatelliteModemStateChanged(
@@ -2556,7 +2631,6 @@
@Test
public void testRequestNtnSignalStrengthWithFeatureFlagEnabled() {
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
resetSatelliteControllerUT();
mRequestNtnSignalStrengthSemaphore.drainPermits();
@@ -3099,7 +3173,8 @@
// Verify call the requestSetSatelliteEnabledForCarrier to enable the satellite when
// satellite service is enabled by entitlement server.
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
- new ArrayList<>(), mIIntegerConsumer);
+ new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -3119,7 +3194,8 @@
.when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
- new ArrayList<>(), mIIntegerConsumer);
+ new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -3150,7 +3226,8 @@
List<String> entitlementPlmnList = new ArrayList<>();
List<String> barredPlmnList = new ArrayList<>();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
@@ -3208,7 +3285,8 @@
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", ""}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
@@ -3216,7 +3294,8 @@
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "123456789"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
@@ -3224,7 +3303,8 @@
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "12"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
@@ -3232,7 +3312,8 @@
reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "1234"}).toList();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
}
@@ -3241,7 +3322,8 @@
List<String> mergedPlmnList, List<String> overlayConfigPlmnList,
List<String> barredPlmnList) {
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
SUB_ID);
@@ -3289,7 +3371,8 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(new ArrayList<>());
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31016");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31016");
assertEquals(new ArrayList<>(), servicesPerPlmn);
// Verify whether the carrier config plmn list is returned with conditions below
@@ -3298,13 +3381,16 @@
setConfigData(new ArrayList<>());
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(1, 3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(Arrays.asList(2).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
@@ -3314,15 +3400,19 @@
setConfigData(Arrays.asList("00101", "00102", "31024"));
setCarrierConfigDataPlmnList(Arrays.asList("00101", "00102", "00104"));
invokeCarrierConfigChanged();
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
assertEquals(Arrays.asList(1).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00102");
assertEquals(Arrays.asList(3).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00104");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00104");
assertEquals(new ArrayList<>(), servicesPerPlmn.stream().sorted().toList());
- servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "31024");
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "31024");
assertEquals(Arrays.asList(5).stream().sorted().toList(),
servicesPerPlmn.stream().sorted().toList());
}
@@ -3455,21 +3545,24 @@
// Change SUB_ID's EntitlementStatus to true
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
- new ArrayList<>(), mIIntegerConsumer);
+ new ArrayList<>(), new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID1));
// Change SUB_ID1's EntitlementStatus to true
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID1, true, new ArrayList<>(),
- new ArrayList<>(), mIIntegerConsumer);
+ new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), mIIntegerConsumer);
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
// Change SUB_ID's EntitlementStatus to false
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
- new ArrayList<>(), mIIntegerConsumer);
+ new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+ new HashMap<>(), mIIntegerConsumer);
assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
@@ -3601,7 +3694,10 @@
@Test
public void testHandleEventServiceStateChanged() {
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_should_notify_availability, true);
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
invokeCarrierConfigChanged();
@@ -3609,6 +3705,7 @@
// Do nothing when the satellite is not connected
doReturn(false).when(mServiceState).isUsingNonTerrestrialNetwork();
sendServiceStateChangedEvent();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
processAllMessages();
assertFalse(mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false));
verify(mMockNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any());
@@ -3934,6 +4031,96 @@
}
@Test
+ public void testRegisterForSelectedNbIotSatelliteSubscriptionChanged_WithFeatureFlagEnabled() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ Semaphore semaphore = new Semaphore(0);
+ final int[] selectedSubIds = new int[1];
+ ISelectedNbIotSatelliteSubscriptionCallback callback =
+ new ISelectedNbIotSatelliteSubscriptionCallback.Stub() {
+ @Override
+ public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
+ logd("onSelectedNbIotSatelliteSubscriptionChanged: selectedSubId="
+ + selectedSubId);
+ try {
+ selectedSubIds[0] = selectedSubId;
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSelectedNbIotSatelliteSubscriptionChanged: Got exception in "
+ + "releasing semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ int errorCode = mSatelliteControllerUT.registerForSelectedNbIotSatelliteSubscriptionChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, errorCode);
+
+ setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+ errorCode = mSatelliteControllerUT.registerForSelectedNbIotSatelliteSubscriptionChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, errorCode);
+
+ // Register the callback and verify that the event is reported.
+ resetSatelliteControllerUT();
+ setUpResponseForRequestIsSatelliteProvisioned(true,SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ errorCode = mSatelliteControllerUT.registerForSelectedNbIotSatelliteSubscriptionChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+ int expectedSubId = 1;
+ sendSelectedNbIotSatelliteSubscriptionChangedEvent(expectedSubId, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSelectedNbIotSatelliteSubscriptionChanged"));
+ assertEquals(expectedSubId, selectedSubIds[0]);
+
+ // Unregister the callback and verify that the event is not reported.
+ mSatelliteControllerUT.unregisterForSelectedNbIotSatelliteSubscriptionChanged(callback);
+ sendSelectedNbIotSatelliteSubscriptionChangedEvent(2, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 0, "testRegisterForSelectedNbIotSatelliteSubscriptionChanged"));
+ }
+
+ @Test
+ public void testRegisterForSelectedNbIotSatelliteSubscriptionChanged_WithFeatureFlagDisabled() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+
+ Semaphore semaphore = new Semaphore(0);
+ final int[] selectedSubIds = new int[1];
+ ISelectedNbIotSatelliteSubscriptionCallback callback =
+ new ISelectedNbIotSatelliteSubscriptionCallback.Stub() {
+ @Override
+ public void onSelectedNbIotSatelliteSubscriptionChanged(int selectedSubId) {
+ logd("onSelectedNbIotSatelliteSubscriptionChanged: selectedSubId="
+ + selectedSubId);
+ try {
+ selectedSubIds[0] = selectedSubId;
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSelectedNbIotSatelliteSubscriptionChanged: Got exception in "
+ + "releasing semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ int errorCode = mSatelliteControllerUT.registerForSelectedNbIotSatelliteSubscriptionChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
+
+ // Verify that the event is not reported.
+ sendSelectedNbIotSatelliteSubscriptionChangedEvent(1, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 0, "testRegisterForSelectedNbIotSatelliteSubscriptionChanged"));
+
+
+ }
+
+ @Test
public void testIsSatelliteEmergencyMessagingSupportedViaCarrier() {
// Carrier-enabled flag is off
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
@@ -4041,6 +4228,7 @@
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
@@ -4095,12 +4283,17 @@
@Test
public void testNotifyNtnEligibilityHysteresisTimedOut() {
+ mContextFixture.putBooleanResource(
+ R.bool.config_satellite_should_notify_availability, true);
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);
+ mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
+ mSatelliteControllerUT.setIsSatelliteSupported(true);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
- mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+ CARRIER_ROAMING_NTN_CONNECT_MANUAL);
mCarrierConfigBundle.putInt(
KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 1 * 60);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
@@ -4122,6 +4315,7 @@
}
mSatelliteControllerUT.setSatellitePhone(1);
mSatelliteControllerUT.isSatelliteAllowedCallback = null;
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
processAllMessages();
mSatelliteControllerUT.elapsedRealtime = 0;
assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
@@ -4178,6 +4372,43 @@
}
@Test
+ public void testNotifyCarrierRoamingNtnSignalStrengthChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ sendSignalStrengthChangedEvent(mPhone.getPhoneId());
+ processAllMessages();
+ ArgumentCaptor<NtnSignalStrength> captor = ArgumentCaptor.forClass(NtnSignalStrength.class);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnSignalStrengthChanged(
+ captor.capture());
+ NtnSignalStrength actualSignalStrength = captor.getValue();
+ assertEquals(NTN_SIGNAL_STRENGTH_NONE, actualSignalStrength.getLevel());
+ clearInvocations(mPhone);
+
+ when(mSignalStrength.getLevel()).thenReturn(SignalStrength.SIGNAL_STRENGTH_GOOD);
+ when(mPhone.getSignalStrength()).thenReturn(mSignalStrength);
+ mCarrierConfigBundle.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 1 * 60);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+ when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(true);
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ sendServiceStateChangedEvent();
+ processAllMessages();
+ captor = ArgumentCaptor.forClass(NtnSignalStrength.class);
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnSignalStrengthChanged(
+ captor.capture());
+ actualSignalStrength = captor.getValue();
+ assertEquals(NTN_SIGNAL_STRENGTH_GOOD, actualSignalStrength.getLevel());
+ clearInvocations(mPhone);
+ }
+
+ @Test
public void testGetWwanIsInService() {
when(mServiceState.getNetworkRegistrationInfoListForTransportType(
eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
@@ -4231,6 +4462,11 @@
resultErrorCode[0] = causeCode;
semaphore.release();
}
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
};
resetSatelliteControllerUTToSupportedAndProvisionedState();
mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
@@ -4284,6 +4520,51 @@
assertTrue(mSatelliteControllerUT.isFoldable(mContext, foldableDeviceStateList));
}
+ @Test
+ public void testTerrestrialNetworkAvailableChangedCallback() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ Semaphore semaphore = new Semaphore(0);
+ final int[] receivedScanResult = new int[1];
+ ISatelliteModemStateCallback callback = new ISatelliteModemStateCallback.Stub() {
+ @Override
+ public void onSatelliteModemStateChanged(int state) {
+ logd("onSatelliteModemStateChanged: state=" + state);
+ }
+
+ @Override
+ public void onEmergencyModeChanged(boolean isEmergency) {
+ logd("onEmergencyModeChanged: emergency=" + isEmergency);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ logd("onRegistrationFailure: causeCode=" + causeCode);
+ }
+
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ receivedScanResult[0] = isAvailable ? 1 : 0;
+ semaphore.release();
+ }
+ };
+ resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
+
+ int RegisterErrorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
+ callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, RegisterErrorCode);
+ verify(mMockSatelliteSessionController).registerForSatelliteModemStateChanged(callback);
+
+ int expectedErrorCode = 1;
+ mIIntegerConsumerResults.clear();
+ sendTerrestrialNetworkAvailableChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegistrationFailureCallback"));
+ assertEquals(expectedErrorCode, receivedScanResult[0]);
+ }
+
private boolean mProvisionState = false;
private int mProvisionSateResultCode = -1;
private Semaphore mProvisionSateSemaphore = new Semaphore(0);
@@ -4354,6 +4635,7 @@
private void verifyRequestSatelliteSubscriberProvisionStatus() throws Exception {
setSatelliteSubscriberTesting();
List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, true);
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -4430,6 +4712,18 @@
}
}
};
+
+ TestSubscriptionManager testSubscriptionManager = new TestSubscriptionManager();
+ doAnswer(invocation -> {
+ testSubscriptionManager.setIsSatelliteProvisionedForNonIpDatagram(
+ invocation.getArgument(0), invocation.getArgument(1));
+ return null;
+ }).when(mMockSubscriptionManagerService).setIsSatelliteProvisionedForNonIpDatagram(anyInt(),
+ anyBoolean());
+ doAnswer(invocation -> testSubscriptionManager.isSatelliteProvisionedForNonIpDatagram(
+ invocation.getArgument(0))).when(
+ mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
+
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
@@ -4449,7 +4743,7 @@
any());
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
- assertTrue(resultArray[0].getProvisionStatus());
+ assertTrue(resultArray[0].isProvisioned());
assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
// Request provisioning with SatelliteSubscriberInfo that has not been provisioned
@@ -4460,7 +4754,7 @@
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
- assertTrue(resultArray[1].getProvisionStatus());
+ assertTrue(resultArray[1].isProvisioned());
assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
// Request provisioning with the same SatelliteSubscriberInfo that was previously
@@ -4475,9 +4769,9 @@
verifyDeprovisionSatellite(inputList);
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
- assertFalse(resultArray[1].getProvisionStatus());
+ assertFalse(resultArray[1].isProvisioned());
assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
- assertTrue(resultArray[0].getProvisionStatus());
+ assertTrue(resultArray[0].isProvisioned());
assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
// Request deprovision for subscriberID 1, verify that subscriberID 1 is set to deprovision.
@@ -4486,9 +4780,9 @@
verifyDeprovisionSatellite(inputList);
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
- assertFalse(resultArray[1].getProvisionStatus());
+ assertFalse(resultArray[1].isProvisioned());
assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
- assertFalse(resultArray[0].getProvisionStatus());
+ assertFalse(resultArray[0].isProvisioned());
assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
// Request provision for subscriberID 2, verify that subscriberID 2 is set to provision.
@@ -4498,9 +4792,9 @@
assertTrue(waitForForEvents(
semaphore, 1, "testRegisterForSatelliteSubscriptionProvisionStateChanged"));
- assertTrue(resultArray[1].getProvisionStatus());
+ assertTrue(resultArray[1].isProvisioned());
assertEquals(mSubscriberId2, resultArray[1].getSatelliteSubscriberInfo().getSubscriberId());
- assertFalse(resultArray[0].getProvisionStatus());
+ assertFalse(resultArray[0].isProvisioned());
assertEquals(mSubscriberId, resultArray[0].getSatelliteSubscriberInfo().getSubscriberId());
}
@@ -4669,6 +4963,7 @@
@Test
public void testCheckForSubscriberIdChange_changed() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
List<SubscriptionInfo> allSubInfos = new ArrayList<>();
String imsi = "012345";
@@ -4687,6 +4982,7 @@
.thenReturn(allSubInfos);
when(mSubscriptionInfo.isSatelliteESOSSupported()).thenReturn(true);
+ when(mSubscriptionInfo.isActive()).thenReturn(true);
when(mMockSubscriptionManagerService.getSubscriptionInfoInternal(SUB_ID))
.thenReturn(subInfoInternal);
@@ -4741,6 +5037,260 @@
eq(SUB_ID), eq(true));
}
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForManualConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_MANUAL: 1
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ assertTrue(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(/*subId*/ SUB_ID));
+ }
+
+ @Test
+ public void testIsCarrierRoamingNtnAvailableServicesForAutomaticConnect() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ // CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC: 0
+ mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0);
+
+ mSatelliteControllerUT.setSatellitePhone(1);
+ processAllMessages();
+ when(mContext.getPackageManager()).thenReturn(mMockPManager);
+ try {
+ when(mMockPManager.getApplicationInfo(anyString(),
+ anyInt())).thenReturn(getApplicationInfo());
+ } catch (PackageManager.NameNotFoundException e) {
+ logd("NameNotFoundException");
+ }
+ // If it is automatic connection case, it is not support the callback.
+ assertFalse(mSatelliteControllerUT
+ .isP2PSmsDisallowedOnCarrierRoamingNtn(/*subId*/ SUB_ID));
+ }
+
+ ApplicationInfo getApplicationInfo() {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.metaData = new Bundle();
+ applicationInfo.metaData.putBoolean(
+ METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT, true);
+ return applicationInfo;
+ }
+
+ @Test
+ public void testRegisterApplicationStateChanged() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false);
+ when(mMockSubscriptionManagerService.getActiveSubIdList(true))
+ .thenReturn(new int[]{SUB_ID1});
+
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+ ArgumentCaptor<BroadcastReceiver> receiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext).registerReceiver(receiverCaptor.capture(), intentFilterCaptor.capture(),
+ anyInt());
+
+ BroadcastReceiver receiver = receiverCaptor.getValue();
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch1 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch1.countDown();
+ }, 100);
+ try {
+ latch1.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_REPLACED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch2 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch2.countDown();
+ }, 100);
+ try {
+ latch2.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+ intent.setData(Uri.parse("com.example.app"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch3 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch3.countDown();
+ }, 100);
+ try {
+ latch3.await();
+ } catch (InterruptedException e) {
+ }
+ assertTrue(mSatelliteControllerUT.isApplicationUpdated);
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
+ intent.setData(Uri.parse("com.example.different"));
+ receiver.onReceive(mContext, intent);
+ CountDownLatch latch4 = new CountDownLatch(1);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ latch4.countDown();
+ }, 100);
+ try {
+ latch4.await();
+ } catch (InterruptedException e) {
+ }
+ assertFalse(mSatelliteControllerUT.isApplicationUpdated);
+ }
+
+ @Test
+ public void testUpdateSystemSelectionChannels() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+ String mccmnc = "123455";
+ int[] bands1 = {200, 201, 202};
+ IntArray intArraybands1 = new IntArray(3);
+ intArraybands1.addAll(bands1);
+ int[] earfcns1 = {300, 301, 310, 311};
+ IntArray intArrayEarfcns1 = new IntArray(4);
+ intArrayEarfcns1.addAll(earfcns1);
+ String seed1 = "test-seed-satellite1";
+ UUID uuid1 = UUID.nameUUIDFromBytes(seed1.getBytes());
+ SatellitePosition satellitePosition1 = new SatellitePosition(0, 35876);
+ EarfcnRange earfcnRange1 = new EarfcnRange(301, 300);
+ EarfcnRange earfcnRange2 = new EarfcnRange(311, 310);
+ List<EarfcnRange> earfcnRangeList1 = new ArrayList<>(
+ Arrays.asList(earfcnRange1, earfcnRange2));
+ SatelliteInfo satelliteInfo1 = new SatelliteInfo(uuid1, satellitePosition1, Arrays.stream(
+ bands1).boxed().collect(Collectors.toList()), earfcnRangeList1);
+ int[] tagIds = {1, 2, 3};
+ IntArray intArrayTagIds = new IntArray(3);
+ intArrayTagIds.addAll(tagIds);
+ SystemSelectionSpecifier systemSelectionSpecifier1 = new SystemSelectionSpecifier(mccmnc,
+ intArraybands1, intArrayEarfcns1, new SatelliteInfo[]{satelliteInfo1},
+ intArrayTagIds);
+
+ setUpResponseForUpdateSystemSelectionChannels(SATELLITE_RESULT_ERROR);
+ mSatelliteControllerUT.updateSystemSelectionChannels(
+ new ArrayList<>(List.of(systemSelectionSpecifier1)),
+ mSystemSelectionChannelUpdatedReceiver);
+ processAllMessages();
+ assertTrue(waitForRequestUpdateSystemSelectionChannelResult(1));
+ assertEquals(SATELLITE_RESULT_ERROR, mQueriedSystemSelectionChannelUpdatedResultCode);
+
+ // Verify whether callback receives expected result
+ setUpResponseForUpdateSystemSelectionChannels(SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.updateSystemSelectionChannels(
+ new ArrayList<>(List.of(systemSelectionSpecifier1)),
+ mSystemSelectionChannelUpdatedReceiver);
+ processAllMessages();
+ assertTrue(waitForRequestUpdateSystemSelectionChannelResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSystemSelectionChannelUpdatedResultCode);
+
+ // Verify whether SatelliteModemInterface API was invoked and data is valid, when single
+ // data was provided.
+ ArgumentCaptor<List<SystemSelectionSpecifier>> systemSelectionSpecifierListCaptor =
+ ArgumentCaptor.forClass(List.class);
+ verify(mMockSatelliteModemInterface, times(2)).updateSystemSelectionChannels(
+ systemSelectionSpecifierListCaptor.capture(), any(Message.class));
+ List<SystemSelectionSpecifier> capturedList = systemSelectionSpecifierListCaptor.getValue();
+ SystemSelectionSpecifier systemSelectionSpecifier = capturedList.getFirst();
+
+ assertEquals(mccmnc, systemSelectionSpecifier.getMccMnc());
+ int[] actualBandsArray = systemSelectionSpecifier.getBands();
+ assertArrayEquals(bands1, actualBandsArray);
+ int[] actualEarfcnsArray = systemSelectionSpecifier.getEarfcns();
+ assertArrayEquals(earfcns1, actualEarfcnsArray);
+ assertArrayEquals(new SatelliteInfo[]{satelliteInfo1},
+ systemSelectionSpecifier.getSatelliteInfos().toArray(new SatelliteInfo[0]));
+ int[] actualTagIdArray = systemSelectionSpecifier.getTagIds();
+ assertArrayEquals(tagIds, actualTagIdArray);
+
+ // Verify whether SatelliteModemInterface API was invoked and data is valid, when list
+ // of data was provided.
+ int[] bands2 = {210, 211, 212};
+ IntArray intArraybands2 = new IntArray(3);
+ intArraybands2.addAll(bands2);
+ int[] earfcns2 = {320, 321, 330, 331};
+ IntArray intArrayEarfcns2 = new IntArray(4);
+ intArrayEarfcns2.addAll(earfcns2);
+ String seed2 = "test-seed-satellite2";
+ UUID uuid2 = UUID.nameUUIDFromBytes(seed2.getBytes());
+ SatellitePosition satellitePosition2 = new SatellitePosition(120, 35876);
+ EarfcnRange earfcnRange3 = new EarfcnRange(321, 320);
+ EarfcnRange earfcnRange4 = new EarfcnRange(331, 330);
+ List<EarfcnRange> earfcnRangeList2 = new ArrayList<>(
+ Arrays.asList(earfcnRange3, earfcnRange4));
+ SatelliteInfo satelliteInfo2 = new SatelliteInfo(uuid2, satellitePosition2, Arrays.stream(
+ bands1).boxed().collect(Collectors.toList()), earfcnRangeList2);
+ SystemSelectionSpecifier systemSelectionSpecifier2 = new SystemSelectionSpecifier(mccmnc,
+ intArraybands2, intArrayEarfcns2, new SatelliteInfo[]{satelliteInfo2},
+ intArrayTagIds);
+
+ // Verify whether callback receives expected result
+ setUpResponseForUpdateSystemSelectionChannels(SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.updateSystemSelectionChannels(
+ new ArrayList<>(List.of(systemSelectionSpecifier1, systemSelectionSpecifier2)),
+ mSystemSelectionChannelUpdatedReceiver);
+ processAllMessages();
+ assertTrue(waitForRequestUpdateSystemSelectionChannelResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSystemSelectionChannelUpdatedResultCode);
+
+ // Verify whether SatelliteModemInterface API was invoked and data is valid,
+ verify(mMockSatelliteModemInterface, times(3)).updateSystemSelectionChannels(
+ systemSelectionSpecifierListCaptor.capture(), any(Message.class));
+ capturedList = systemSelectionSpecifierListCaptor.getValue();
+ SystemSelectionSpecifier capturedSystemSelectionSpecifier1 = capturedList.getFirst();
+ SystemSelectionSpecifier capturedSystemSelectionSpecifier2 = capturedList.get(1);
+
+ // Verify first SystemSelectionSpecifier
+ assertEquals(mccmnc, systemSelectionSpecifier.getMccMnc());
+ actualBandsArray = capturedSystemSelectionSpecifier1.getBands();
+ assertArrayEquals(bands1, actualBandsArray);
+ actualEarfcnsArray = capturedSystemSelectionSpecifier1.getEarfcns();
+ assertArrayEquals(earfcns1, actualEarfcnsArray);
+ assertArrayEquals(new SatelliteInfo[]{satelliteInfo1},
+ capturedSystemSelectionSpecifier1.getSatelliteInfos().toArray(
+ new SatelliteInfo[0]));
+ actualTagIdArray = capturedSystemSelectionSpecifier1.getTagIds();
+ assertArrayEquals(tagIds, actualTagIdArray);
+
+ // Verify second SystemSelectionSpecifier
+ assertEquals(mccmnc, systemSelectionSpecifier.getMccMnc());
+ actualBandsArray = capturedSystemSelectionSpecifier2.getBands();
+ assertArrayEquals(bands2, actualBandsArray);
+ actualEarfcnsArray = capturedSystemSelectionSpecifier2.getEarfcns();
+ assertArrayEquals(earfcns2, actualEarfcnsArray);
+ assertArrayEquals(new SatelliteInfo[]{satelliteInfo2},
+ capturedSystemSelectionSpecifier2.getSatelliteInfos().toArray(
+ new SatelliteInfo[0]));
+ actualTagIdArray = capturedSystemSelectionSpecifier2.getTagIds();
+ assertArrayEquals(tagIds, actualTagIdArray);
+ }
+
private void verifyProvisionStatusPerSubscriberIdGetFromDb(boolean provision) {
doReturn(provision).when(
mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
@@ -4761,7 +5311,7 @@
assertEquals(SATELLITE_RESULT_SUCCESS,
mRequestSatelliteSubscriberProvisionStatusResultCode);
assertEquals(provision,
- mRequestSatelliteSubscriberProvisionStatusResultList.get(0).getProvisionStatus());
+ mRequestSatelliteSubscriberProvisionStatusResultList.get(0).isProvisioned());
}
private void setComponentName() {
@@ -5055,6 +5605,19 @@
}).when(mMockSatelliteModemInterface).stopSendingNtnSignalStrength(any(Message.class));
}
+ private void setUpResponseForUpdateSystemSelectionChannels(
+ @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).updateSystemSelectionChannels(anyList(),
+ any(Message.class));
+ }
+
private boolean waitForRequestIsSatelliteSupportedResult(int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
try {
@@ -5178,6 +5741,24 @@
return true;
}
+ private boolean waitForRequestUpdateSystemSelectionChannelResult(int expectedNumberOfEvents) {
+ for (int i = 0; i < expectedNumberOfEvents; i++) {
+ try {
+ if (!mSystemSelectionChannelUpdatedSemaphore.tryAcquire(TIMEOUT,
+ TimeUnit.MILLISECONDS)) {
+ logd("Timeout to receive "
+ + "updateSystemSelectionChannel()"
+ + " callback");
+ return false;
+ }
+ } catch (Exception ex) {
+ logd("updateSystemSelectionChannel: Got exception=" + ex);
+ return false;
+ }
+ }
+ return true;
+ }
+
private void verifySatelliteSupported(boolean supported, int expectedErrorCode) {
mSatelliteSupportSemaphore.drainPermits();
mSatelliteControllerUT.requestIsSatelliteSupported(mSatelliteSupportReceiver);
@@ -5247,6 +5828,13 @@
msg.sendToTarget();
}
+ private void sendSignalStrengthChangedEvent(int phoneId) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 57 /* EVENT_SIGNAL_STRENGTH_CHANGED */);
+ msg.obj = new AsyncResult(phoneId, null, null);
+ msg.sendToTarget();
+ }
+
private void sendCmdStartSendingNtnSignalStrengthChangedEvent(boolean shouldReport) {
Message msg = mSatelliteControllerUT.obtainMessage(
35 /* CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING */);
@@ -5290,6 +5878,22 @@
msg.sendToTarget();
}
+ private void sendTerrestrialNetworkAvailableChangedEvent(boolean isAvailable,
+ Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 55 /* EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED */);
+ msg.obj = new AsyncResult(null, isAvailable, exception);
+ msg.sendToTarget();
+ }
+
+ private void sendSelectedNbIotSatelliteSubscriptionChangedEvent(int selectedSubId,
+ Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 60 /* EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED */);
+ msg.obj = new AsyncResult(null, selectedSubId, exception);
+ msg.sendToTarget();
+ }
+
private void setRadioPower(boolean on) {
mSimulatedCommands.setRadioPower(on, false, false, null);
}
@@ -5319,6 +5923,15 @@
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+
+ try {
+ setSatelliteSubscriberTesting();
+ } catch (Exception ex) {
+ fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
+ }
+ doReturn(true).when(mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(
+ anyInt());
+
cancelRemote = mSatelliteControllerUT.provisionSatelliteService(
TEST_SATELLITE_TOKEN,
testProvisionData, mIIntegerConsumer);
@@ -5490,11 +6103,16 @@
public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
public OutcomeReceiver<Boolean, SatelliteException> isSatelliteAllowedCallback = null;
+ public static boolean isApplicationUpdated;
+ public String packageName = "com.example.app";
+ public boolean isSatelliteBeingDisabled = false;
+ public boolean mIsApplicationSupportsP2P = false;
TestSatelliteController(
Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
super(context, looper, featureFlags);
logd("Constructing TestSatelliteController");
+ isApplicationUpdated = false;
}
@Override
@@ -5569,9 +6187,41 @@
"DEFAULT" /* name */).build()));
}
+ @Override
+ public boolean isSatelliteBeingDisabled() {
+ return isSatelliteBeingDisabled;
+ }
+
+ protected String getConfigSatelliteGatewayServicePackage() {
+ String packageName = "com.example.app";
+ return packageName;
+ }
+
+ @Override
+ protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
+ isApplicationUpdated = true;
+ }
+
+ @Override
+ public boolean isApplicationSupportsP2P(String packageName) {
+ return mIsApplicationSupportsP2P;
+ }
+
+ @Override
+ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+ return new int[]{3, 5};
+ }
+
+
void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
- synchronized (mSatelliteViaOemProvisionLock) {
- mIsSatelliteViaOemProvisioned = isProvisioned;
+ synchronized (mDeviceProvisionLock) {
+ mIsDeviceProvisioned = isProvisioned;
+ }
+ }
+
+ void setIsSatelliteSupported(@Nullable Boolean isSatelliteSupported) {
+ synchronized (mIsSatelliteSupportedLock) {
+ mIsSatelliteSupported = isSatelliteSupported;
}
}
@@ -5614,5 +6264,327 @@
public boolean isAnyWaitForSatelliteEnablingResponseTimerStarted() {
return hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT);
}
+
+ public int getResultReceiverTotalCount() {
+ synchronized (mResultReceiverTotalCountLock) {
+ return mResultReceiverTotalCount;
+ }
+ }
+
+ public HashMap<String, Integer> getResultReceiverCountPerMethodMap() {
+ synchronized (mResultReceiverTotalCountLock) {
+ return mResultReceiverCountPerMethodMap;
+ }
+ }
+ }
+
+ @Test
+ public void testLoggingCodeForResultReceiverCount() throws Exception {
+ final String callerSC = "SC:ResultReceiver";
+ final String callerSAC = "SAC:ResultReceiver";
+
+ doReturn(false).when(mFeatureFlags).carrierRoamingNbIotNtn();
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+
+ doReturn(true).when(mFeatureFlags).carrierRoamingNbIotNtn();
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSC);
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(2, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.incrementResultReceiverCount(callerSAC);
+ assertEquals(3, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(2, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSC);
+ assertEquals(1, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(1, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+
+ mSatelliteControllerUT.decrementResultReceiverCount(callerSAC);
+ assertEquals(0, mSatelliteControllerUT.getResultReceiverTotalCount());
+ assertEquals(2, mSatelliteControllerUT.getResultReceiverCountPerMethodMap().size());
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSC)).orElse(0));
+ assertEquals(0, (int) Optional.ofNullable(mSatelliteControllerUT
+ .getResultReceiverCountPerMethodMap().get(callerSAC)).orElse(0));
+ }
+
+ @Test
+ public void testSetNtnSmsSupportedByMessagesApp() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ mSatelliteControllerUT.setNtnSmsSupportedByMessagesApp(true);
+ assertTrue(mSharedPreferences.getBoolean(
+ SatelliteController.NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false));
+ }
+
+ private static class TestSubscriptionManager {
+ public Map<Integer, Boolean> mSatelliteProvisionedForNonIpDatagram = new HashMap<>();
+
+ public void resetProvisionMapForNonIpDatagram() {
+ mSatelliteProvisionedForNonIpDatagram.clear();
+ }
+
+ public void setIsSatelliteProvisionedForNonIpDatagram(int subId, boolean provisioned) {
+ mSatelliteProvisionedForNonIpDatagram.put(subId, provisioned);
+ }
+
+ public boolean isSatelliteProvisionedForNonIpDatagram(int subId) {
+ Boolean isProvisioned = mSatelliteProvisionedForNonIpDatagram.get(subId);
+ return isProvisioned != null ? isProvisioned : false;
+ }
+ }
+
+ @Test
+ public void testGetSatelliteDataPlanForPlmn_WithEntitlement() throws Exception {
+ logd("testGetSatelliteDataPlanForPlmn_WithEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, Integer> dataPlanListMap = Map.of(
+ "00101", SATELLITE_DATA_PLAN_METERED,
+ "00103", SATELLITE_DATA_PLAN_UNMETERED);
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, dataPlanListMap, new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+ int dataPlanForPlmn;
+ dataPlanForPlmn = mSatelliteControllerUT.getSatelliteDataPlanForPlmn(SUB_ID, "00101");
+ assertEquals(SATELLITE_DATA_PLAN_METERED, dataPlanForPlmn);
+
+ dataPlanForPlmn = mSatelliteControllerUT.getSatelliteDataPlanForPlmn(SUB_ID, "00103");
+ assertEquals(SATELLITE_DATA_PLAN_UNMETERED, dataPlanForPlmn);
+ }
+
+ @Test
+ public void testGetSatelliteDataPlanForPlmn_WithoutEntitlement() throws Exception {
+ logd("testGetSatelliteDataPlanForPlmn_WithoutEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, Integer> dataPlanListMap = new HashMap<>();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, dataPlanListMap, new HashMap<>(),
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+ int dataPlanForPlmn = mSatelliteControllerUT.getSatelliteDataPlanForPlmn(SUB_ID, "00101");
+ assertEquals(SATELLITE_DATA_PLAN_METERED, dataPlanForPlmn);
+ }
+
+ @Test
+ public void TestGetSupportedSatelliteServicesForPlmn_WithEntitlement() throws Exception {
+ logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, List<Integer>> serviceTypeListMap = Map.of(
+ "00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS),
+ "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+ "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+ List<Integer> allowedServiceForPlmn;
+ allowedServiceForPlmn = mSatelliteControllerUT
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
+ assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+
+ allowedServiceForPlmn = mSatelliteControllerUT
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
+ assertEquals(List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+
+ allowedServiceForPlmn = mSatelliteControllerUT
+ .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
+ assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+ allowedServiceForPlmn);
+ }
+
+ @Test
+ public void TestGetSupportedSatelliteServicesForPlmn_WithoutEntitlement() throws Exception {
+ logd("TestGetSupportedSatelliteServicesForPlmn_WithoutAllowedServices");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, Integer> dataPlanListMap = new HashMap<>();
+ Map<String, List<Integer>> allowedServiceListMap = new HashMap<>();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, dataPlanListMap, allowedServiceListMap,
+ new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+ // Verify whether the carrier config plmn list is returned with conditions below
+ // the config data plmn list : empty
+ // the carrier config plmn list : exist with services {{2}}
+ setConfigData(new ArrayList<>());
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+ PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+ new PersistableBundle();
+ List<String> carrierConfigPlmnList = List.of("00101");
+ carrierSupportedSatelliteServicesPerProvider.putIntArray(
+ carrierConfigPlmnList.get(0), new int[]{2});
+ mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ carrierSupportedSatelliteServicesPerProvider);
+ invokeCarrierConfigChanged();
+
+ List<Integer> servicesPerPlmn;
+ servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+ SUB_ID, "00101");
+ assertEquals(Arrays.asList(2).stream().sorted().toList(),
+ servicesPerPlmn.stream().sorted().toList());
+ }
+
+ @Test
+ public void testGetSupportedSatelliteDataModeForPlmn_WithEntitlement() throws Exception {
+ logd("testGetSupportedSatelliteDataModeForPlmn_WithEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, Integer> dataServicePolicyMap = Map.of(
+ "00101", SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED,
+ "00102", SATELLITE_DATA_SUPPORT_ALL
+ );
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ dataServicePolicyMap, new HashMap<>(), mIIntegerConsumer);
+
+ int dataSupportModeForPlmn;
+ dataSupportModeForPlmn = mSatelliteControllerUT
+ .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
+ assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn);
+
+ dataSupportModeForPlmn = mSatelliteControllerUT
+ .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00102");
+ assertEquals(SATELLITE_DATA_SUPPORT_ALL, dataSupportModeForPlmn);
+
+ }
+
+ @Test
+ public void testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement() throws Exception {
+ logd("testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement");
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+ replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+ mSatelliteControllerUT, new SparseArray<>());
+ List<String> overlayConfigPlmnList = new ArrayList<>();
+ replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+ mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
+
+ List<String> entitlementPlmnList =
+ Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+ .toList();
+ List<String> barredPlmnList = new ArrayList<>();
+ Map<String, Integer> dataServicePolicyMap = new HashMap<>();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+ dataServicePolicyMap, new HashMap<>(), mIIntegerConsumer);
+
+ mCarrierConfigBundle.putInt(
+ CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+ SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+ int dataSupportModeForPlmn = mSatelliteControllerUT
+ .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
+ assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn);
}
}
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 f15ffbd..529088b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -152,8 +152,10 @@
mServiceState2 = Mockito.mock(ServiceState.class);
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getPhoneId()).thenReturn(PHONE_ID);
+ when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getPhoneId()).thenReturn(PHONE_ID2);
+ when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
mTestSOSMessageRecommender = new TestSOSMessageRecommender(mContext, Looper.myLooper(),
mTestSatelliteController, mTestImsManager);
when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
@@ -266,7 +268,7 @@
@Test
public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent() {
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.setIsSatelliteViaOemProvisioned(false);
+ mTestSatelliteController.setDeviceProvisioned(false);
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
@@ -371,6 +373,7 @@
@Test
public void testSatelliteProvisionStateChangedBeforeTimeout() {
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
@@ -391,6 +394,7 @@
assertFalse(mTestSOSMessageRecommender.isDialerNotified());
reset(mMockSatelliteStats);
+ mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
processAllMessages();
assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -568,20 +572,20 @@
}
@Test
- public void testIsSatelliteViaOemAvailable() {
+ public void testIsDeviceProvisioned() {
Boolean originalIsSatelliteViaOemProvisioned =
- mTestSatelliteController.mIsSatelliteViaOemProvisioned;
+ mTestSatelliteController.mIsDeviceProvisionedForTest;
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = null;
- assertFalse(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = null;
+ assertFalse(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
- assertTrue(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
+ assertTrue(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
- assertFalse(mTestSOSMessageRecommender.isSatelliteViaOemAvailable());
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
+ assertFalse(mTestSOSMessageRecommender.isDeviceProvisioned());
- mTestSatelliteController.mIsSatelliteViaOemProvisioned =
+ mTestSatelliteController.mIsDeviceProvisionedForTest =
originalIsSatelliteViaOemProvisioned;
}
@@ -632,7 +636,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -646,7 +650,7 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -660,13 +664,13 @@
mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = true;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = true;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
- mTestSatelliteController.mIsSatelliteViaOemProvisioned = false;
+ mTestSatelliteController.mIsDeviceProvisionedForTest = false;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
@@ -771,7 +775,7 @@
mProvisionStateChangedCallbacks;
private int mRegisterForSatelliteProvisionStateChangedCalls = 0;
private int mUnregisterForSatelliteProvisionStateChangedCalls = 0;
- private Boolean mIsSatelliteViaOemProvisioned = true;
+ private Boolean mIsDeviceProvisionedForTest = true;
private boolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime = true;
public boolean isOemEnabledSatelliteSupported = true;
public boolean isCarrierEnabledSatelliteSupported = true;
@@ -792,8 +796,8 @@
}
@Override
- public Boolean isSatelliteViaOemProvisioned() {
- return mIsSatelliteViaOemProvisioned;
+ public Boolean isDeviceProvisioned() {
+ return mIsDeviceProvisionedForTest;
}
@Override
@@ -867,12 +871,12 @@
return mUnregisterForSatelliteProvisionStateChangedCalls;
}
- public void setIsSatelliteViaOemProvisioned(boolean provisioned) {
- mIsSatelliteViaOemProvisioned = provisioned;
+ public void setDeviceProvisioned(boolean provisioned) {
+ mIsDeviceProvisionedForTest = provisioned;
}
public void sendProvisionStateChangedEvent(int subId, boolean provisioned) {
- mIsSatelliteViaOemProvisioned = provisioned;
+ mIsDeviceProvisionedForTest = provisioned;
Set<ISatelliteProvisionStateCallback> perSubscriptionCallbacks =
mProvisionStateChangedCallbacks.get(SUB_ID);
if (perSubscriptionCallbacks != null) {
@@ -981,6 +985,8 @@
private ComponentName mSmsAppComponent = new ComponentName(
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS);
private boolean mIsDialerNotified;
+ private boolean mProvisionState = true;
+ private boolean mSatelliteAllowedByReasons = true;
/**
* Create an instance of SatelliteSOSMessageRecommender.
@@ -1015,6 +1021,16 @@
mIsDialerNotified = isDialerNotified;
}
+ @Override
+ protected boolean updateAndGetProvisionState() {
+ return mProvisionState;
+ }
+
+ @Override
+ protected boolean isSatelliteAllowedByReasons() {
+ return mSatelliteAllowedByReasons;
+ }
+
public boolean isTimerStarted() {
return hasMessages(EVENT_TIME_OUT);
}
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 d8daa76..0d11fed 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -39,6 +39,8 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
@@ -50,6 +52,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AlarmManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
@@ -57,12 +60,14 @@
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.internal.R;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
@@ -79,6 +84,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -116,9 +122,12 @@
@Mock private DatagramController mMockDatagramController;
@Mock private ServiceState mMockServiceState;
@Mock private SessionMetricsStats mMockSessionMetricsStats;
+ @Mock private AlarmManager mAlarmManager;
@Captor ArgumentCaptor<Handler> mHandlerCaptor;
@Captor ArgumentCaptor<Integer> mMsgCaptor;
+ @Captor ArgumentCaptor<Executor> mExecutorArgumentCaptor;
+ @Captor ArgumentCaptor<AlarmManager.OnAlarmListener> mOnAlarmListenerArgumentCaptor;
@Before
public void setUp() throws Exception {
@@ -138,7 +147,12 @@
Resources resources = mContext.getResources();
when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
-
+ when(resources.getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning))
+ .thenReturn(false);
+ when(resources.getBoolean(
+ R.bool.config_satellite_allow_tn_scanning_during_satellite_session))
+ .thenReturn(true);
when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
@@ -160,6 +174,7 @@
mTestSatelliteModemStateCallback);
assertSuccessfulModemStateChangedCallback(
mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mTestSatelliteSessionController.setAlarmManager(mAlarmManager);
}
@After
@@ -213,6 +228,13 @@
@Test
public void testScreenOffInactivityTimer() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
@@ -237,11 +259,18 @@
processAllMessages();
clearInvocations(mMockSatelliteController);
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
-
- // Time shift to cause timeout
- moveTimeForward(SCREEN_OFF_INACTIVITY_TIMEOUT_SEC * 1000);
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
+ // Notify alarm expired
+ mExecutorArgumentCaptor.getValue().execute(
+ () -> mOnAlarmListenerArgumentCaptor.getValue().onAlarm());
processAllMessages();
// Verify that SatelliteController#requestSatelliteEnabled() was called.
@@ -252,6 +281,13 @@
@Test
public void testScreenOffInactivityTimerStop() {
when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ // Support P2P_SMS
+ when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
+ anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
doNothing().when(mDeviceStateMonitor).registerForScreenStateChanged(
eq(mTestSatelliteSessionController.getHandler()), anyInt(), any());
// Satellite enabling request is for an emergency.
@@ -287,15 +323,23 @@
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), false);
processAllMessages();
- // Verify that the screen off inactivity timer is started.
- assertTrue(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is set.
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
+ anyLong(),
+ anyString(),
+ mExecutorArgumentCaptor.capture(),
+ any(),
+ mOnAlarmListenerArgumentCaptor.capture()
+ );
// Notify Screen on
sendScreenStateChanged(mHandlerCaptor.getValue(), mMsgCaptor.getValue(), true);
+
processAllMessages();
- // Verify that the screen off inactivity timer is stopped
- assertFalse(mTestSatelliteSessionController.isScreenOffInActivityTimerStarted());
+ // Verify that the screen off inactivity timer is clear.
+ verify(mAlarmManager).cancel(eq(mOnAlarmListenerArgumentCaptor.getValue()));
}
@Test
@@ -306,6 +350,10 @@
when(mMockSatelliteController.getRequestIsEmergency()).thenReturn(false);
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
when(mMockSatelliteController.isInCarrierRoamingNbIotNtn()).thenReturn(true);
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
@@ -400,6 +448,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -483,6 +535,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -558,6 +614,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -625,6 +685,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -670,14 +734,6 @@
// Time shift to cause P2P_SMS timeout
moveTimeForward(P2P_SMS_INACTIVITY_TIMEOUT_SEC * 1000);
processAllMessages();
-
- // Verify that expired P2P_SMS timer
- // reported IDLE state, called satellite disabling.
- verifyEsosP2pSmsInactivityTimer(false, false);
- assertSuccessfulModemStateChangedCallback(
- mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
- verify(mMockSatelliteController, times(1)).requestSatelliteEnabled(
- eq(false), eq(false), eq(false), any(IIntegerConsumer.Stub.class));
}
@Test
@@ -697,6 +753,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -774,6 +834,10 @@
// Support P2P_SMS
when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
anyInt())).thenReturn(true);
+ when(mMockSatelliteController.getSupportedServicesOnCarrierRoamingNtn(anyInt()))
+ .thenReturn(new int[]{
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY});
// Setup carrier config for timer values
PersistableBundle bundle = new PersistableBundle();
@@ -1468,23 +1532,6 @@
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
- // Set up error response for the request to disable cellular scanning
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_MODEM_ERROR);
-
- // Start sending datagrams
- mTestSatelliteSessionController.onDatagramTransferStateChanged(
- SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
- SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- DATAGRAM_TYPE_UNKNOWN);
- processAllMessages();
-
- // SatelliteSessionController should stay at IDLE state because it failed to disable
- // cellular scanning.
- assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
- assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
-
- mSatelliteModemInterface.setErrorCode(SatelliteManager.SATELLITE_RESULT_SUCCESS);
-
// Power off the modem.
mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
processAllMessages();
@@ -1799,6 +1846,283 @@
assertEmergencyModeChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
}
+ @Test
+ public void testNotConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testNotConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(true);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but clients should be
+ // notified that modem has moved to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToTransferringStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ clearInvocations(mMockDatagramController);
+ }
+
+ @Test
+ public void testConnectedToIdleToNotConnectedStateTransition() {
+ when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ when(mContext.getResources().getBoolean(
+ R.bool.config_satellite_modem_support_concurrent_tn_scanning)).thenReturn(true);
+
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report CONNECTED state
+ setupDatagramTransferringState(true);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be started.
+ assertTrue(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Wait for timeout
+ moveTimeForward(TEST_SATELLITE_TIMEOUT_MILLIS);
+ processAllMessages();
+
+ // SatelliteSessionController should move to IDLE state, but the state transition will
+ // be hidden because device does not support satellite modem IDLE state.
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // The inactivity timer should be stopped.
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ // The transition is hidden and thus DatagramController is not notified.
+ verify(mMockDatagramController, never()).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ clearInvocations(mMockDatagramController);
+
+ // Modem report NOT_CONNECTED state
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should stay in IDLE state, but the clients
+ // should be notified that modem has moved to NOT_CONNECTED state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ DATAGRAM_TYPE_UNKNOWN);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
private void verifyEsosP2pSmsInactivityTimer(boolean esosTimer, boolean p2pSmsTimer) {
assertEquals(mTestSatelliteSessionController.isEsosInActivityTimerStarted(), esosTimer);
@@ -1820,9 +2144,9 @@
processAllMessages();
}
- private void setupDatagramTransferringState(boolean isTransferring) {
- when(mMockDatagramController.isSendingInIdleState()).thenReturn(isTransferring);
- when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
+ private void setupDatagramTransferringState(boolean isIdle) {
+ when(mMockDatagramController.isSendingInIdleState()).thenReturn(isIdle);
+ when(mMockDatagramController.isPollingInIdleState()).thenReturn(isIdle);
}
private void powerOnSatelliteModem() {
@@ -2035,10 +2359,6 @@
return hasDeferredMessages(event);
}
- boolean isScreenOffInActivityTimerStarted() {
- return hasMessages(EVENT_SCREEN_OFF_INACTIVITY_TIMER_TIMED_OUT);
- }
-
protected boolean isSatelliteEnabledForNtnOnlySubscription() {
return mSatelliteEnabledForNtnOnlySubscription;
}
@@ -2087,6 +2407,11 @@
logd("onRegistrationFailure: causeCode=" + causeCode);
}
+ @Override
+ public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {
+ logd("onTerrestrialNetworkAvailableChanged: isAvailable=" + isAvailable);
+ }
+
public boolean waitUntilResultForModemStateChanged() {
try {
if (!mSemaphoreForModemStateChanged.tryAcquire(EVENT_PROCESSING_TIME_MILLIS,
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 65790f8..66b2eb8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -70,6 +70,7 @@
import android.Manifest;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PropertyInvalidatedCache;
import android.compat.testing.PlatformCompatChangeRule;
@@ -1123,9 +1124,12 @@
public void testGetAccessibleSubscriptionInfoList() {
doReturn(true).when(mEuiccManager).isEnabled();
insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), any(UserHandle.class));
// FAKE_SUBSCRIPTION_INFO2 is a not eSIM. So the list should be empty.
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEmpty();
@@ -1138,6 +1142,8 @@
doReturn(false).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(false).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
doReturn(true).when(mEuiccManager).isEnabled();
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
@@ -1145,6 +1151,8 @@
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(new SubscriptionInfoInternal.Builder(
FAKE_SUBSCRIPTION_INFO1).setId(2).build().toSubscriptionInfo()));
@@ -1363,6 +1371,9 @@
doReturn(true).when(mEuiccManager).isEnabled();
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
// Test getActiveSubIdList, System
@@ -1499,6 +1510,9 @@
doReturn(true).when(mEuiccManager).isEnabled();
doReturn(true).when(mSubscriptionManager).canManageSubscription(
any(SubscriptionInfo.class), eq(CALLING_PACKAGE));
+ UserHandle user = UserHandle.of(ActivityManager.getCurrentUser());
+ doReturn(true).when(mSubscriptionManager).canManageSubscriptionAsUser(
+ any(SubscriptionInfo.class), eq(CALLING_PACKAGE), eq(user));
assertThat(mSubscriptionManagerServiceUT.getAccessibleSubscriptionInfoList(
CALLING_PACKAGE)).isEqualTo(List.of(FAKE_SUBSCRIPTION_INFO1.toSubscriptionInfo()));
// Test getActiveSubIdList, System
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java
new file mode 100644
index 0000000..2c13d3b
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionPlanTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.subscription;
+
+import static android.telephony.SubscriptionPlan.SUBSCRIPTION_STATUS_ACTIVE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.telephony.SubscriptionPlan;
+import android.testing.AndroidTestingRunner;
+
+import com.android.internal.telephony.flags.Flags;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Period;
+import java.time.ZonedDateTime;
+
+@RunWith(AndroidTestingRunner.class)
+public class SubscriptionPlanTest {
+ private static final ZonedDateTime ZONED_DATE_TIME_START =
+ ZonedDateTime.parse("2007-03-14T00:00:00.000Z");
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderExpirationDateSetsCorrectly() {
+ ZonedDateTime endDate = ZonedDateTime.parse("2024-11-07T00:00:00.000Z");
+
+ SubscriptionPlan planNonRecurring = SubscriptionPlan.Builder
+ .createNonrecurring(ZONED_DATE_TIME_START, endDate)
+ .setTitle("unit test")
+ .build();
+ SubscriptionPlan planRecurring = SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setTitle("unit test")
+ .build();
+
+ assertThat(planNonRecurring.getPlanEndDate()).isEqualTo(endDate);
+ assertNull(planRecurring.getPlanEndDate());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderValidSubscriptionStatusSetsCorrectly() {
+ @SubscriptionPlan.SubscriptionStatus int status = SUBSCRIPTION_STATUS_ACTIVE;
+
+ SubscriptionPlan plan = SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(status)
+ .setTitle("unit test")
+ .build();
+
+ assertThat(plan.getSubscriptionStatus()).isEqualTo(status);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE)
+ public void testBuilderInvalidSubscriptionStatusThrowsError() {
+ int minInvalid = -1;
+ int maxInvalid = 5;
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(minInvalid)
+ .setTitle("unit test")
+ .build();
+ });
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ SubscriptionPlan.Builder
+ .createRecurring(ZONED_DATE_TIME_START, Period.ofMonths(1))
+ .setSubscriptionStatus(maxInvalid)
+ .setTitle("unit test")
+ .build();
+ });
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
index 33b195c..bfdca0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCardTest.java
@@ -69,6 +69,7 @@
@After
public void tearDown() throws Exception {
+ mUiccCard.dispose();
mUiccCard = null;
mIccIoResult = null;
super.tearDown();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 58a8153..3343570 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.telephony.uicc;
-import static junit.framework.Assert.fail;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -131,6 +129,7 @@
@After
public void tearDown() throws Exception {
+ if (mUiccControllerUT != null) mUiccControllerUT.dispose();
mUiccControllerUT = null;
super.tearDown();
}
@@ -145,6 +144,7 @@
com.android.internal.R.array.non_removable_euicc_slots,
nonRemovableEuiccSlots);
replaceInstance(UiccController.class, "mInstance", null, null);
+ mUiccControllerUT.dispose();
mUiccControllerUT = UiccController.make(mContext, mFeatureFlags);
processAllMessages();
}
@@ -250,7 +250,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn(mMockPort).when(mMockCard).getUiccPort(0);
doReturn("A1B2C3D4").when(mMockPort).getIccId();
@@ -296,7 +296,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
// simulate slot status loaded so that the UiccController sets the card ID
@@ -323,7 +323,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
// simulate slot status loaded so that the UiccController sets the card ID
@@ -351,7 +351,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(false).when(mMockSlot).isEuicc();
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn("ASDF1234").when(mMockCard).getCardId();
@@ -402,7 +402,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(false).when(mMockSlot).isEuicc();
doReturn(mMockCard).when(mMockSlot).getUiccCard();
doReturn("ASDF1234").when(mMockCard).getCardId();
@@ -453,7 +453,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(null).when(mMockSlot).getUiccCard();
doReturn(false).when(mMockSlot).isRemovable();
@@ -499,21 +499,17 @@
* The default eUICC should not be the removable slot if there is a built-in eUICC.
*/
@Test
- public void testDefaultEuiccIsNotRemovable() {
- try {
- reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
- } catch (Exception e) {
- fail("Unable to reconfigure slots.");
- }
+ public void testDefaultEuiccIsNotRemovable() throws Exception {
+ reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots so that [0] is a removable eUICC and [1] is built-in
- mUiccControllerUT.mUiccSlots[0] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
@@ -550,21 +546,17 @@
* not depend on the order of the slots.
*/
@Test
- public void testDefaultEuiccIsNotRemovable_swapSlotOrder() {
- try {
- reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */);
- } catch (Exception e) {
- fail("Unable to reconfigure slots.");
- }
+ public void testDefaultEuiccIsNotRemovable_swapSlotOrder() throws Exception {
+ reconfigureSlots(2, new int[]{ 0 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots so that [0] is a built-in eUICC and [1] is removable
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
@@ -603,21 +595,17 @@
* the removable eUICC.
*/
@Test
- public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() {
- try {
- reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
- } catch (Exception e) {
- fail();
- }
+ public void testDefaultEuiccIsNotRemovable_EuiccIsInactive() throws Exception {
+ reconfigureSlots(2, new int[]{ 1 } /* non-removable slot */);
// Give UiccController a real context so it can use shared preferences
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots. Slot 0 is inactive here.
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(false).when(mMockSlot).isRemovable();
- mUiccControllerUT.mUiccSlots[1] = mMockRemovableEuiccSlot;
+ mUiccControllerUT.setUiccSlot(1, mMockRemovableEuiccSlot);
doReturn(true).when(mMockRemovableEuiccSlot).isEuicc();
doReturn(true).when(mMockRemovableEuiccSlot).isRemovable();
@@ -669,7 +657,7 @@
mUiccControllerUT.mContext = InstrumentationRegistry.getContext();
// Mock out UiccSlots
- mUiccControllerUT.mUiccSlots[0] = mMockSlot;
+ mUiccControllerUT.setUiccSlot(0, mMockSlot);
doReturn(true).when(mMockSlot).isEuicc();
doReturn(null).when(mMockSlot).getUiccCard();
//doReturn("123451234567890").when(mMockSlot).getIccId();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index a2b42af..47b7c53 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -82,6 +82,7 @@
@After
public void tearDown() throws Exception {
+ mUiccPort.dispose();
mUiccPort = null;
mIccIoResult = null;
super.tearDown();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index 671f273..8449ecc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -103,6 +103,7 @@
mTestHandlerThread = null;
mTestHandler.removeCallbacksAndMessages(null);
mTestHandler = null;
+ mUiccSlot.dispose();
mUiccSlot = null;
super.tearDown();
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
index f88bc1e..c9b159c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
@@ -51,6 +51,8 @@
private static final int CARD_COUNT = 1;
private static final String PROVISIONING_PACKAGE_NAME = "test.provisioning.package";
+ private UiccCard mUiccCardToDispose;
+
// Mocked classes
private Resources mResources;
@@ -77,6 +79,9 @@
@After
public void tearDown() throws Exception {
super.tearDown();
+
+ if (mUiccCardToDispose != null) mUiccCardToDispose.dispose();
+ mUiccCardToDispose = null;
}
@Test @SmallTest
@@ -99,7 +104,7 @@
msg.what = integerArgumentCaptor.getValue();
// The first broadcast should be sent after initialization.
- UiccCard card = new UiccCard(mContext, mSimulatedCommands,
+ UiccCard card = mUiccCardToDispose = new UiccCard(mContext, mSimulatedCommands,
makeCardStatus(CardState.CARDSTATE_PRESENT), 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
when(UiccController.getInstance().getUiccCardForPhone(0)).thenReturn(card);
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 bcb5c4c..560c9aa 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
@@ -109,7 +109,10 @@
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
- mEuiccCard = null;
+ if (mEuiccCard != null) {
+ mEuiccCard.dispose();
+ mEuiccCard = null;
+ }
super.tearDown();
}
@@ -132,6 +135,7 @@
@Test
public void testPassEidInConstructor() {
mMockIccCardStatus.eid = "1A2B3C4D";
+ mEuiccCard.dispose();
mEuiccCard = new EuiccCard(mContextFixture.getTestDouble(), mMockCi,
mMockIccCardStatus, 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
@@ -154,6 +158,7 @@
public void testLoadEidAndNotifyRegistrants() {
int channel = mockLogicalChannelResponses("BF3E065A041A2B3C4D9000");
mHandler.post(() -> {
+ mEuiccCard.dispose();
mEuiccCard = new EuiccCard(mContextFixture.getTestDouble(), mMockCi,
mMockIccCardStatus, 0 /* phoneId */, new Object(),
IccSlotStatus.MultipleEnabledProfilesMode.NONE);
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 2fef021..f0f1af3 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
@@ -141,6 +141,7 @@
public void tearDown() throws Exception {
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
+ mEuiccPort.dispose();
mEuiccPort = null;
super.tearDown();
}