Add Handover Failure Mode to Radio Hal
On a handover request failure, the modem can now determine
whether or not to fallback. There is also the option to revert
to the legacy logic. Following the legacy logic is the default
behavior.
Test: FrameworkTelephonyTests
Bug: 161572465
Change-Id: If69faea4c7760d4aacd47297e3da42802d578381
Merged-In: If69faea4c7760d4aacd47297e3da42802d578381
diff --git a/Android.bp b/Android.bp
index 3f87578..aff9f6a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -75,6 +75,7 @@
"android.hardware.radio-V1.3-java",
"android.hardware.radio-V1.4-java",
"android.hardware.radio-V1.5-java",
+ "android.hardware.radio-V1.6-java",
"voip-common",
"ims-common",
"unsupportedappusage",
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index b3c9544..f89ad57 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -100,6 +100,7 @@
import android.telephony.TelephonyManager.PrefNetworkMode;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
+import android.telephony.data.DataCallResponse.HandoverFailureMode;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.emergency.EmergencyNumber;
@@ -191,6 +192,9 @@
/** @hide */
public static final HalVersion RADIO_HAL_VERSION_1_5 = new HalVersion(1, 5);
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_1_6 = new HalVersion(1, 6);
+
// IRadio version
private HalVersion mRadioVersion = RADIO_HAL_VERSION_UNKNOWN;
@@ -488,14 +492,23 @@
+ " is disabled");
} else {
try {
- mRadioProxy = android.hardware.radio.V1_5.IRadio.getService(
+ mRadioProxy = android.hardware.radio.V1_6.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
- mRadioVersion = RADIO_HAL_VERSION_1_5;
+ mRadioVersion = RADIO_HAL_VERSION_1_6;
} catch (NoSuchElementException e) {
}
if (mRadioProxy == null) {
try {
+ mRadioProxy = android.hardware.radio.V1_5.IRadio.getService(
+ HIDL_SERVICE_NAME[mPhoneId], true);
+ mRadioVersion = RADIO_HAL_VERSION_1_5;
+ } catch (NoSuchElementException e) {
+ }
+ }
+
+ if (mRadioProxy == null) {
+ try {
mRadioProxy = android.hardware.radio.V1_4.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_4;
@@ -1844,7 +1857,40 @@
}
try {
- if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
+ if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_6)) {
+ // IRadio V1.6
+ android.hardware.radio.V1_6.IRadio radioProxy16 =
+ (android.hardware.radio.V1_6.IRadio) radioProxy;
+
+ // Convert to HAL data profile
+ android.hardware.radio.V1_5.DataProfileInfo dpi =
+ convertToHalDataProfile15(dataProfile);
+
+ ArrayList<android.hardware.radio.V1_5.LinkAddress> addresses15 =
+ new ArrayList<>();
+ if (linkProperties != null) {
+ for (LinkAddress la : linkProperties.getAllLinkAddresses()) {
+ android.hardware.radio.V1_5.LinkAddress linkAddress =
+ new android.hardware.radio.V1_5.LinkAddress();
+ linkAddress.address = la.getAddress().getHostAddress();
+ linkAddress.properties = la.getFlags();
+ linkAddress.deprecationTime = la.getDeprecationTime();
+ linkAddress.expirationTime = la.getExpirationTime();
+ addresses15.add(linkAddress);
+ }
+ }
+
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + ",accessNetworkType="
+ + AccessNetworkType.toString(accessNetworkType) + ",isRoaming="
+ + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile
+ + ",addresses=" + addresses15 + ",dnses=" + dnses);
+ }
+
+ radioProxy16.setupDataCall_1_6(rr.mSerial, accessNetworkType, dpi, allowRoaming,
+ reason, addresses15, dnses);
+ } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_5)) {
// IRadio V1.5
android.hardware.radio.V1_5.IRadio radioProxy15 =
(android.hardware.radio.V1_5.IRadio) radioProxy;
@@ -6788,6 +6834,9 @@
String[] gateways = null;
String[] pcscfs = null;
+ @HandoverFailureMode
+ int handoverFailureMode = DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY;
+
List<LinkAddress> laList = new ArrayList<>();
if (dcResult instanceof android.hardware.radio.V1_0.SetupDataCallResult) {
@@ -6855,6 +6904,26 @@
mtu = Math.max(result.mtuV4, result.mtuV6);
mtuV4 = result.mtuV4;
mtuV6 = result.mtuV6;
+ } else if (dcResult instanceof android.hardware.radio.V1_6.SetupDataCallResult) {
+ final android.hardware.radio.V1_6.SetupDataCallResult result =
+ (android.hardware.radio.V1_6.SetupDataCallResult) dcResult;
+ cause = result.base.cause;
+ suggestedRetryTime = result.base.suggestedRetryTime;
+ cid = result.base.cid;
+ active = result.base.active;
+ protocolType = result.base.type;
+ ifname = result.base.ifname;
+ laList = result.base.addresses.stream().map(la -> createLinkAddressFromString(
+ la.address, la.properties, la.deprecationTime, la.expirationTime))
+ .collect(Collectors.toList());
+
+ dnses = result.base.dnses.stream().toArray(String[]::new);
+ gateways = result.base.gateways.stream().toArray(String[]::new);
+ pcscfs = result.base.pcscf.stream().toArray(String[]::new);
+ mtu = Math.max(result.base.mtuV4, result.base.mtuV6);
+ mtuV4 = result.base.mtuV4;
+ mtuV6 = result.base.mtuV6;
+ handoverFailureMode = result.handoverFailureMode;
} else {
Rlog.e(RILJ_LOG_TAG, "Unsupported SetupDataCallResult " + dcResult);
return null;
@@ -6919,6 +6988,7 @@
.setMtu(mtu)
.setMtuV4(mtuV4)
.setMtuV6(mtuV6)
+ .setHandoverFailureMode(handoverFailureMode)
.build();
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 0acb42f..f980c35 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -2126,9 +2126,7 @@
// failure cause and determine if we need to retry this APN later
// or not.
mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
- // TODO: The actual failure mode should come from the underlying
- // data service
- DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY);
+ dataCallResponse.getHandoverFailureMode());
transitionTo(mInactiveState);
break;
case ERROR_STALE:
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 8f09eeb..9914766 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -22,6 +22,8 @@
import static android.telephony.data.ApnSetting.PROTOCOL_IPV4V6;
import static android.telephony.data.ApnSetting.TYPE_DEFAULT;
import static android.telephony.data.ApnSetting.TYPE_IA;
+import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK;
+import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY;
import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
@@ -2481,15 +2483,27 @@
b.putInt(DATA_COMPLETE_MSG_EXTRA_REQUEST_TYPE, requestType);
b.putInt(DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE, transport);
b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK,
- (handoverFailureMode == DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK
- || (handoverFailureMode
- == DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY
- && cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED)));
+ shouldFallbackOnFailedHandover(handoverFailureMode, requestType, cause));
message.sendToTarget();
}
+ private boolean shouldFallbackOnFailedHandover(@HandoverFailureMode int handoverFailureMode,
+ @RequestNetworkType int requestType,
+ @DataFailureCause int cause) {
+ if (requestType != REQUEST_TYPE_HANDOVER) {
+ //The fallback is only relevant if the request is a handover
+ return false;
+ } else if (handoverFailureMode == HANDOVER_FAILURE_MODE_DO_FALLBACK) {
+ return true;
+ } else if (handoverFailureMode == HANDOVER_FAILURE_MODE_LEGACY) {
+ return cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED;
+ } else {
+ return false;
+ }
+ }
+
public void enableApn(@ApnType int apnType, @RequestNetworkType int requestType,
- Message onCompleteMsg) {
+ Message onCompleteMsg) {
sendMessage(obtainMessage(DctConstants.EVENT_ENABLE_APN, apnType, requestType,
onCompleteMsg));
}