Merge "Implement callingUser propagation in outgoing SMS impl class" into main
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 80d6f61..a993d51 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -34,53 +34,6 @@
}
}
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "use_alarm_callback"
- namespace: "telephony"
- description: "Use alarm callback instead of broadcast."
- bug: "311476875"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "refine_preferred_data_profile_selection"
- namespace: "telephony"
- description: "Upon internet network connect, refine selection of preferred data profile."
- bug: "311476883"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "unthrottle_check_transport"
- namespace: "telephony"
- description: "Check transport when unthrottle."
- bug: "303922311"
-}
-
-# OWNER=linggm TARGET=24Q1
-flag {
- name: "relax_ho_teardown"
- namespace: "telephony"
- description: "Relax handover tear down if the device is currently in voice call."
- bug: "270895912"
-}
-
-# OWNER=linggm TARGET=24Q2
-flag {
- name: "allow_mmtel_in_non_vops"
- namespace: "telephony"
- description: "Allow bring up MMTEL in nonVops area specified by carrier config."
- bug: "241198464"
-}
-
-# OWNER=jackyu TARGET=24Q2
-flag {
- name: "metered_embb_urlcc"
- namespace: "telephony"
- description: "Force networks that have PRIORITIZE_BANDWIDTH or PRIORITIZE_LATENCY to be metered."
- bug: "301310451"
- }
# OWNER=sarahchin TARGET=24Q3
flag {
@@ -109,14 +62,6 @@
bug:"286171724"
}
-# OWNER=nagendranb TARGET=24Q2
-flag {
- name: "notify_data_activity_changed_with_slot"
- namespace: "telephony"
- description: "notify data activity changed for slot id"
- bug: "309896936"
-}
-
# OWNER=qingqi TARGET=24Q3
flag {
name: "vonr_enabled_metric"
@@ -125,14 +70,6 @@
bug:"288449751"
}
-# OWNER=willycwhu TARGET=24Q2
-flag {
- name: "ignore_existing_networks_for_internet_allowed_checking"
- namespace: "telephony"
- description: "Ignore existing networks when checking if internet is allowed"
- bug: "284420611"
-}
-
# OWNER=apsankar TARGET=24Q3
flag {
name: "data_call_session_stats_captures_cross_sim_calling"
@@ -141,14 +78,6 @@
bug: "313956117"
}
-# OWNER=jackyu TARGET=24Q2
-flag {
- name: "force_iwlan_mms"
- namespace: "telephony"
- description: "When QNS prefers MMS on IWLAN, MMS will be attempted on IWLAN if it can, even though if existing cellular network already supports MMS."
- bug: "316211526"
-}
-
# OWNER=sewook TARGET=24Q3
flag {
name: "reconnect_qualified_network"
@@ -181,4 +110,14 @@
bug:"353723350"
}
+# OWNER=jackyu TARGET=25Q1
+flag {
+ name: "support_network_provider"
+ namespace: "telephony"
+ description: "Deprecate network factory and adapt the new network provider model from connectivity service"
+ bug: "343370895"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index cf10c92..f41fad3 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -69,3 +69,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=mewan TARGET=24Q4
+flag {
+ name: "optimization_apdu_sender"
+ namespace: "telephony"
+ description: "This flag controls optimization of apdu sender class."
+ bug:"335257880"
+}
diff --git a/src/java/com/android/internal/telephony/CarrierActionAgent.java b/src/java/com/android/internal/telephony/CarrierActionAgent.java
index 7bb89d0..c4ba77d 100644
--- a/src/java/com/android/internal/telephony/CarrierActionAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierActionAgent.java
@@ -258,6 +258,8 @@
return mCarrierActionOnRadioEnabled;
case CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS:
return mCarrierActionReportDefaultNetworkStatus;
+ case EVENT_APN_SETTINGS_CHANGED:
+ return null; // we don't know if it's enabled, but this is not "unsupported" action
default:
loge("Unsupported action: " + action);
return null;
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index a6d24f2..da17f60 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -135,13 +135,9 @@
int subId = sender.getSubId();
- if (mFeatureFlags.notifyDataActivityChangedWithSlot()) {
- int phoneId = sender.getPhoneId();
- mTelephonyRegistryMgr.notifyDataActivityChanged(phoneId, subId,
- sender.getDataActivityState());
- } else {
- mTelephonyRegistryMgr.notifyDataActivityChanged(subId, sender.getDataActivityState());
- }
+ int phoneId = sender.getPhoneId();
+ mTelephonyRegistryMgr.notifyDataActivityChanged(phoneId, subId,
+ sender.getDataActivityState());
}
@Override
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 2cd6021..f7ce388 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -46,6 +46,7 @@
import com.android.internal.telephony.data.CellularNetworkValidator;
import com.android.internal.telephony.data.PhoneSwitcher;
import com.android.internal.telephony.data.TelephonyNetworkFactory;
+import com.android.internal.telephony.data.TelephonyNetworkProvider;
import com.android.internal.telephony.euicc.EuiccCardController;
import com.android.internal.telephony.euicc.EuiccController;
import com.android.internal.telephony.flags.FeatureFlags;
@@ -101,6 +102,7 @@
static private SimultaneousCallingTracker sSimultaneousCallingTracker;
static private PhoneSwitcher sPhoneSwitcher;
static private TelephonyNetworkFactory[] sTelephonyNetworkFactories;
+ private static TelephonyNetworkProvider sTelephonyNetworkProvider;
static private NotificationChannelController sNotificationChannelController;
static private CellularNetworkValidator sCellularNetworkValidator;
@@ -285,9 +287,15 @@
sNotificationChannelController = new NotificationChannelController(context);
- for (int i = 0; i < numPhones; i++) {
- sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i], featureFlags);
+ if (featureFlags.supportNetworkProvider()) {
+ // Create the TelephonyNetworkProvider instance, which is a singleton.
+ sTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
+ context, featureFlags);
+ } else {
+ for (int i = 0; i < numPhones; i++) {
+ sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+ Looper.myLooper(), sPhones[i], featureFlags);
+ }
}
}
}
@@ -312,7 +320,10 @@
sPhones = copyOf(sPhones, activeModemCount);
sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount);
- sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
+ }
int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
for (int i = prevActiveModemCount; i < activeModemCount; i++) {
@@ -324,8 +335,11 @@
PackageManager.FEATURE_TELEPHONY_IMS)) {
sPhones[i].createImsPhone();
}
- sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
- Looper.myLooper(), sPhones[i], sFeatureFlags);
+
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
+ Looper.myLooper(), sPhones[i], sFeatureFlags);
+ }
}
}
}
@@ -393,6 +407,10 @@
}
}
+ public static TelephonyNetworkProvider getNetworkProvider() {
+ return sTelephonyNetworkProvider;
+ }
+
/**
* Get the network factory associated with a given phone ID.
* @param phoneId the phone id
@@ -579,13 +597,22 @@
pw.flush();
pw.println("++++++++++++++++++++++++++++++++");
- sTelephonyNetworkFactories[i].dump(fd, pw, args);
+ if (!sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkFactories[i].dump(fd, pw, args);
+ }
pw.flush();
pw.decreaseIndent();
pw.println("++++++++++++++++++++++++++++++++");
}
+ pw.increaseIndent();
+ if (sFeatureFlags.supportNetworkProvider()) {
+ sTelephonyNetworkProvider.dump(fd, pw, args);
+ }
+ pw.decreaseIndent();
+ pw.println("++++++++++++++++++++++++++++++++");
+
pw.println("UiccController:");
pw.increaseIndent();
try {
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8abebe2..de33753 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -4374,9 +4374,9 @@
riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+ " params: " + carrierRestrictionRules);
}
-
radioServiceInvokeHelper(HAL_SERVICE_SIM, rr, "setAllowedCarriers", () -> {
- simProxy.setAllowedCarriers(rr.mSerial, carrierRestrictionRules);
+ simProxy.setAllowedCarriers(rr.mSerial, carrierRestrictionRules,
+ getHalVersion(HAL_SERVICE_SIM));
});
}
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 8897db4..a81dbc8 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -1944,6 +1944,31 @@
}
/**
+ * Convert a list of CarrierIdentifiers into an array of CarrierInfo.aidl
+ *
+ * @param carriers List of CarrierIdentifiers
+ * @return The converted array of CarrierInfos.
+ */
+ public static android.hardware.radio.sim.CarrierInfo[] convertToHalCarrierInfoListAidl(
+ List<CarrierIdentifier> carriers) {
+ android.hardware.radio.sim.CarrierInfo[] result =
+ new android.hardware.radio.sim.CarrierInfo[carriers.size()];
+ for (int i = 0; i < carriers.size(); i++) {
+ CarrierIdentifier ci = carriers.get(i);
+ android.hardware.radio.sim.CarrierInfo carrierInfo =
+ new android.hardware.radio.sim.CarrierInfo();
+ carrierInfo.mcc = convertNullToEmptyString(ci.getMcc());
+ carrierInfo.mnc = convertNullToEmptyString(ci.getMnc());
+ carrierInfo.spn = ci.getSpn();
+ carrierInfo.imsiPrefix = ci.getImsi();
+ carrierInfo.gid1 = ci.getGid1();
+ carrierInfo.gid2 = ci.getGid2();
+ result[i] = carrierInfo;
+ }
+ return result;
+ }
+
+ /**
* Convert to Dial defined in radio/1.0/types.hal
* @param address Address
* @param clirMode CLIR mode
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index da20639..b4db14c 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -466,7 +466,7 @@
RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_DATA_MODEM,
result, mDefaultWorkSource);
if (DBG) {
- logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+ logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest) + " " + modemId);
}
try {
proxy.setPreferredDataModem(rr.mSerial, modemId);
diff --git a/src/java/com/android/internal/telephony/RadioSimProxy.java b/src/java/com/android/internal/telephony/RadioSimProxy.java
index 9bf9a50..1c864fe 100644
--- a/src/java/com/android/internal/telephony/RadioSimProxy.java
+++ b/src/java/com/android/internal/telephony/RadioSimProxy.java
@@ -24,6 +24,8 @@
import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
import com.android.internal.telephony.uicc.SimPhonebookRecord;
+import java.util.Collections;
+
/**
* A holder for IRadioSim.
* Use getAidl to get IRadioSim and call the AIDL implementations of the HAL APIs.
@@ -512,21 +514,36 @@
/**
* Call IRadioSim#setAllowedCarriers
- * @param serial Serial number of request
+ *
+ * @param serial Serial number of request
* @param carrierRestrictionRules Allowed carriers
- * @throws RemoteException
*/
- public void setAllowedCarriers(int serial, CarrierRestrictionRules carrierRestrictionRules)
- throws RemoteException {
+ public void setAllowedCarriers(int serial, CarrierRestrictionRules carrierRestrictionRules,
+ HalVersion halversion) throws RemoteException {
if (isEmpty()) return;
if (isAidl()) {
- // Prepare structure with allowed list, excluded list and priority
android.hardware.radio.sim.CarrierRestrictions carrierRestrictions =
new android.hardware.radio.sim.CarrierRestrictions();
- carrierRestrictions.allowedCarriers = RILUtils.convertToHalCarrierRestrictionListAidl(
- carrierRestrictionRules.getAllowedCarriers());
- carrierRestrictions.excludedCarriers = RILUtils.convertToHalCarrierRestrictionListAidl(
- carrierRestrictionRules.getExcludedCarriers());
+ if (halversion.greaterOrEqual(RIL.RADIO_HAL_VERSION_2_2)) {
+ carrierRestrictions.allowedCarrierInfoList =
+ RILUtils.convertToHalCarrierInfoListAidl(
+ carrierRestrictionRules.getAllowedCarriers());
+ carrierRestrictions.excludedCarrierInfoList =
+ RILUtils.convertToHalCarrierInfoListAidl(
+ carrierRestrictionRules.getExcludedCarriers());
+ carrierRestrictions.allowedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(Collections.EMPTY_LIST);
+ carrierRestrictions.excludedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(Collections.EMPTY_LIST);
+ } else {
+ // Prepare structure with allowed list, excluded list and priority
+ carrierRestrictions.allowedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(
+ carrierRestrictionRules.getAllowedCarriers());
+ carrierRestrictions.excludedCarriers =
+ RILUtils.convertToHalCarrierRestrictionListAidl(
+ carrierRestrictionRules.getExcludedCarriers());
+ }
carrierRestrictions.allowedCarriersPrioritized =
(carrierRestrictionRules.getDefaultCarrierRestriction()
== CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED);
@@ -534,6 +551,7 @@
mSimProxy.setAllowedCarriers(serial, carrierRestrictions,
RILUtils.convertToHalSimLockMultiSimPolicyAidl(
carrierRestrictionRules.getMultiSimPolicy()));
+ Rlog.d(TAG, "RadioSimProxy setAllowedCarriers params = " + carrierRestrictions);
} else {
// Prepare structure with allowed list, excluded list and priority
android.hardware.radio.V1_4.CarrierRestrictionsWithPriority carrierRestrictions =
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index e2f5980..e7500a2 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -1164,6 +1164,9 @@
mDesiredPowerState = power;
setPowerStateToDesired(forEmergencyCall, isSelectedPhoneForEmergencyCall, forceApply);
+ if (mDesiredPowerState) {
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(true);
+ }
}
/**
@@ -1325,6 +1328,12 @@
// Hence, issuing shut down regardless of radio power response
mCi.requestShutdown(null);
}
+
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception != null) {
+ loge("EVENT_RADIO_POWER_OFF_DONE: exception=" + ar.exception);
+ SatelliteController.getInstance().onPowerOffCellularRadioFailed();
+ }
break;
// GSM
@@ -4979,7 +4988,7 @@
*/
public void powerOffRadioSafely() {
synchronized (this) {
- SatelliteController.getInstance().onCellularRadioPowerOffRequested();
+ SatelliteController.getInstance().onSetCellularRadioPowerStateRequested(false);
if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
EmergencyStateTracker.getInstance().onCellularRadioPowerOffRequested();
}
diff --git a/src/java/com/android/internal/telephony/SimResponse.java b/src/java/com/android/internal/telephony/SimResponse.java
index 59defc3..97692a0 100644
--- a/src/java/com/android/internal/telephony/SimResponse.java
+++ b/src/java/com/android/internal/telephony/SimResponse.java
@@ -112,7 +112,7 @@
android.hardware.radio.sim.CarrierRestrictions carrierRestrictions,
int multiSimPolicy) {
RILRequest rr = mRil.processResponse(HAL_SERVICE_SIM, responseInfo);
- boolean carrierLockInfoSupported = mRil.getHalVersion(HAL_SERVICE_SIM).greater(
+ boolean carrierLockInfoSupported = mRil.getHalVersion(HAL_SERVICE_SIM).greaterOrEqual(
RIL.RADIO_HAL_VERSION_2_2);
if (rr == null) {
return;
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index d9ddde0..89b0fec 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -643,10 +643,8 @@
// Consumer slices are the slices that are allowed to be accessed by regular application to
// get better performance. They should be metered. This can be turned into configurations in
// the future.
- if (mFeatureFlags.meteredEmbbUrlcc()) {
- meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
- meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
- }
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
+ meteredCapabilities.add(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
return Collections.unmodifiableSet(meteredCapabilities);
}
@@ -761,7 +759,6 @@
*/
public boolean allowBringUpNetworkInNonVops(@NetworkRegistrationInfo.RegistrationState
int regState) {
- if (!mFeatureFlags.allowMmtelInNonVops()) return false;
int networkType = -1;
if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
networkType = CarrierConfigManager.Ims.NETWORK_TYPE_HOME;
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 2f0c0ff..738c60f 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -100,6 +100,7 @@
import com.android.internal.telephony.data.DataRetryManager.DataRetryEntry;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
import com.android.internal.telephony.data.TelephonyNetworkAgent.TelephonyNetworkAgentCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DataCallSessionStats;
@@ -271,6 +272,9 @@
/** Event for response to data network validation request. */
private static final int EVENT_DATA_NETWORK_VALIDATION_RESPONSE = 29;
+ /** Event for preferred data subscription changed. */
+ private static final int EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED = 30;
+
/** Invalid context id. */
private static final int INVALID_CID = -1;
@@ -591,6 +595,10 @@
@NonNull
private final DataNetworkController mDataNetworkController;
+ /** Phone switcher which is responsible to determine which phone to route network request. */
+ @NonNull
+ private final PhoneSwitcher mPhoneSwitcher;
+
/** Data network controller callback. */
@NonNull
private final DataNetworkController.DataNetworkControllerCallback
@@ -676,6 +684,13 @@
/** Whether the current data network is congested. */
private boolean mCongested = false;
+ /**
+ * Whether the current data network is on preferred data modem.
+ *
+ * @see PhoneSwitcher#getPreferredDataPhoneId()
+ */
+ private boolean mOnPreferredDataPhone;
+
/** The network requests associated with this data network */
@NonNull
private final NetworkRequestList mAttachedNetworkRequestList =
@@ -815,6 +830,12 @@
private PreciseDataConnectionState mPreciseDataConnectionState;
/**
+ * Callback to listen event from {@link PhoneSwitcher}.
+ */
+ @NonNull
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
+ /**
* The network bandwidth.
*/
public static class NetworkBandwidth {
@@ -1027,6 +1048,8 @@
mAccessNetworksManager = phone.getAccessNetworksManager();
mVcnManager = mPhone.getContext().getSystemService(VcnManager.class);
mDataNetworkController = phone.getDataNetworkController();
+ mPhoneSwitcher = PhoneSwitcher.getInstance();
+ mOnPreferredDataPhone = phone.getPhoneId() == mPhoneSwitcher.getPreferredDataPhoneId();
mDataNetworkControllerCallback = new DataNetworkController.DataNetworkControllerCallback(
getHandler()::post) {
@Override
@@ -1156,14 +1179,25 @@
configBuilder.setNat64DetectionEnabled(false);
}
- final NetworkFactory factory = PhoneFactory.getNetworkFactory(
- mPhone.getPhoneId());
- final NetworkProvider provider = (null == factory) ? null : factory.getProvider();
+ NetworkProvider provider;
+ if (mFlags.supportNetworkProvider()) {
+ provider = PhoneFactory.getNetworkProvider();
+ } else {
+ final NetworkFactory factory = PhoneFactory.getNetworkFactory(
+ mPhone.getPhoneId());
+ provider = (null == factory) ? null : factory.getProvider();
+ }
- mNetworkScore = new NetworkScore.Builder()
- .setKeepConnectedReason(isHandoverInProgress()
+ NetworkScore.Builder builder = new NetworkScore.Builder()
+ .setKeepConnectedReason(isHandoverInProgress()
? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER
- : NetworkScore.KEEP_CONNECTED_NONE).build();
+ : NetworkScore.KEEP_CONNECTED_NONE);
+ if (mFlags.supportNetworkProvider()) {
+ builder.setTransportPrimary(mOnPreferredDataPhone);
+ }
+ mNetworkScore = builder.build();
+ logl("mNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
+ + ", keepConnectedReason=" + mNetworkScore.getKeepConnectedReason());
return new TelephonyNetworkAgent(mPhone, getHandler().getLooper(), this,
mNetworkScore, configBuilder.build(), provider,
@@ -1225,6 +1259,16 @@
mDataNetworkController.getDataSettingsManager()
.registerCallback(mDataSettingsManagerCallback);
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcherCallback = new PhoneSwitcherCallback(Runnable::run) {
+ @Override
+ public void onPreferredDataPhoneIdChanged(int phoneId) {
+ sendMessage(EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED, phoneId, 0);
+ }
+ };
+ mPhoneSwitcher.registerCallback(mPhoneSwitcherCallback);
+ }
+
mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(
getHandler(), EVENT_DISPLAY_INFO_CHANGED, null);
mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(),
@@ -1266,21 +1310,19 @@
getHandler(), EVENT_VOICE_CALL_ENDED, null);
}
- if (mFlags.forceIwlanMms()) {
- if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
- mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
- getHandler()::post) {
- @Override
- public void onPreferredTransportChanged(
- @NetCapability int networkCapability, boolean forceReconnect) {
- if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) {
- log("MMS preference changed.");
- updateNetworkCapabilities();
- }
+ if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
+ getHandler()::post) {
+ @Override
+ public void onPreferredTransportChanged(
+ @NetCapability int networkCapability, boolean forceReconnect) {
+ if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) {
+ log("MMS preference changed.");
+ updateNetworkCapabilities();
}
- };
- mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
- }
+ }
+ };
+ mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
}
// Only add symmetric code here, for example, registering and unregistering.
@@ -1292,7 +1334,7 @@
@Override
public void exit() {
logv("Unregistering all events.");
- if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) {
+ if (mAccessNetworksManagerCallback != null) {
mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
}
@@ -1318,6 +1360,9 @@
mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler());
mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(
getHandler());
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcher.unregisterCallback(mPhoneSwitcherCallback);
+ }
mDataNetworkController.getDataSettingsManager()
.unregisterCallback(mDataSettingsManagerCallback);
mRil.unregisterForPcoData(getHandler());
@@ -1351,13 +1396,13 @@
}
case EVENT_ATTACH_NETWORK_REQUEST: {
onAttachNetworkRequests((NetworkRequestList) msg.obj);
- updateNetworkScore(isHandoverInProgress());
+ updateNetworkScore();
break;
}
case EVENT_DETACH_NETWORK_REQUEST: {
onDetachNetworkRequest((TelephonyNetworkRequest) msg.obj,
msg.arg1 != 0 /* shouldRetry */);
- updateNetworkScore(isHandoverInProgress());
+ updateNetworkScore();
break;
}
case EVENT_DETACH_ALL_NETWORK_REQUESTS: {
@@ -1428,6 +1473,12 @@
// handle the resultCode in response for the request.
handleDataNetworkValidationRequestResultCode(msg.arg1 /* resultCode */);
break;
+ case EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED:
+ mOnPreferredDataPhone = mPhone.getPhoneId() == msg.arg1;
+ logl("Preferred data phone id changed to " + msg.arg1
+ + ", mOnPreferredDataPhone=" + mOnPreferredDataPhone);
+ updateNetworkScore();
+ break;
default:
loge("Unhandled event " + eventToString(msg.what));
break;
@@ -2355,14 +2406,7 @@
DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
// Check if the network is non-VoPS.
if (dsri != null && dsri.getVopsSupportInfo() != null
- && !dsri.getVopsSupportInfo().isVopsSupported()
- // Reflect the actual MMTEL if flag on.
- && (mFlags.allowMmtelInNonVops()
- // Deceive Connectivity service to satisfy an MMTEL request, this should
- // be useless because we reach here if no MMTEL request, then removing
- // MMTEL capability shouldn't have any impacts.
- || !mDataConfigManager.shouldKeepNetworkUpInNonVops(
- nri.getNetworkRegistrationState()))) {
+ && !dsri.getVopsSupportInfo().isVopsSupported()) {
builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
}
log("updateNetworkCapabilities: dsri=" + dsri);
@@ -2490,8 +2534,7 @@
// Check if the feature force MMS on IWLAN is enabled. When the feature is enabled, MMS
// will be attempted on IWLAN if possible, even if existing cellular networks already
// supports IWLAN.
- if (mFlags.forceIwlanMms() && builder.build()
- .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ if (builder.build().hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
// If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on
// IWLAN, then we need to remove the MMS capability on the cellular network. This will
// allow the new MMS network to be brought up on IWLAN when MMS network request arrives.
@@ -3314,6 +3357,12 @@
return mLinkStatus;
}
+ /**
+ * Update the network score and report to connectivity service if necessary.
+ */
+ private void updateNetworkScore() {
+ updateNetworkScore(isHandoverInProgress());
+ }
/**
* Update the network score and report to connectivity service if necessary.
@@ -3323,10 +3372,18 @@
private void updateNetworkScore(boolean keepConnectedForHandover) {
int connectedReason = keepConnectedForHandover
? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER : NetworkScore.KEEP_CONNECTED_NONE;
- if (mNetworkScore.getKeepConnectedReason() != connectedReason) {
- mNetworkScore = new NetworkScore.Builder()
- .setKeepConnectedReason(connectedReason).build();
+ if (mNetworkScore.getKeepConnectedReason() != connectedReason
+ || (mFlags.supportNetworkProvider()
+ && mNetworkScore.isTransportPrimary() != mOnPreferredDataPhone)) {
+ NetworkScore.Builder builder = new NetworkScore.Builder()
+ .setKeepConnectedReason(connectedReason);
+ if (mFlags.supportNetworkProvider()) {
+ builder.setTransportPrimary(mOnPreferredDataPhone);
+ }
+ mNetworkScore = builder.build();
mNetworkAgent.sendNetworkScore(mNetworkScore);
+ logl("updateNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
+ + ", keepConnectedForHandover=" + keepConnectedForHandover);
}
}
@@ -4055,12 +4112,14 @@
pw.println("Tag: " + name());
pw.increaseIndent();
pw.println("mSubId=" + mSubId);
+ pw.println("mOnPreferredDataPhone=" + mOnPreferredDataPhone);
pw.println("mTransport=" + AccessNetworkConstants.transportTypeToString(mTransport));
pw.println("mLastKnownDataNetworkType=" + TelephonyManager
.getNetworkTypeName(mLastKnownDataNetworkType));
pw.println("WWAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
pw.println("WLAN cid=" + mCid.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
pw.println("mNetworkScore=" + mNetworkScore);
+ pw.println("keepConnectedReason=" + mNetworkScore.getKeepConnectedReason());
pw.println("mDataAllowedReason=" + mDataAllowedReason);
pw.println("mPduSessionId=" + mPduSessionId);
pw.println("mDataProfile=" + mDataProfile);
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 4d1786b..89153ab 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1299,6 +1299,13 @@
* @param networkRequest The network request.
*/
private void onAddNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
+ // TelephonyNetworkRequest at TelephonyNetworkProvider layer does not have config assigned
+ // (Because TelephonyNetworkProvider is a singleton across all SIMs. We are not able to
+ // retrieve the right carrier config for it.). So as soon as the request arrives
+ // DataNetworkController, we need to update the config in the request so it can update
+ // some of its config-dependent properties like request priority.
+ networkRequest.updateDataConfig(mDataConfigManager);
+
// To detect IMS back-to-back release-request anomaly event
if (mLastImsOperationIsRelease) {
mLastImsOperationIsRelease = false;
@@ -1501,11 +1508,9 @@
.build(), mPhone, mFeatureFlags);
// If we don't skip checking existing network, then we should check If one of the
// existing networks can satisfy the internet request, then internet is allowed.
- if ((!mFeatureFlags.ignoreExistingNetworksForInternetAllowedChecking()
- || !ignoreExistingNetworks)
- && mDataNetworkList.stream().anyMatch(
- dataNetwork -> internetRequest.canBeSatisfiedBy(
- dataNetwork.getNetworkCapabilities()))) {
+ if (!ignoreExistingNetworks && mDataNetworkList.stream().anyMatch(
+ dataNetwork -> internetRequest.canBeSatisfiedBy(
+ dataNetwork.getNetworkCapabilities()))) {
return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY);
}
@@ -1746,7 +1751,9 @@
// Check if request is unmetered (WiFi or unmetered APN).
evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
} else if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
- if (!networkRequest.isMeteredRequest()) {
+ boolean isMeteredRequest = mDataConfigManager.isAnyMeteredCapability(
+ networkRequest.getCapabilities(), mServiceState.getDataRoaming());
+ if (!isMeteredRequest) {
evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
}
}
@@ -2507,6 +2514,30 @@
}
private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest request) {
+ if (mFeatureFlags.supportNetworkProvider()) {
+ if (!mAllNetworkRequestList.remove(request)) {
+ loge("onRemoveNetworkRequest: Network request does not exist. " + request);
+ return;
+ }
+
+ if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+ mImsThrottleCounter.addOccurrence();
+ mLastReleasedImsRequestCapabilities = request.getCapabilities();
+ mLastImsOperationIsRelease = true;
+ }
+
+ if (request.getAttachedNetwork() != null) {
+ request.getAttachedNetwork().detachNetworkRequest(
+ request, false /* shouldRetry */);
+ }
+
+ request.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+ request.setEvaluation(null);
+
+ log("onRemoveNetworkRequest: Removed " + request);
+ return;
+ }
+
// The request generated from telephony network factory does not contain the information
// the original request has, for example, attached data network. We need to find the
// original one.
@@ -2527,7 +2558,7 @@
if (networkRequest.getAttachedNetwork() != null) {
networkRequest.getAttachedNetwork().detachNetworkRequest(
- networkRequest, false /* shouldRetry */);
+ networkRequest, false /* shouldRetry */);
}
log("onRemoveNetworkRequest: Removed " + networkRequest);
}
@@ -3610,8 +3641,7 @@
dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry);
} else if (dataNetwork.shouldDelayImsTearDownDueToInCall()
&& (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE)
- || mFeatureFlags.relaxHoTeardown() && dataEvaluation.isSubsetOf(
- DataDisallowedReason.NOT_IN_SERVICE,
+ || dataEvaluation.isSubsetOf(DataDisallowedReason.NOT_IN_SERVICE,
DataDisallowedReason.NOT_ALLOWED_BY_POLICY))) {
// We try our best to preserve the voice call by retrying later
if (dataHandoverRetryEntry != null) {
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index c50d50a..28fe935 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -432,35 +432,18 @@
*/
private void onInternetDataNetworkConnected(@NonNull Set<DataNetwork> internetNetworks) {
DataProfile defaultProfile = null;
- if (mFeatureFlags.refinePreferredDataProfileSelection()) {
- // Most of the cases there should be only one.
- // but in case there are multiple, find the default internet network, and choose the
- // one which has longest life cycle.
- defaultProfile = internetNetworks.stream()
- .filter(network -> mPreferredDataProfile == null
- // Find the one most resembles the current preferred profile,
- // avoiding e.g. DUN default network.
- || canPreferredDataProfileSatisfy(
- network.getAttachedNetworkRequestList()))
- .map(DataNetwork::getDataProfile)
- .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
- .orElse(null);
- } else {
- if (internetNetworks.size() == 1) {
- // Most of the cases there should be only one.
- defaultProfile = internetNetworks.stream().findFirst().get().getDataProfile();
- } else if (internetNetworks.size() > 1) {
- // but in case there are multiple, find the default internet network, and choose the
- // one which has longest life cycle.
- defaultProfile = internetNetworks.stream()
- .filter(network -> mPreferredDataProfile == null
- || canPreferredDataProfileSatisfy(
- network.getAttachedNetworkRequestList()))
- .map(DataNetwork::getDataProfile)
- .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
- .orElse(null);
- }
- }
+ // Most of the cases there should be only one.
+ // but in case there are multiple, find the default internet network, and choose the
+ // one which has longest life cycle.
+ defaultProfile = internetNetworks.stream()
+ .filter(network -> mPreferredDataProfile == null
+ // Find the one most resembles the current preferred profile,
+ // avoiding e.g. DUN default network.
+ || canPreferredDataProfileSatisfy(
+ network.getAttachedNetworkRequestList()))
+ .map(DataNetwork::getDataProfile)
+ .min(Comparator.comparingLong(DataProfile::getLastSetupTimestamp))
+ .orElse(null);
// Update a working internet data profile by subid as a future candidate for preferred
// data profile after APNs are reset to default
diff --git a/src/java/com/android/internal/telephony/data/DataRetryManager.java b/src/java/com/android/internal/telephony/data/DataRetryManager.java
index 2a009c8..318c4b5 100644
--- a/src/java/com/android/internal/telephony/data/DataRetryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataRetryManager.java
@@ -22,11 +22,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.NetworkCapabilities;
import android.os.AsyncResult;
import android.os.Handler;
@@ -79,11 +74,6 @@
public class DataRetryManager extends Handler {
private static final boolean VDBG = false;
- /** Intent of Alarm Manager for long retry timer. */
- private static final String ACTION_RETRY = "com.android.internal.telephony.data.ACTION_RETRY";
- /** The extra key for the hashcode of the retry entry for Alarm Manager. */
- private static final String ACTION_RETRY_EXTRA_HASHCODE = "extra_retry_hashcode";
-
/** Event for data setup retry. */
private static final int EVENT_DATA_SETUP_RETRY = 3;
@@ -1078,22 +1068,6 @@
mRil.registerForOn(this, EVENT_RADIO_ON, null);
mRil.registerForModemReset(this, EVENT_MODEM_RESET, null);
- if (!mFlags.useAlarmCallback()) {
- // Register intent of alarm manager for long retry timer
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_RETRY);
- mPhone.getContext().registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_RETRY.equals(intent.getAction())) {
- DataRetryManager.this.onAlarmIntentRetry(
- intent.getIntExtra(ACTION_RETRY_EXTRA_HASHCODE,
- -1 /*Bad hashcode*/));
- }
- }
- }, intentFilter);
- }
-
if (mDataConfigManager.shouldResetDataThrottlingWhenTacChanges()) {
mPhone.getServiceStateTracker().registerForAreaCodeChanged(this, EVENT_TAC_CHANGED,
null);
@@ -1531,32 +1505,19 @@
? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY, dataRetryEntry),
dataRetryEntry.retryDelayMillis);
} else {
- if (mFlags.useAlarmCallback()) {
- // No need to wake up the device, the retry can wait util next time the device wake
- // up to save power.
- mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
- dataRetryEntry.retryElapsedTime,
- "dataRetryHash-" + dataRetryEntry.hashCode() /*debug tag*/,
- Runnable::run,
- null /*worksource*/,
- () -> {
- logl("onAlarm retry " + dataRetryEntry);
- sendMessage(obtainMessage(dataRetryEntry instanceof DataSetupRetryEntry
- ? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY,
- dataRetryEntry));
- });
- } else {
- Intent intent = new Intent(ACTION_RETRY);
- intent.putExtra(ACTION_RETRY_EXTRA_HASHCODE, dataRetryEntry.hashCode());
- // No need to wake up the device, the retry can wait util next time the device wake
- // up to save power.
- mAlarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
- dataRetryEntry.retryElapsedTime,
- PendingIntent.getBroadcast(mPhone.getContext(),
- dataRetryEntry.hashCode()/*Unique identifier of the retry attempt*/,
- intent,
- PendingIntent.FLAG_IMMUTABLE));
- }
+ // No need to wake up the device, the retry can wait util next time the device wake
+ // up to save power.
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
+ dataRetryEntry.retryElapsedTime,
+ "dataRetryHash-" + dataRetryEntry.hashCode() /*debug tag*/,
+ Runnable::run,
+ null /*worksource*/,
+ () -> {
+ logl("onAlarm retry " + dataRetryEntry);
+ sendMessage(obtainMessage(dataRetryEntry instanceof DataSetupRetryEntry
+ ? EVENT_DATA_SETUP_RETRY : EVENT_DATA_HANDOVER_RETRY,
+ dataRetryEntry));
+ });
}
}
@@ -1601,8 +1562,7 @@
// transport.
mDataThrottlingEntries.removeIf(
throttlingEntry -> dataProfile.equals(throttlingEntry.dataProfile)
- && (!mFlags.unthrottleCheckTransport()
- || throttlingEntry.transport == transport));
+ && (throttlingEntry.transport == transport));
if (mDataThrottlingEntries.size() >= MAXIMUM_HISTORICAL_ENTRIES) {
// If we don't see the anomaly report after U release, we should remove this check for
@@ -1651,7 +1611,7 @@
// profile manager.
Stream<DataThrottlingEntry> stream = mDataThrottlingEntries.stream();
stream = stream.filter(entry -> entry.expirationTimeMillis > now
- && (!mFlags.unthrottleCheckTransport() || entry.transport == transport));
+ && entry.transport == transport);
if (dataProfile.getApnSetting() != null) {
stream = stream
.filter(entry -> entry.dataProfile.getApnSetting() != null)
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index fb112d9..0b9ac27 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -326,7 +326,7 @@
@Override
public void onUserDataEnabledChanged(boolean enabled,
@NonNull String callingPackage) {
- log("phone" + phone.getPhoneId() + " onUserDataEnabledChanged "
+ log("phone " + phone.getPhoneId() + " onUserDataEnabledChanged "
+ enabled + " by " + callingPackage
+ ", reevaluating mobile data policies");
DataSettingsManager.this.updateDataEnabledAndNotify(
@@ -335,6 +335,16 @@
});
}
}
+ SubscriptionManagerService.getInstance().registerCallback(
+ new SubscriptionManagerService.SubscriptionManagerServiceCallback(this::post) {
+ @Override
+ public void onDefaultDataSubscriptionChanged(int subId) {
+ log((subId == mSubId ? "Became" : "Not")
+ + " default data sub, reevaluating mobile data policies");
+ DataSettingsManager.this.updateDataEnabledAndNotify(
+ TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+ }
+ });
updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
}
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index f1f7b49..1005bb7 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -30,6 +30,7 @@
import static java.util.Arrays.copyOf;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -63,6 +64,7 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseIntArray;
@@ -183,6 +185,27 @@
}
}
+ /**
+ * Callback from PhoneSwitcher
+ */
+ public static class PhoneSwitcherCallback extends DataCallback {
+ /**
+ * Constructor
+ *
+ * @param executor The executor of the callback.
+ */
+ public PhoneSwitcherCallback(@NonNull @CallbackExecutor Executor executor) {
+ super(executor);
+ }
+
+ /**
+ * Called when preferred data phone id changed.
+ *
+ * @param phoneId The phone id of the preferred data.
+ */
+ public void onPreferredDataPhoneIdChanged(int phoneId) {}
+ }
+
@NonNull
private final NetworkRequestList mNetworkRequestList = new NetworkRequestList();
protected final RegistrantList mActivePhoneRegistrants;
@@ -261,6 +284,10 @@
private ISetOpportunisticDataCallback mSetOpptSubCallback;
+ /** Phone switcher callbacks. */
+ @NonNull
+ private final Set<PhoneSwitcherCallback> mPhoneSwitcherCallbacks = new ArraySet<>();
+
private static final int EVENT_PRIMARY_DATA_SUB_CHANGED = 101;
protected static final int EVENT_SUBSCRIPTION_CHANGED = 102;
private static final int EVENT_REQUEST_NETWORK = 103;
@@ -468,6 +495,24 @@
}
}
+ /**
+ * Register the callback for receiving information from {@link PhoneSwitcher}.
+ *
+ * @param callback The callback.
+ */
+ public void registerCallback(@NonNull PhoneSwitcherCallback callback) {
+ mPhoneSwitcherCallbacks.add(callback);
+ }
+
+ /**
+ * Unregister the callback for receiving information from {@link PhoneSwitcher}.
+ *
+ * @param callback The callback.
+ */
+ public void unregisterCallback(@NonNull PhoneSwitcherCallback callback) {
+ mPhoneSwitcherCallbacks.remove(callback);
+ }
+
private void evaluateIfImmediateDataSwitchIsNeeded(String evaluationReason, int switchReason) {
if (onEvaluate(REQUESTS_UNCHANGED, evaluationReason)) {
logDataSwitchEvent(mPreferredDataSubId.get(),
@@ -607,33 +652,35 @@
mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
- final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
- .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
- .setNetworkSpecifier(new MatchAllNetworkSpecifier());
- TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
- .forEach(builder::addCapability);
+ if (!mFlags.supportNetworkProvider()) {
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
+ .setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
+ .forEach(builder::addCapability);
- if (mFlags.satelliteInternet()) {
- // TODO: b/328622096 remove the try/catch
- try {
- builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
- } catch (IllegalArgumentException exception) {
- loge("TRANSPORT_SATELLITE is not supported.");
+ if (mFlags.satelliteInternet()) {
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ loge("TRANSPORT_SATELLITE is not supported.");
+ }
}
- }
- NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
- builder.build(), this);
- // we want to see all requests
- networkFactory.registerIgnoringScore();
+ NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
+ builder.build(), this);
+ // we want to see all requests
+ networkFactory.registerIgnoringScore();
+ }
updateHalCommandToUse();
@@ -1053,11 +1100,12 @@
return false;
}
+ // TODO: Remove after removing TelephonyNetworkFactory
private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory {
private final PhoneSwitcher mPhoneSwitcher;
public PhoneSwitcherNetworkRequestListener (Looper l, Context c,
NetworkCapabilities nc, PhoneSwitcher ps) {
- super(l, c, "PhoneSwitcherNetworkRequstListener", nc);
+ super(l, c, "PhoneSwitcherNetworkRequestListener", nc);
mPhoneSwitcher = ps;
}
@@ -1078,7 +1126,13 @@
}
}
- private void onRequestNetwork(NetworkRequest networkRequest) {
+ /**
+ * Called when receiving a network request.
+ *
+ * @param networkRequest The network request.
+ */
+ // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
+ public void onRequestNetwork(@NonNull NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (!mNetworkRequestList.contains(telephonyNetworkRequest)) {
@@ -1087,7 +1141,13 @@
}
}
- private void onReleaseNetwork(NetworkRequest networkRequest) {
+ /**
+ * Called when releasing a network request.
+ *
+ * @param networkRequest The network request to release.
+ */
+ // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
+ public void onReleaseNetwork(@NonNull NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (mNetworkRequestList.remove(telephonyNetworkRequest)) {
@@ -1101,18 +1161,6 @@
mDefaultNetworkCallback.mSwitchReason = reason;
}
- private void collectRequestNetworkMetrics(NetworkRequest networkRequest) {
- // Request network for MMS will temporary disable the network on default data subscription,
- // this only happen on multi-sim device.
- if (mActiveModemCount > 1 && networkRequest.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_MMS)) {
- OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
- onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
- onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_START;
- TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch);
- }
- }
-
private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
// Release network for MMS will recover the network on default data subscription, this only
// happen on multi-sim device.
@@ -1561,6 +1609,7 @@
* If preferred phone changes, or phone activation status changes, registrants
* will be notified.
*/
+ // TODO: Remove after removing TelephonyNetworkFactory
public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
Registrant r = new Registrant(h, what, o);
mActivePhoneRegistrants.add(r);
@@ -1982,6 +2031,10 @@
// Notify all registrants
mActivePhoneRegistrants.notifyRegistrants();
notifyPreferredDataSubIdChanged();
+ if (mFlags.supportNetworkProvider()) {
+ mPhoneSwitcherCallbacks.forEach(callback -> callback.invokeFromExecutor(
+ () -> callback.onPreferredDataPhoneIdChanged(phoneId)));
+ }
}
private boolean isPhoneIdValidForRetry(int phoneId) {
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
new file mode 100644
index 0000000..63edefa
--- /dev/null
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.data;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
+import android.net.NetworkProvider.NetworkOfferCallback;
+import android.net.NetworkRequest;
+import android.net.NetworkScore;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.SubscriptionManager;
+import android.util.ArrayMap;
+import android.util.LocalLog;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.telephony.Rlog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Map;
+
+/**
+ * TelephonyNetworkProvider is a singleton network provider responsible for providing all
+ * telephony related networks including networks on cellular and IWLAN across all active SIMs.
+ */
+public class TelephonyNetworkProvider extends NetworkProvider implements NetworkOfferCallback {
+
+ public final String LOG_TAG = "TNP";
+
+ /** Android feature flags */
+ @NonNull
+ private final FeatureFlags mFlags;
+
+ /** The event handler */
+ @NonNull
+ private final Handler mHandler;
+
+ /** Phone switcher responsible to determine request routing on dual-SIM device */
+ @NonNull
+ private final PhoneSwitcher mPhoneSwitcher;
+
+ /** Network requests map. Key is the network request, value is the phone id it applies to. */
+ private final Map<TelephonyNetworkRequest, Integer> mNetworkRequests = new ArrayMap<>();
+
+ /** Persisted log */
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(256);
+
+ /**
+ * Constructor
+ *
+ * @param looper The looper for event handling
+ * @param context The context
+ * @param featureFlags Android feature flags
+ */
+ public TelephonyNetworkProvider(@NonNull Looper looper, @NonNull Context context,
+ @NonNull FeatureFlags featureFlags) {
+ super(context, looper, TelephonyNetworkProvider.class.getSimpleName());
+
+ mFlags = featureFlags;
+ mHandler = new Handler(looper);
+ mPhoneSwitcher = PhoneSwitcher.getInstance();
+
+ // Register for subscription changed event.
+ context.getSystemService(SubscriptionManager.class)
+ .addOnSubscriptionsChangedListener(mHandler::post,
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ logl("Subscription changed.");
+ reevaluateNetworkRequests("subscription changed");
+ }});
+
+ // Register for preferred data changed event
+ mPhoneSwitcher.registerCallback(new PhoneSwitcherCallback(mHandler::post) {
+ @Override
+ public void onPreferredDataPhoneIdChanged(int phoneId) {
+ logl("Preferred data sub phone id changed to " + phoneId);
+ reevaluateNetworkRequests("Preferred data subscription changed");
+ }
+ });
+
+ // Register the provider and tell connectivity service what network offer telephony can
+ // provide
+ ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
+ if (cm != null) {
+ cm.registerNetworkProvider(this);
+ NetworkCapabilities caps = makeNetworkFilter();
+ registerNetworkOffer(new NetworkScore.Builder().build(), caps, mHandler::post, this);
+ logl("registerNetworkOffer: " + caps);
+ }
+ }
+
+ /**
+ * Get the phone id for the network request.
+ *
+ * @param request The network request
+ * @return The id of the phone where the network request should route to. If the network request
+ * can't be applied to any phone, {@link SubscriptionManager#INVALID_PHONE_INDEX} will be
+ * returned.
+ */
+ private int getPhoneIdForNetworkRequest(@NonNull TelephonyNetworkRequest request) {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ int phoneId = phone.getPhoneId();
+ if (mPhoneSwitcher.shouldApplyNetworkRequest(request, phoneId)) {
+ // Return here because by design the network request can be only applied to *one*
+ // phone. It's not possible to have two DataNetworkController to attempt to setup
+ // data call for the same network request.
+ return phoneId;
+ }
+ }
+
+ return SubscriptionManager.INVALID_PHONE_INDEX;
+ }
+
+ /**
+ * Called when receiving a network request from connectivity service. This is the entry point
+ * that a network request arrives telephony.
+ *
+ * @param request The network request
+ */
+ @Override
+ public void onNetworkNeeded(@NonNull NetworkRequest request) {
+ TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(request, mFlags);
+ if (mNetworkRequests.containsKey(networkRequest)) {
+ loge("Duplicate network request " + networkRequest);
+ return;
+ }
+
+ mPhoneSwitcher.onRequestNetwork(request);
+
+ // Check with PhoneSwitcher to see where to route the request.
+ int phoneId = getPhoneIdForNetworkRequest(networkRequest);
+ if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ logl("onNetworkNeeded: phoneId=" + phoneId + ", " + networkRequest);
+ PhoneFactory.getPhone(phoneId).getDataNetworkController()
+ .addNetworkRequest(networkRequest);
+ } else {
+ logl("onNetworkNeeded: Not applied. " + networkRequest);
+ }
+
+ mNetworkRequests.put(networkRequest, phoneId);
+ }
+
+ /**
+ * Called when connectivity service remove the network request. Note this will not result in
+ * network tear down. Even there is no network request attached to the network, telephony still
+ * relies on {@link NetworkAgent#onNetworkUnwanted()} to tear down the network.
+ *
+ * @param request The released network request
+ *
+ * @see TelephonyNetworkAgent#onNetworkUnwanted()
+ */
+ @Override
+ public void onNetworkUnneeded(@NonNull NetworkRequest request) {
+ TelephonyNetworkRequest networkRequest = mNetworkRequests.keySet().stream()
+ .filter(r -> r.getNativeNetworkRequest().equals(request))
+ .findFirst()
+ .orElse(null);
+ if (networkRequest == null) {
+ loge("onNetworkUnneeded: Cannot find " + request);
+ return;
+ }
+
+ mPhoneSwitcher.onReleaseNetwork(request);
+ int phoneId = mNetworkRequests.remove(networkRequest);
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone != null) {
+ logl("onNetworkUnneeded: phoneId=" + phoneId + ", " + networkRequest);
+ // Remove the network request from network controller. Note this will not result
+ // in disconnecting the data network.
+ phone.getDataNetworkController().removeNetworkRequest(networkRequest);
+ } else {
+ loge("onNetworkUnneeded: Unable to get phone. phoneId=" + phoneId);
+ }
+ }
+
+ /**
+ * Re-evaluate the existing networks and re-apply to the applicable phone.
+ *
+ * @param reason The reason for re-evaluating network request. Note this can be only used for
+ * debugging message purposes.
+ */
+ private void reevaluateNetworkRequests(@NonNull String reason) {
+ logl("reevaluateNetworkRequests: " + reason + ".");
+ mNetworkRequests.forEach((request, oldPhoneId) -> {
+ int newPhoneId = getPhoneIdForNetworkRequest(request);
+ if (newPhoneId != oldPhoneId) {
+ // We need to move the request from old phone to the new phone. This can happen
+ // when the user changes the default data subscription.
+
+ if (oldPhoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ PhoneFactory.getPhone(oldPhoneId).getDataNetworkController()
+ .removeNetworkRequest(request);
+ }
+
+ if (newPhoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+ PhoneFactory.getPhone(newPhoneId).getDataNetworkController()
+ .addNetworkRequest(request);
+ }
+
+ logl("Request moved. phoneId " + oldPhoneId + " -> " + newPhoneId + " " + request);
+ mNetworkRequests.put(request, newPhoneId);
+ }
+ });
+ }
+
+ /**
+ * @return The maximal network capabilities that telephony can support.
+ */
+ @NonNull
+ private NetworkCapabilities makeNetworkFilter() {
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
+ .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
+ // Ideally TelephonyNetworkProvider should only accept TelephonyNetworkSpecifier,
+ // but this network provider is a singleton across all SIMs, and
+ // TelephonyNetworkSpecifier can't accept more than one subscription id, so we let
+ // the provider accepts all different kinds NetworkSpecifier.
+ .setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
+ .forEach(builder::addCapability);
+
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ log("TRANSPORT_SATELLITE is not supported.");
+ }
+
+ return builder.build();
+ }
+
+ /**
+ * Log debug message to logcat.
+ *
+ * @param s The debug message to log
+ */
+ private void log(@NonNull String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+
+ /**
+ * Log error debug messages to logcat.
+ * @param s The error debug messages
+ */
+ private void loge(@NonNull String s) {
+ Rlog.e(LOG_TAG, s);
+ }
+
+ /**
+ * Log to logcat and persisted local log.
+ *
+ * @param s The debug message to log
+ */
+ private void logl(@NonNull String s) {
+ log(s);
+ mLocalLog.log(s);
+ }
+
+ /**
+ * Dump the state of telephony network provider.
+ *
+ * @param fd File descriptor
+ * @param writer Print writer
+ * @param args Arguments
+ */
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+ pw.println("TelephonyNetworkProvider:");
+ pw.increaseIndent();
+
+ pw.println("mPreferredDataPhoneId=" + mPhoneSwitcher.getPreferredDataPhoneId());
+ int defaultDataSubId = SubscriptionManagerService.getInstance().getDefaultDataSubId();
+ pw.println("DefaultDataSubId=" + defaultDataSubId);
+ pw.println("DefaultDataPhoneId=" + SubscriptionManagerService.getInstance()
+ .getPhoneId(defaultDataSubId));
+
+ pw.println("Registered capabilities: " + makeNetworkFilter());
+ pw.println("Network requests:");
+ pw.increaseIndent();
+ for (Phone phone : PhoneFactory.getPhones()) {
+ pw.println("Phone " + phone.getPhoneId() + ":");
+ pw.increaseIndent();
+ mNetworkRequests.forEach((request, phoneId) -> {
+ if (phoneId == phone.getPhoneId()) {
+ pw.println(request);
+ }
+ });
+ pw.decreaseIndent();
+ }
+ pw.println("Not applied requests:");
+ pw.increaseIndent();
+ mNetworkRequests.forEach((request, phoneId) -> {
+ if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
+ pw.println(request);
+ }
+ });
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ pw.println();
+ pw.println("Local logs:");
+ pw.increaseIndent();
+ mLocalLog.dump(fd, pw, args);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+}
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
index 67639eb..ca1ca21 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
@@ -137,10 +137,6 @@
CAPABILITY_ATTRIBUTE_APN_SETTING | CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN)
);
- /** The phone instance. */
- @NonNull
- private final Phone mPhone;
-
/**
* Native network request from the clients. See {@link NetworkRequest};
*/
@@ -164,8 +160,8 @@
/**
* Data config manager for retrieving data config.
*/
- @NonNull
- private final DataConfigManager mDataConfigManager;
+ @Nullable
+ private DataConfigManager mDataConfigManager;
/**
* The attached data network. Note that the data network could be in any state. {@code null}
@@ -205,7 +201,19 @@
*/
public TelephonyNetworkRequest(@NonNull NetworkRequest request, @NonNull Phone phone,
@NonNull FeatureFlags featureFlags) {
- mPhone = phone;
+ this(request, featureFlags);
+ mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
+ updatePriority();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param request The native network request from the clients.
+ * @param featureFlags The feature flag
+ */
+ public TelephonyNetworkRequest(@NonNull NetworkRequest request,
+ @NonNull FeatureFlags featureFlags) {
mNativeNetworkRequest = request;
mFeatureFlags = featureFlags;
@@ -222,7 +230,15 @@
// to satisfy it.
mState = REQUEST_STATE_UNSATISFIED;
mCreatedTimeMillis = SystemClock.elapsedRealtime();
- mDataConfigManager = phone.getDataNetworkController().getDataConfigManager();
+ }
+
+ /**
+ * Update the associated data config manager.
+ *
+ * @param dataConfigManager Data config manager
+ */
+ public void updateDataConfig(@NonNull DataConfigManager dataConfigManager) {
+ mDataConfigManager = dataConfigManager;
updatePriority();
}
@@ -315,13 +331,15 @@
if (mNativeNetworkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
&& !mNativeNetworkRequest.hasTransport(
NetworkCapabilities.TRANSPORT_SATELLITE)) {
- if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
- .getForcedCellularTransportCapabilities()::contains)) {
- // If the request is explicitly for the cellular, then the data profile
- // needs to support cellular.
- if (!dataProfile.getApnSetting().isForInfrastructure(
- ApnSetting.INFRASTRUCTURE_CELLULAR)) {
- return false;
+ if (mDataConfigManager != null) {
+ if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
+ .getForcedCellularTransportCapabilities()::contains)) {
+ // If the request is explicitly for the cellular, then the data profile
+ // needs to support cellular.
+ if (!dataProfile.getApnSetting().isForInfrastructure(
+ ApnSetting.INFRASTRUCTURE_CELLULAR)) {
+ return false;
+ }
}
}
} else if (mNativeNetworkRequest.hasTransport(
@@ -371,10 +389,12 @@
* Update the priority from data config manager.
*/
public void updatePriority() {
- mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
- .map(mDataConfigManager::getNetworkCapabilityPriority)
- .max()
- .orElse(0);
+ if (mDataConfigManager != null) {
+ mPriority = Arrays.stream(mNativeNetworkRequest.getCapabilities())
+ .map(mDataConfigManager::getNetworkCapabilityPriority)
+ .max()
+ .orElse(0);
+ }
}
/**
@@ -387,6 +407,7 @@
@NetCapability
public int getHighestPriorityApnTypeNetworkCapability() {
if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1;
+ if (mDataConfigManager == null) return -1;
return Arrays.stream(getCapabilities()).boxed()
.filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
.max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
@@ -403,6 +424,7 @@
*/
@NetCapability
public int getHighestPrioritySupportedNetworkCapability() {
+ if (mDataConfigManager == null) return -1;
return Arrays.stream(getCapabilities()).boxed()
.filter(CAPABILITY_ATTRIBUTE_MAP::containsKey)
.max(Comparator.comparingInt(mDataConfigManager::getNetworkCapabilityPriority))
@@ -466,7 +488,7 @@
*
* @param evaluation The data evaluation result.
*/
- public void setEvaluation(@NonNull DataEvaluation evaluation) {
+ public void setEvaluation(@Nullable DataEvaluation evaluation) {
mEvaluation = evaluation;
}
@@ -487,14 +509,6 @@
}
/**
- * @return {@code true} if this network request can result in bringing up a metered network.
- */
- public boolean isMeteredRequest() {
- return mDataConfigManager.isAnyMeteredCapability(
- getCapabilities(), mPhone.getServiceState().getDataRoaming());
- }
-
- /**
* Get Os/App id from the network request.
*
* @return Os/App id. {@code null} if the request does not have traffic descriptor based network
@@ -547,7 +561,7 @@
return "[" + mNativeNetworkRequest + ", mPriority=" + mPriority
+ ", state=" + requestStateToString(mState)
+ ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
- ? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
+ ? mAttachedDataNetwork.name() : null)
+ ", created time=" + DataUtils.elapsedTimeToString(mCreatedTimeMillis)
+ ", evaluation result=" + mEvaluation + "]";
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 194865b..0a39865 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -116,6 +116,7 @@
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteSubscriberInfo;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -241,6 +242,7 @@
private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46;
private static final int EVENT_WIFI_CONNECTIVITY_STATE_CHANGED = 47;
private static final int EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT = 48;
+ protected static final int EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT = 49;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@@ -344,9 +346,13 @@
private final Object mIsSatelliteEnabledLock = new Object();
@GuardedBy("mIsSatelliteEnabledLock")
private Boolean mIsSatelliteEnabled = null;
- private final Object mIsRadioOnLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected final Object mIsRadioOnLock = new Object();
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean mIsRadioOn;
@GuardedBy("mIsRadioOnLock")
- private boolean mIsRadioOn = false;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean mRadioOffRequested = false;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected final Object mSatelliteViaOemProvisionLock = new Object();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -1325,6 +1331,14 @@
mIsRadioOn = true;
} else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
resetCarrierRoamingSatelliteModeParams();
+ synchronized (mIsRadioOnLock) {
+ if (mRadioOffRequested) {
+ logd("EVENT_RADIO_STATE_CHANGED: set mIsRadioOn to false");
+ stopWaitForCellularModemOffTimer();
+ mIsRadioOn = false;
+ mRadioOffRequested = false;
+ }
+ }
}
}
@@ -1635,6 +1649,13 @@
break;
}
+ case EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT: {
+ plogw("Timed out to wait for cellular modem OFF state");
+ synchronized (mIsRadioOnLock) {
+ mRadioOffRequested = false;
+ }
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1716,6 +1737,12 @@
SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
return;
}
+ if (mRadioOffRequested) {
+ ploge("Radio is being powering off, can not enable satellite");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
+ return;
+ }
}
if (mTelecomManager.isInEmergencyCall()) {
@@ -2900,27 +2927,50 @@
/**
* This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify
- * {@link SatelliteController} that it has received a request to power off the cellular radio
- * modem. {@link SatelliteController} will then power off the satellite modem.
+ * {@link SatelliteController} that it has received a request to power on or off the cellular
+ * radio modem.
+ *
+ * @param powerOn {@code true} means cellular radio is about to be powered on, {@code false}
+ * means cellular modem is about to be powered off.
*/
- public void onCellularRadioPowerOffRequested() {
- logd("onCellularRadioPowerOffRequested()");
+ public void onSetCellularRadioPowerStateRequested(boolean powerOn) {
+ logd("onSetCellularRadioPowerStateRequested: powerOn=" + powerOn);
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- plogd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
+ plogd("onSetCellularRadioPowerStateRequested: oemEnabledSatelliteFlag is disabled");
return;
}
synchronized (mIsRadioOnLock) {
- mIsRadioOn = false;
+ mRadioOffRequested = !powerOn;
}
- requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- plogd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
- }
- });
+ if (powerOn) {
+ stopWaitForCellularModemOffTimer();
+ } else {
+ requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("onSetCellularRadioPowerStateRequested: requestSatelliteEnabled"
+ + " result=" + result);
+ }
+ });
+ startWaitForCellularModemOffTimer();
+ }
+ }
+
+ /**
+ * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify
+ * {@link SatelliteController} that the request to power off the cellular radio modem has
+ * failed.
+ */
+ public void onPowerOffCellularRadioFailed() {
+ logd("onPowerOffCellularRadioFailed");
+ synchronized (mIsRadioOnLock) {
+ mRadioOffRequested = false;
+ stopWaitForCellularModemOffTimer();
+ }
}
/**
@@ -4956,6 +5006,32 @@
R.integer.config_wait_for_satellite_enabling_response_timeout_millis);
}
+ private long getWaitForCellularModemOffTimeoutMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis);
+ }
+
+ private void startWaitForCellularModemOffTimer() {
+ synchronized (mIsRadioOnLock) {
+ if (hasMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT)) {
+ plogd("startWaitForCellularModemOffTimer: the timer was already started");
+ return;
+ }
+ long timeoutMillis = getWaitForCellularModemOffTimeoutMillis();
+ plogd("Start timer to wait for cellular modem OFF state, timeoutMillis="
+ + timeoutMillis);
+ sendMessageDelayed(obtainMessage(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT),
+ timeoutMillis);
+ }
+ }
+
+ private void stopWaitForCellularModemOffTimer() {
+ synchronized (mSatelliteEnabledRequestLock) {
+ plogd("Stop timer to wait for cellular modem OFF state");
+ removeMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT);
+ }
+ }
+
private void startWaitForSatelliteEnablingResponseTimer(
@NonNull RequestSatelliteEnabledArgument argument) {
synchronized (mSatelliteEnabledRequestLock) {
@@ -5524,14 +5600,20 @@
// The subscriberId for ntnOnly SIMs is the Iccid, whereas for ESOS supported SIMs, the
// subscriberId is the Imsi prefix 6 digit + phone number.
- private @NonNull String getSubscriberId(SubscriptionInfo info) {
+ private Pair<String, Integer> getSubscriberIdAndType(SubscriptionInfo info) {
+ String subscriberId = "";
+ @SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
+ SatelliteSubscriberInfo.ICCID;
if (info.isSatelliteESOSSupported()) {
- return getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
+ subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
}
if (info.isOnlyNonTerrestrialNetwork()) {
- return info.getIccId();
+ subscriberId = info.getIccId();
}
- return "";
+ logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
+ + subscriberIdType);
+ return new Pair<>(subscriberId, subscriberIdType);
}
private String getPhoneNumberBasedCarrier(int subId) {
@@ -5540,7 +5622,6 @@
SubscriptionManager subscriptionManager = mContext.getSystemService(
SubscriptionManager.class);
String phoneNumber = subscriptionManager.getPhoneNumber(subId);
-
if (phoneNumber == null) {
logd("getPhoneNumberBasedCarrier: phoneNumber null");
return "";
@@ -5603,77 +5684,59 @@
* @param result The result receiver, which returns the list of prioritized satellite tokens
* to be used for provision if the request is successful or an error code if the request failed.
*/
- public void requestProvisionSubscriberIds(@NonNull ResultReceiver result) {
+ public void requestSatelliteSubscriberProvisionStatus(@NonNull ResultReceiver result) {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
return;
}
- List<SatelliteSubscriberInfo> list = new ArrayList<>();
+ List<SatelliteSubscriberProvisionStatus> list = new ArrayList<>();
synchronized (mSatelliteTokenProvisionedLock) {
mSubscriberIdPerSub = new HashMap<>();
for (int priority : mSubsInfoListPerPriority.keySet()) {
List<SubscriptionInfo> infoList = mSubsInfoListPerPriority.get(priority);
if (infoList == null) {
- logd("requestProvisionSubscriberIds: no exist this priority " + priority);
+ logd("requestSatelliteSubscriberProvisionStatus: no exist this priority "
+ + priority);
continue;
}
for (SubscriptionInfo info : infoList) {
- String subscriberId = getSubscriberId(info);
+ Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(info);
+ String subscriberId = subscriberIdPair.first;
int carrierId = info.getCarrierId();
String apn = getConfigForSubId(info.getSubscriptionId())
.getString(KEY_SATELLITE_NIDD_APN_NAME_STRING);
- logd("requestProvisionSubscriberIds: subscriberId:" + subscriberId
- + " , carrierId=" + carrierId + " , apn=" + apn);
+ logd("requestSatelliteSubscriberProvisionStatus: subscriberId:"
+ + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
if (subscriberId.isEmpty()) {
- logd("requestProvisionSubscriberIds: getSubscriberId failed skip this "
- + "subscriberId.");
+ logd("requestSatelliteSubscriberProvisionStatus: getSubscriberId "
+ + "failed skip this subscriberId.");
continue;
}
- list.add(new SatelliteSubscriberInfo(subscriberId, carrierId, apn));
+ SatelliteSubscriberInfo satelliteSubscriberInfo =
+ new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
+ .setCarrierId(carrierId).setNiddApn(apn)
+ .setSubId(info.getSubscriptionId())
+ .setSubscriberIdType(subscriberIdPair.second)
+ .build();
+ boolean provisioned = mProvisionedSubscriberId.getOrDefault(
+ subscriberId, false);
+ logd("requestSatelliteSubscriberProvisionStatus: satelliteSubscriberInfo="
+ + satelliteSubscriberInfo + ", provisioned=" + provisioned);
+ list.add(new SatelliteSubscriberProvisionStatus.Builder()
+ .setSatelliteSubscriberInfo(satelliteSubscriberInfo)
+ .setProvisionStatus(provisioned).build());
mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId());
}
}
}
- logd("requestProvisionSubscriberIds: " + list);
+ logd("requestSatelliteSubscriberProvisionStatus: " + list);
final Bundle bundle = new Bundle();
bundle.putParcelableList(SatelliteManager.KEY_REQUEST_PROVISION_SUBSCRIBER_ID_TOKEN, list);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
}
- /**
- * Request to get provisioned status for given a satellite subscriber id.
- *
- * @param satelliteSubscriberId Satellite subscriber id requiring provisioned status check.
- * @param result The result receiver, which returns the provisioned status of the token if the
- * request is successful or an error code if the request failed.
- */
- public void requestIsProvisioned(@NonNull String satelliteSubscriberId,
- @NonNull ResultReceiver result) {
- if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
- result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
- return;
- }
- if (satelliteSubscriberId.isEmpty()) {
- result.send(SATELLITE_RESULT_INVALID_ARGUMENTS, null);
- return;
- }
-
- boolean isProvisioned = false;
- synchronized (mSatelliteTokenProvisionedLock) {
- if (mProvisionedSubscriberId.getOrDefault(satelliteSubscriberId, false)) {
- isProvisioned = true;
- }
- }
-
- logd("requestIsProvisioned: satelliteSubscriberId=" + satelliteSubscriberId
- + " , isProvisioned=" + isProvisioned);
- final Bundle bundle = new Bundle();
- bundle.putBoolean(SatelliteManager.KEY_IS_SATELLITE_PROVISIONED, isProvisioned);
- result.send(SATELLITE_RESULT_SUCCESS, bundle);
- }
-
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean isSubscriptionProvisioned(int subId) {
plogd("isSubscriptionProvisioned: subId=" + subId);
@@ -5682,8 +5745,8 @@
return false;
}
- String subscriberId = getSubscriberId(
- mSubscriptionManagerService.getSubscriptionInfo(subId));
+ String subscriberId = getSubscriberIdAndType(
+ mSubscriptionManagerService.getSubscriptionInfo(subId)).first;
if (subscriberId.isEmpty()) {
plogd("isSubscriptionProvisioned: subId=" + subId + " subscriberId is empty.");
return false;
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 9988ea0..f24d484 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -17,7 +17,6 @@
package com.android.internal.telephony.satellite;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
-import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT;
import static android.telephony.ServiceState.STATE_EMERGENCY_ONLY;
import static android.telephony.ServiceState.STATE_IN_SERVICE;
import static android.telephony.ServiceState.STATE_OUT_OF_SERVICE;
@@ -43,7 +42,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.OutcomeReceiver;
-import android.os.PersistableBundle;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.telecom.Connection;
@@ -58,6 +56,7 @@
import android.telephony.ims.RegistrationManager;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.text.TextUtils;
import android.util.Pair;
import android.util.SparseArray;
@@ -73,6 +72,7 @@
import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.SatelliteStats;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -160,6 +160,13 @@
plogd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> satelliteSubscriberProvisionStatus) {
+ plogd("onSatelliteSubscriptionProvisionStateChanged: "
+ + satelliteSubscriberProvisionStatus);
+ }
};
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 749f190..8dad3ec 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -23,7 +23,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.telephony.CellIdentityGsm;
import android.telephony.CellInfo;
@@ -101,23 +100,7 @@
}
@Test @SmallTest
- public void testNotifyDataActivity() throws Exception {
- when(mFeatureFlags.notifyDataActivityChangedWithSlot()).thenReturn(false);
- //mock data activity state
- doReturn(TelephonyManager.DATA_ACTIVITY_NONE).when(mPhone).getDataActivityState();
- mDefaultPhoneNotifierUT.notifyDataActivity(mPhone);
- verify(mTelephonyRegistryManager).notifyDataActivityChanged(eq(0),
- eq(TelephonyManager.DATA_ACTIVITY_NONE));
-
- doReturn(1).when(mPhone).getSubId();
- doReturn(TelephonyManager.DATA_ACTIVITY_IN).when(mPhone).getDataActivityState();
- mDefaultPhoneNotifierUT.notifyDataActivity(mPhone);
- verify(mTelephonyRegistryManager).notifyDataActivityChanged(eq(1),
- eq(TelephonyManager.DATA_ACTIVITY_IN));
- }
- @Test @SmallTest
public void testNotifyDataActivityWithSlot() throws Exception {
- when(mFeatureFlags.notifyDataActivityChangedWithSlot()).thenReturn(true);
//mock data activity state
doReturn(TelephonyManager.DATA_ACTIVITY_NONE).when(mPhone).getDataActivityState();
doReturn(PHONE_ID).when(mPhone).getPhoneId();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index b9fac4a..1465176 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.nullable;
@@ -594,7 +595,7 @@
sst.setRadioPowerForReason(false, false, false, false, reason);
assertTrue(sst.getRadioPowerOffReasons().contains(reason));
assertTrue(sst.getRadioPowerOffReasons().size() == 1);
- verify(mSatelliteController).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(false));
clearInvocations(mSatelliteController);
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
@@ -602,7 +603,7 @@
TelephonyManager.RADIO_POWER_REASON_USER);
assertTrue(sst.getRadioPowerOffReasons().contains(reason));
assertTrue(sst.getRadioPowerOffReasons().size() == 1);
- verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController, never()).onSetCellularRadioPowerStateRequested(anyBoolean());
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
@@ -610,7 +611,7 @@
// had been turned off for.
sst.setRadioPowerForReason(true, false, false, false, reason);
assertTrue(sst.getRadioPowerOffReasons().isEmpty());
- verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(true));
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
@@ -1928,6 +1929,8 @@
sst.setRadioPower(false);
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
+ verify(mSatelliteController).onSetCellularRadioPowerStateRequested(eq(false));
+ verify(mSatelliteController).onPowerOffCellularRadioFailed();
sst.requestShutdown();
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
assertFalse(mSimulatedCommands.getRadioState()
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 38b4f77..36ac992 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -580,6 +580,7 @@
mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
+ doReturn(true).when(mFeatureFlags).supportNetworkProvider();
TelephonyManager.disableServiceHandleCaching();
PropertyInvalidatedCache.disableForTestMode();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
index 005b312..95cefd8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
@@ -146,7 +146,6 @@
@Test
public void testMeteredNetworkCapabilities() {
- doReturn(true).when(mFeatureFlags).meteredEmbbUrlcc();
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[] {ApnSetting.TYPE_MMS_STRING, ApnSetting.TYPE_DEFAULT_STRING});
mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 499c1f5..5dce5c2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -159,7 +159,6 @@
private static final int EVENT_SUBSCRIPTION_OVERRIDE = 23;
// Mocked classes
- private PhoneSwitcher mMockedPhoneSwitcher;
protected ISub mMockedIsub;
private DataNetworkControllerCallback mMockedDataNetworkControllerCallback;
private DataRetryManagerCallback mMockedDataRetryManagerCallback;
@@ -855,7 +854,6 @@
public void setUp() throws Exception {
logd("DataNetworkControllerTest +Setup!");
super.setUp(getClass().getSimpleName());
- mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
mMockedIsub = Mockito.mock(ISub.class);
mMockedImsManager = mContext.getSystemService(ImsManager.class);
mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class);
@@ -878,7 +876,6 @@
mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
mMockedWlanDataServiceManager);
- replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doReturn(1).when(mMockedIsub).getDefaultDataSubId();
doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
doReturn(mPhone).when(mPhone).getImsPhone();
@@ -893,8 +890,6 @@
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
doReturn(true).when(mFeatureFlags).satelliteInternet();
- doReturn(true).when(mFeatureFlags)
- .ignoreExistingNetworksForInternetAllowedChecking();
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
@@ -2844,7 +2839,6 @@
@Test
public void testHandoverDataNetworkNotAllowedByPolicyDelayDueToVoiceCall() throws Exception {
- doReturn(true).when(mFeatureFlags).relaxHoTeardown();
// Config delay IMS tear down enabled
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
true);
@@ -3901,7 +3895,6 @@
@Test
public void testNonVoPStoVoPSImsSetup() throws Exception {
- doReturn(true).when(mFeatureFlags).allowMmtelInNonVops();
mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
// Config that allows non-vops bring up when Roaming
mCarrierConfig.putIntArray(CarrierConfigManager.Ims
@@ -4908,14 +4901,10 @@
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, 0, NetworkRequest.Type.REQUEST);
-
- mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone, mFeatureFlags));
- processAllMessages();
-
- // Intentionally create a new telephony request with the original native network request.
TelephonyNetworkRequest request = new TelephonyNetworkRequest(
nativeNetworkRequest, mPhone, mFeatureFlags);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
mDataNetworkControllerUT.removeNetworkRequest(request);
processAllFutureMessages();
@@ -4936,7 +4925,7 @@
processAllMessages();
// this slot is 0, modem preferred on slot 1
- doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
+ doReturn(1).when(mPhoneSwitcher).getPreferredDataPhoneId();
// Simulate telephony network factory remove request due to switch.
mDataNetworkControllerUT.removeNetworkRequest(request);
@@ -4949,7 +4938,7 @@
@Test
public void testSetupDataOnNonDds() throws Exception {
// this slot is 0, modem preferred on slot 1
- doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId();
+ doReturn(1).when(mPhoneSwitcher).getPreferredDataPhoneId();
TelephonyNetworkRequest request = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_MMS);
@@ -5475,4 +5464,18 @@
assertThat(mDataNetworkControllerUT.getInternetEvaluation(true/*ignoreExistingNetworks*/)
.containsDisallowedReasons()).isTrue();
}
+
+ @Test
+ public void testRemoveNetworkRequestClearState() throws Exception {
+ TelephonyNetworkRequest request = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ assertThat(request.getState()).isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
+
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ processAllMessages();
+ assertThat(request.getState()).isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 8be0f8b..f832a6b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -25,6 +25,7 @@
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -86,6 +87,7 @@
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
import com.android.internal.telephony.metrics.DataCallSessionStats;
import com.android.internal.telephony.test.SimulatedCommands;
@@ -238,14 +240,14 @@
// Mocked classes
private DataNetworkCallback mDataNetworkCallback;
private DataCallSessionStats mDataCallSessionStats;
- private PhoneSwitcher mMockedPhoneSwitcher;
-
private final NetworkRegistrationInfo mIwlanNetworkRegistrationInfo =
new NetworkRegistrationInfo.Builder()
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.build();
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid) {
setSuccessfulSetupDataResponse(dsm, cid, Collections.emptyList(), null);
}
@@ -379,14 +381,13 @@
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
+ doReturn(1).when(mPhone).getSubId();
doReturn(mImsPhone).when(mPhone).getImsPhone();
doReturn(mImsCT).when(mImsPhone).getCallTracker();
doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
mDataNetworkCallback = Mockito.mock(DataNetworkCallback.class);
mDataCallSessionStats = Mockito.mock(DataCallSessionStats.class);
- mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
- replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
doAnswer(invocation -> {
((Runnable) invocation.getArguments()[0]).run();
return null;
@@ -2418,7 +2419,6 @@
@Test
public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
- doReturn(true).when(mFeatureFlags).forceIwlanMms();
setupDataNetwork();
TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
@@ -2662,4 +2662,35 @@
assertThat(mDataNetworkUT.getNetworkCapabilities()
.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
}
+
+ @Test
+ public void testPrimaryTransport() throws Exception {
+ doReturn(0).when(mPhoneSwitcher).getPreferredDataPhoneId();
+ setupDataNetwork();
+ TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+ replaceInstance(DataNetwork.class, "mNetworkAgent",
+ mDataNetworkUT, mockNetworkAgent);
+
+ ArgumentCaptor<PhoneSwitcherCallback> callbackCaptor =
+ ArgumentCaptor.forClass(PhoneSwitcherCallback.class);
+ verify(mPhoneSwitcher).registerCallback(callbackCaptor.capture());
+ mPhoneSwitcherCallback = callbackCaptor.getValue();
+
+ // Switch the preferred data subscription to another.
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(1);
+ processAllMessages();
+
+ ArgumentCaptor<NetworkScore> networkScoreCaptor =
+ ArgumentCaptor.forClass(NetworkScore.class);
+ verify(mockNetworkAgent).sendNetworkScore(networkScoreCaptor.capture());
+ assertThat(networkScoreCaptor.getValue().isTransportPrimary()).isFalse();
+ clearInvocations(mockNetworkAgent);
+
+ // Switch back
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(0);
+ processAllMessages();
+
+ verify(mockNetworkAgent).sendNetworkScore(networkScoreCaptor.capture());
+ assertThat(networkScoreCaptor.getValue().isTransportPrimary()).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 30ce46f..96d0c8c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -1046,7 +1046,6 @@
@Test
public void testSetPreferredDataProfile() {
- doReturn(true).when(mFeatureFlags).refinePreferredDataProfileSelection();
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
index 89cdc47..78bb553 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
@@ -341,7 +341,6 @@
@Test
public void testDataSetupUnthrottling() throws Exception {
- doReturn(true).when(mFeatureFlags).unthrottleCheckTransport();
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
@@ -807,7 +806,6 @@
@Test
public void testDataRetryLongTimer() {
- doReturn(true).when(mFeatureFlags).useAlarmCallback();
// Rule requires a long timer
DataSetupRetryRule retryRule = new DataSetupRetryRule(
"capabilities=internet, retry_interval=120000, maximum_retries=2");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
index 3f18a3a..620cf39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
@@ -42,6 +42,7 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.After;
import org.junit.Before;
@@ -184,6 +185,49 @@
}
@Test
+ public void testUpdateDataEnabledAndNotifyOverrideDdsChange() throws Exception {
+ // Mock 2nd phone the DDS phone.
+ int phone2Id = 1;
+ int phone2SubId = 2;
+ doReturn(phone2SubId).when(mSubscriptionManagerService).getDefaultDataSubId();
+ Phone phone2 = Mockito.mock(Phone.class);
+ doReturn(phone2Id).when(phone2).getPhoneId();
+ doReturn(phone2SubId).when(phone2).getSubId();
+ doReturn(phone2Id).when(mSubscriptionManagerService).getPhoneId(phone2SubId);
+ DataSettingsManager dataSettingsManager2 = Mockito.mock(DataSettingsManager.class);
+ doReturn(dataSettingsManager2).when(phone2).getDataSettingsManager();
+ doReturn(true).when(phone2).isUserDataEnabled();
+
+ mPhones = new Phone[] {mPhone, phone2};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ ArgumentCaptor<SubscriptionManagerService.SubscriptionManagerServiceCallback>
+ callbackArgumentCaptor = ArgumentCaptor
+ .forClass(SubscriptionManagerService.SubscriptionManagerServiceCallback.class);
+
+ mDataSettingsManagerUT.sendEmptyMessage(11 /* EVENT_INITIALIZE */);
+ mDataSettingsManagerUT.setDataEnabled(TelephonyManager.DATA_ENABLED_REASON_USER, false, "");
+ processAllMessages();
+
+ // Verify listening to DDS change callback
+ verify(mSubscriptionManagerService, times(2))
+ .registerCallback(callbackArgumentCaptor.capture());
+ SubscriptionManagerService.SubscriptionManagerServiceCallback callback =
+ callbackArgumentCaptor.getValue();
+
+ // Mock the phone as nonDDS auto switch override enabled.
+ clearInvocations(mPhones);
+ mDataSettingsManagerUT.setMobileDataPolicy(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, true);
+ processAllMessages();
+ verify(mPhone).notifyDataEnabled(true, TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+
+ // The phone became DDS, data should be disabled
+ doReturn(mPhone.getSubId()).when(mSubscriptionManagerService).getDefaultDataSubId();
+ callback.onDefaultDataSubscriptionChanged(mPhone.getSubId());
+ verify(mPhone).notifyDataEnabled(false, TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
+ }
+
+ @Test
public void testNotifyDataEnabledFromNewValidSubId() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mDataSettingsManagerUT.registerCallback(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index a820ec7..f7990b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -52,18 +52,15 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
-import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.Messenger;
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
@@ -75,8 +72,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import androidx.test.filters.SmallTest;
-
import com.android.ims.ImsException;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CommandException;
@@ -140,9 +135,6 @@
private PhoneSwitcher mPhoneSwitcherUT;
private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
- private ConnectivityManager mConnectivityManager;
- // The messenger of PhoneSwitcher used to receive network requests.
- private Messenger mNetworkProviderMessenger = null;
private Map<Integer, DataSettingsManager.DataSettingsManagerCallback>
mDataSettingsManagerCallbacks;
private int mDefaultDataSub = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -211,8 +203,6 @@
public void tearDown() throws Exception {
mPhoneSwitcherUT = null;
mSubChangedListener = null;
- mConnectivityManager = null;
- mNetworkProviderMessenger = null;
mTelephonyDisplayInfo = null;
super.tearDown();
}
@@ -221,7 +211,6 @@
* Test that a single phone case results in our phone being active and the RIL called
*/
@Test
- @SmallTest
public void testRegister() throws Exception {
initialize();
@@ -468,7 +457,6 @@
}
@Test
- @SmallTest
public void testAutoDataSwitch_exemptPingTest() throws Exception {
initialize();
@@ -506,7 +494,6 @@
* - don't switch phones when in emergency mode
*/
@Test
- @SmallTest
public void testPrioritization() throws Exception {
initialize();
@@ -541,7 +528,6 @@
* wins (ie, switch to wifi).
*/
@Test
- @SmallTest
public void testHigherPriorityDefault() throws Exception {
initialize();
@@ -574,7 +560,6 @@
* active one.
*/
@Test
- @SmallTest
public void testSetPreferredData() throws Exception {
initialize();
@@ -620,7 +605,6 @@
* 3. CBRS requests OR Auto switch requests - only one case applies at a time
*/
@Test
- @SmallTest
public void testSetPreferredDataCasePriority_CbrsWaitsForVoiceCall() throws Exception {
initialize();
setAllPhonesInactive();
@@ -674,7 +658,6 @@
}
@Test
- @SmallTest
public void testSetPreferredData_NoAutoSwitchWhenCbrs() throws Exception {
initialize();
setAllPhonesInactive();
@@ -728,7 +711,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataModemCommand() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -827,7 +809,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataWithValidation() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -888,7 +869,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds() throws Exception {
initialize();
setAllPhonesInactive();
@@ -916,7 +896,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallDialingOnLte_shouldSwitchDds()
throws Exception {
initialize();
@@ -950,7 +929,6 @@
assertEquals(1, mPhoneSwitcherUT.getPreferredDataPhoneId());
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallIncomingOnLte_shouldSwitchDds()
throws Exception {
initialize();
@@ -979,7 +957,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnWlan_shouldNotSwitchDds() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1006,7 +983,6 @@
}
@Test
- @SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnCrossSIM_HandoverToLTE() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1169,7 +1145,6 @@
}
@Test
- @SmallTest
public void testNetworkRequestOnNonDefaultData() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1194,7 +1169,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideSuccessBeforeCallStarts() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1215,7 +1189,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideNoDdsChange() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1235,7 +1208,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideEndSuccess() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1273,7 +1245,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideEcbmStartEnd() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1323,7 +1294,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideNoCallStart() throws Exception {
PhoneSwitcher.DEFAULT_DATA_OVERRIDE_TIMEOUT_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1355,7 +1325,6 @@
}
@Test
- @SmallTest
public void testEmergencyOverrideMultipleOverrideRequests() throws Exception {
PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS = 500;
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1406,7 +1375,6 @@
}
@Test
- @SmallTest
public void testSetPreferredDataCallback() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1581,7 +1549,6 @@
}
@Test
- @SmallTest
public void testMultiSimConfigChange() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
mActiveModemCount = 1;
@@ -1609,7 +1576,6 @@
}
@Test
- @SmallTest
public void testValidationOffSwitch_shouldSwitchOnNetworkAvailable() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1650,7 +1616,6 @@
}
@Test
- @SmallTest
public void testValidationOffSwitch_shouldSwitchOnTimeOut() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
initialize();
@@ -1773,7 +1738,6 @@
}
@Test
- @SmallTest
public void testRegisterForImsRegistrationCallback() throws Exception {
initialize();
setAllPhonesInactive();
@@ -1801,7 +1765,6 @@
}
@Test
- @SmallTest
public void testReceivingImsRegistrationTech() throws Exception {
doReturn(true).when(mFeatureFlags).changeMethodOfObtainingImsRegistrationRadioTech();
@@ -1882,9 +1845,6 @@
doReturn(true).when(mPhone2).isDataAllowed();
doReturn(true).when(mDataSettingsManager2).isDataEnabled();
- // 3.1 No default network
- doReturn(null).when(mConnectivityManager).getNetworkCapabilities(any());
-
mPhoneSwitcherUT.sendEmptyMessage(EVENT_EVALUATE_AUTO_SWITCH);
}
@@ -2040,7 +2000,6 @@
initializeSubControllerMock();
initializeCommandInterfacesMock();
initializeTelRegistryMock();
- initializeConnManagerMock();
initializeConfigMock();
mPhoneSwitcherUT = new PhoneSwitcher(mMaxDataAttachModemCount, mContext, Looper.myLooper(),
@@ -2154,21 +2113,6 @@
* Capture mNetworkProviderMessenger so that testing can request or release
* network requests on PhoneSwitcher.
*/
- private void initializeConnManagerMock() {
- mConnectivityManager = (ConnectivityManager)
- mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- doAnswer(invocation -> {
- mNetworkProviderMessenger =
- ((NetworkProvider) invocation.getArgument(0)).getMessenger();
- return null;
- }).when(mConnectivityManager).registerNetworkProvider(any());
- }
-
- /**
- * Capture mNetworkProviderMessenger so that testing can request or release
- * network requests on PhoneSwitcher.
- */
private void initializeSubControllerMock() throws Exception {
doReturn(mDefaultDataSub).when(mSubscriptionManagerService).getDefaultDataSubId();
doReturn(mDefaultDataSub).when(mMockedIsub).getDefaultDataSubId();
@@ -2265,13 +2209,7 @@
NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
0, NetworkRequest.Type.REQUEST);
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
- message.arg1 = score;
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
-
+ mPhoneSwitcherUT.onRequestNetwork(networkRequest);
return networkRequest;
}
@@ -2289,14 +2227,7 @@
}
NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
1, NetworkRequest.Type.REQUEST);
-
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_REQUEST_NETWORK;
- message.arg1 = 50; // Score
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
-
+ mPhoneSwitcherUT.onRequestNetwork(networkRequest);
return networkRequest;
}
@@ -2304,10 +2235,6 @@
* Tell PhoneSwitcher to release a network request.
*/
private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
- Message message = Message.obtain();
- message.what = android.net.NetworkProvider.CMD_CANCEL_REQUEST;
- message.obj = networkRequest;
- mNetworkProviderMessenger.send(message);
- processAllMessages();
+ mPhoneSwitcherUT.onReleaseNetwork(networkRequest);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
new file mode 100644
index 0000000..2fdf9e6
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.data;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.NonNull;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkCapabilities;
+import android.net.NetworkProvider;
+import android.net.NetworkRequest;
+import android.net.NetworkScore;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.connectivity.android.net.INetworkOfferCallback;
+import android.os.Looper;
+import android.telephony.Annotation.NetCapability;
+import android.telephony.SubscriptionManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Arrays;
+import java.util.Set;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class TelephonyNetworkProviderTest extends TelephonyTest {
+
+ private TelephonyNetworkProvider mTelephonyNetworkProvider;
+
+ private PhoneSwitcherCallback mPhoneSwitcherCallback;
+
+ // Mocked classes
+ private DataNetworkController mDataNetworkController2;
+
+
+ /**
+ * Set the preferred data phone, which is supposed to take the network request.
+ *
+ * @param phoneId The phone id
+ */
+ private void setPreferredDataPhone(int phoneId) {
+ doAnswer(invocation -> {
+ TelephonyNetworkRequest request = (TelephonyNetworkRequest)
+ invocation.getArguments()[0];
+ int id = (int) invocation.getArguments()[1];
+
+ logd("shouldApplyNetworkRequest: request phone id=" + id
+ + ", preferred data phone id=" + phoneId);
+
+ TelephonyNetworkSpecifier specifier = (TelephonyNetworkSpecifier)
+ request.getNetworkSpecifier();
+ if (specifier != null) {
+ int subId = specifier.getSubscriptionId();
+ logd("shouldApplyNetworkRequest: requested on sub " + subId);
+ if (subId == 1 && mPhone.getPhoneId() == id) {
+ logd("shouldApplyNetworkRequest: matched phone 0");
+ return true;
+ }
+ if (subId == 2 && mPhone2.getPhoneId() == id) {
+ logd("shouldApplyNetworkRequest: matched phone 1");
+ return true;
+ }
+ return false;
+ }
+
+ if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) return true;
+ return id == phoneId;
+ }).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(TelephonyNetworkRequest.class),
+ anyInt());
+ }
+
+ /**
+ * Create a simple network request with internet capability.
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequest() {
+ return createNetworkRequestForSub(SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ /**
+ * Create a network request with specified network capabilities.
+ *
+ * @param caps Network capabilities
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequest(@NetCapability int... caps) {
+ return createNetworkRequestForSub(SubscriptionManager.INVALID_SUBSCRIPTION_ID, caps);
+ }
+
+ /**
+ * Create a network request with subscription id specified.
+ *
+ * @param subId The subscription in for the network request
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequestForSub(int subId) {
+ return createNetworkRequestForSub(subId, NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ /**
+ * Create the network request.
+ *
+ * @param subId The subscription id. {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if no
+ * @param caps Network capabilities in the network request need to specify.
+ *
+ * @return The network request
+ */
+ @NonNull
+ private NetworkRequest createNetworkRequestForSub(int subId, @NetCapability int... caps) {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ Arrays.stream(caps).boxed().toList().forEach(builder::addCapability);
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ builder.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+ builder.setSubscriptionIds(Set.of(subId));
+ }
+
+ return builder.build();
+ }
+
+ /** Clear all invocations from all DataNetworkControllers. */
+ private void resetInvocations() {
+ clearInvocations(mDataNetworkController);
+ clearInvocations(mDataNetworkController2);
+ }
+
+ /**
+ * Verify the request was sent to the correct phone's DataNetworkController.
+ *
+ * @param phoneId The id of the phone that the request is supposed to send
+ * @param request The network request
+ */
+ private void verifyRequestSentOnPhone(int phoneId, @NonNull NetworkRequest request) {
+ ArgumentCaptor<TelephonyNetworkRequest> requestCaptor =
+ ArgumentCaptor.forClass(TelephonyNetworkRequest.class);
+
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.getPhoneId() == phoneId) {
+ verify(phone.getDataNetworkController(), times(1)
+ .description("Did not request on phone " + phoneId))
+ .addNetworkRequest(requestCaptor.capture());
+ assertThat(requestCaptor.getValue().getNativeNetworkRequest()).isEqualTo(request);
+ } else {
+ verifyNoRequestSentOnPhone(phone.getPhoneId());
+ }
+ }
+ }
+
+ /**
+ * Verify the request was released on the specified phone's DataNetworkController.
+ *
+ * @param phoneId The id of the phone that the request is supposed to send
+ * @param request The network request
+ */
+ private void verifyRequestReleasedOnPhone(int phoneId, @NonNull NetworkRequest request) {
+ ArgumentCaptor<TelephonyNetworkRequest> requestCaptor =
+ ArgumentCaptor.forClass(TelephonyNetworkRequest.class);
+
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.getPhoneId() == phoneId) {
+ verify(phone.getDataNetworkController(), times(1)
+ .description("Did not remove on phone " + phoneId))
+ .removeNetworkRequest(requestCaptor.capture());
+ assertThat(requestCaptor.getValue().getNativeNetworkRequest()).isEqualTo(request);
+ } else {
+ verifyNoRequestReleasedOnPhone(phone.getPhoneId());
+ }
+ }
+ }
+
+ /**
+ * Verify there is no request sent on specified phone.
+ *
+ * @param phoneId The phone id
+ */
+ private void verifyNoRequestSentOnPhone(int phoneId) {
+ verify(PhoneFactory.getPhone(phoneId).getDataNetworkController(), never()
+ .description("Should not request on phone " + phoneId))
+ .addNetworkRequest(any(TelephonyNetworkRequest.class));
+ }
+
+ /**
+ * Verify there is no request released on specified phone.
+ *
+ * @param phoneId The phone id
+ */
+ private void verifyNoRequestReleasedOnPhone(int phoneId) {
+ verify(PhoneFactory.getPhone(phoneId).getDataNetworkController(), never()
+ .description("Should not release on phone " + phoneId))
+ .removeNetworkRequest(any(TelephonyNetworkRequest.class));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ logd("TelephonyNetworkProviderTest +Setup!");
+ super.setUp(getClass().getSimpleName());
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mPhone2});
+
+ mDataNetworkController2 = mock(DataNetworkController.class);
+
+ doReturn(0).when(mPhone).getPhoneId();
+ doReturn(1).when(mPhone).getSubId();
+ doReturn(1).when(mPhone2).getPhoneId();
+ doReturn(2).when(mPhone2).getSubId();
+
+ doReturn(mDataNetworkController2).when(mPhone2).getDataNetworkController();
+
+ setPreferredDataPhone(0);
+
+ doAnswer(invocation -> {
+ NetworkProvider provider = (NetworkProvider) invocation.getArguments()[0];
+ provider.setProviderId(1);
+ return 1;
+ }).when(mConnectivityManager).registerNetworkProvider(any(NetworkProvider.class));
+
+ mTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
+ mContext, mFeatureFlags);
+
+ ArgumentCaptor<PhoneSwitcherCallback> callbackCaptor =
+ ArgumentCaptor.forClass(PhoneSwitcherCallback.class);
+ verify(mPhoneSwitcher).registerCallback(callbackCaptor.capture());
+ mPhoneSwitcherCallback = callbackCaptor.getValue();
+
+ logd("TelephonyNetworkProviderTest -Setup!");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logd("tearDown");
+ super.tearDown();
+ }
+
+ @Test
+ public void testRegisterProvider() {
+ verify(mConnectivityManager).registerNetworkProvider(any(TelephonyNetworkProvider.class));
+
+ ArgumentCaptor<NetworkCapabilities> capsCaptor =
+ ArgumentCaptor.forClass(NetworkCapabilities.class);
+ verify(mConnectivityManager).offerNetwork(anyInt(), any(NetworkScore.class),
+ capsCaptor.capture(), any(INetworkOfferCallback.class));
+
+ NetworkCapabilities caps = capsCaptor.getValue();
+
+ TelephonyNetworkRequest.getAllSupportedNetworkCapabilities().forEach(
+ (cap) -> assertThat(caps.hasCapability(cap)));
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+ assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)).isTrue();
+ assertThat(caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+ assertThat(caps.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+
+ assertThat(caps.getNetworkSpecifier()).isInstanceOf(MatchAllNetworkSpecifier.class);
+ }
+
+ @Test
+ public void testRequestNetwork() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ }
+
+ @Test
+ public void testReleaseNetwork() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ resetInvocations();
+
+ // Now release the network request.
+ mTelephonyNetworkProvider.onNetworkUnneeded(request);
+ // Should release on phone 0
+ verifyRequestReleasedOnPhone(0, request);
+ resetInvocations();
+
+ // Release the same request again should not result in another remove
+ mTelephonyNetworkProvider.onNetworkUnneeded(request);
+ verifyNoRequestReleasedOnPhone(0);
+ verifyNoRequestReleasedOnPhone(1);
+ }
+
+ @Test
+ public void testRequestNetworkDuplicate() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+
+ resetInvocations();
+ // send the same request again should be blocked.
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ verifyNoRequestSentOnPhone(0);
+ verifyNoRequestSentOnPhone(1);
+ }
+
+ @Test
+ public void testRequestNetworkPreferredPhone1() {
+ setPreferredDataPhone(1);
+
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 1
+ verifyRequestSentOnPhone(1, request);
+ }
+
+ @Test
+ public void testRequestEmergencyNetwork() {
+ setPreferredDataPhone(1);
+
+ NetworkRequest request = createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_EIMS);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ }
+
+ @Test
+ public void testRequestNetworkOnSpecifiedSub() {
+ NetworkRequest request = createNetworkRequestForSub(1);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ verifyRequestSentOnPhone(0, request);
+
+ resetInvocations();
+ request = createNetworkRequestForSub(2);
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 1
+ verifyRequestSentOnPhone(1, request);
+ }
+
+ @Test
+ public void testPreferredDataSwitch() {
+ NetworkRequest request = createNetworkRequest();
+ mTelephonyNetworkProvider.onNetworkNeeded(request);
+ // Should request on phone 0
+ verifyRequestSentOnPhone(0, request);
+ resetInvocations();
+
+ // Now switch from phone 0 to phone 1
+ setPreferredDataPhone(1);
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(1);
+ verifyRequestReleasedOnPhone(0, request);
+ verifyRequestSentOnPhone(1, request);
+ resetInvocations();
+
+ // Now switch back to phone 0
+ setPreferredDataPhone(0);
+ mPhoneSwitcherCallback.onPreferredDataPhoneIdChanged(0);
+ verifyRequestReleasedOnPhone(1, request);
+ verifyRequestSentOnPhone(0, request);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 9493dc7..a3a189b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -125,6 +125,7 @@
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteManager.SatelliteException;
+import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Pair;
@@ -183,6 +184,8 @@
private static final int[] ACTIVE_SUB_IDS = {SUB_ID};
private static final int TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS =
(int) TimeUnit.SECONDS.toMillis(60);
+ private static final int TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS =
+ (int) TimeUnit.SECONDS.toMillis(60);
private static final String SATELLITE_PLMN = "00103";
private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
@@ -517,6 +520,9 @@
mContextFixture.putIntResource(
R.integer.config_wait_for_satellite_enabling_response_timeout_millis,
TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS);
+ mContextFixture.putIntResource(
+ R.integer.config_satellite_wait_for_cellular_modem_off_timeout_millis,
+ TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS);
doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
@@ -727,6 +733,87 @@
processAllMessages();
verify(mMockSatelliteModemInterface, times(5))
.requestIsSatelliteSupported(any(Message.class));
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Radio is off during TN -> NTN image switch, SatelliteController should not set radio
+ // state to OFF
+ setRadioPower(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Turn on radio
+ setRadioPower(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // SatelliteController should set the radio state to OFF
+ setRadioPower(false);
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Turn on radio
+ setRadioPower(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Modem fails to power off radio. APM is disabled
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(true);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // The timer WaitForCellularModemOff time out
+ moveTimeForward(TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // APM is triggered
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertTrue(mSatelliteControllerUT.isRadioOffRequested());
+ assertTrue(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
+
+ // Modem failed to power off the radio
+ mSatelliteControllerUT.onPowerOffCellularRadioFailed();
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isRadioOn());
+ assertFalse(mSatelliteControllerUT.isRadioOffRequested());
+ assertFalse(mSatelliteControllerUT.isWaitForCellularModemOffTimerStarted());
}
@Test
@@ -847,7 +934,7 @@
mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
setRadioPower(false);
- mSatelliteControllerUT.onCellularRadioPowerOffRequested();
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
processAllMessages();
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_OFF, null);
processAllMessages();
@@ -1061,12 +1148,49 @@
resetSatelliteControllerUTToOnAndProvisionedState();
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
- mSatelliteControllerUT.onCellularRadioPowerOffRequested();
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
processAllMessages();
// Satellite should not be powered off since the feature flag oemEnabledSatelliteFlag is
// disabled
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Successfully disable satellite.
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ // Fail to enable satellite when radio is being powered off.
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ // Radio is being powered off, can not enable satellite
+ assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
+
+ // Modem failed to power off
+ mSatelliteControllerUT.onPowerOffCellularRadioFailed();
+
+ // Successfully enable satellite when radio is on.
+ mIIntegerConsumerResults.clear();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
}
@Test
@@ -1447,6 +1571,12 @@
+ "semaphore, ex=" + ex);
}
}
+
+ @Override
+ public void onSatelliteSubscriptionProvisionStateChanged(
+ List<SatelliteSubscriberProvisionStatus> status) {
+ logd("onSatelliteSubscriptionProvisionStateChanged: " + status);
+ }
};
int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(
SUB_ID, callback);
@@ -4712,5 +4842,21 @@
mIsSatelliteViaOemProvisioned = isProvisioned;
}
}
+
+ public boolean isRadioOn() {
+ synchronized (mIsRadioOnLock) {
+ return mIsRadioOn;
+ }
+ }
+
+ public boolean isRadioOffRequested() {
+ synchronized (mIsRadioOnLock) {
+ return mRadioOffRequested;
+ }
+ }
+
+ public boolean isWaitForCellularModemOffTimerStarted() {
+ return hasMessages(EVENT_WAIT_FOR_CELLULAR_MODEM_OFF_TIMED_OUT);
+ }
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
index 27f743f..846d9b6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/LogicalChannelMocker.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.uicc.euicc.apdu;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -30,7 +31,6 @@
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
-import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -48,13 +48,12 @@
int[] responseInts = isException ? null : getSelectResponse(responseObject.toString());
Throwable exception = isException ? (Throwable) responseObject : null;
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
doAnswer((Answer<Void>) invocation -> {
- Message msg = response.getValue();
+ Message msg = invocation.getArgument(2);
AsyncResult.forMessage(msg, responseInts, exception);
msg.sendToTarget();
return null;
- }).when(mockCi).iccOpenLogicalChannel(anyString(), anyInt(), response.capture());
+ }).when(mockCi).iccOpenLogicalChannel(anyString(), anyInt(), any());
return LOGICAL_CHANNEL;
}
@@ -64,22 +63,20 @@
*/
public static void mockSendToLogicalChannel(CommandsInterface mockCi, int channel,
Object... responseObjects) {
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
-
doAnswer(new Answer() {
private int mIndex = 0;
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
- Object responseObject = responseObjects[mIndex++];
- mockIccTransmitApduLogicalChannelResponse(response, responseObject);
+ Object response = responseObjects[mIndex++];
+ mockIccTransmitApduLogicalChannelResponse(invocation.getArgument(8), response);
return null;
}
}).when(mockCi).iccTransmitApduLogicalChannel(eq(channel), anyInt(), anyInt(), anyInt(),
- anyInt(), anyInt(), anyString(), anyBoolean(), response.capture());
+ anyInt(), anyInt(), anyString(), anyBoolean(), any());
}
- private static void mockIccTransmitApduLogicalChannelResponse(ArgumentCaptor<Message> response,
+ private static void mockIccTransmitApduLogicalChannelResponse(Message msg,
Object responseObject) throws Throwable {
boolean isException = responseObject instanceof Throwable;
@@ -95,20 +92,18 @@
IccIoResult result = isException ? null : new IccIoResult(sw1, sw2, hex);
Throwable exception = isException ? (Throwable) responseObject : null;
- Message msg = response.getValue();
AsyncResult.forMessage(msg, result, exception);
msg.sendToTarget();
}
public static void mockCloseLogicalChannel(CommandsInterface mockCi, int channel) {
- ArgumentCaptor<Message> response = ArgumentCaptor.forClass(Message.class);
doAnswer((Answer<Void>) invocation -> {
- Message msg = response.getValue();
+ Message msg = invocation.getArgument(2);
AsyncResult.forMessage(msg);
msg.sendToTarget();
return null;
}).when(mockCi).iccCloseLogicalChannel(eq(channel),
- eq(true /*isEs10*/), response.capture());
+ eq(true /*isEs10*/), any());
}
private static int[] getSelectResponse(String responseHex) {