Delay handover tear down due to policy for call
When a handover is not allowed due to handover policy, delay the tear down until the call ends.
Fix: 270895912
Test: basic voice call + data browsing
Change-Id: I7c3a850fb2ad18843b57f9147cdf1558e3b56668
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 9a5b506..c769bcc 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1 +1,8 @@
package: "com.android.internal.telephony.flags"
+
+flag {
+ name: "relax_ho_teardown"
+ namespace: "telephony"
+ description: "Relax handover tear down if the device is currently in voice call."
+ bug: "270895912"
+}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index eaaf0a5..6858c6a 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -155,6 +155,21 @@
}
/**
+ * Check if all the disallowed reasons are a subset of the given reason.
+ *
+ * @param reasons The given reason to check
+ * @return {@code true} if it doesn't contain any disallowed reasons other than the given
+ * reasons.
+ */
+ public boolean isSubsetOf(DataDisallowedReason... reasons) {
+ int matched = 0;
+ for (DataDisallowedReason requestedReason : reasons) {
+ if (mDataDisallowedReasons.contains(requestedReason)) matched++;
+ }
+ return matched == mDataDisallowedReasons.size();
+ }
+
+ /**
* Check if the any of the disallowed reasons match one of the provided reason.
*
* @param reasons The given reasons to check.
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index d13aaf2..3073f49 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -3236,9 +3236,12 @@
logl("Start handover " + dataNetwork + " to "
+ AccessNetworkConstants.transportTypeToString(targetTransport));
dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry);
- } else if (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE)
- && dataNetwork.shouldDelayImsTearDownDueToInCall()) {
- // We try to preserve voice call in the case of temporary preferred transport mismatch
+ } else if (dataNetwork.shouldDelayImsTearDownDueToInCall()
+ && (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE)
+ || mFeatureFlags.relaxHoTeardown() && 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) {
dataHandoverRetryEntry.setState(DataRetryEntry.RETRY_STATE_FAILED);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
index 63f3e4f..6d4c0c1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
@@ -16,10 +16,10 @@
package com.android.internal.telephony.data;
-import com.android.internal.telephony.TelephonyTest;
-
import static com.google.common.truth.Truth.assertThat;
+import com.android.internal.telephony.TelephonyTest;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -59,4 +59,32 @@
DataEvaluation.DataDisallowedReason.DATA_DISABLED);
assertThat(mDataEvaluationUT.getDataDisallowedReasons().size()).isEqualTo(1);
}
+
+
+ @Test
+ public void testIsSubsetOf() {
+ mDataEvaluationUT = new DataEvaluation(DataEvaluation.DataEvaluationReason.DATA_RETRY);
+ assertThat(mDataEvaluationUT.isSubsetOf(
+ DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isTrue();
+ mDataEvaluationUT.addDataDisallowedReason(
+ DataEvaluation.DataDisallowedReason.DATA_DISABLED);
+ assertThat(mDataEvaluationUT.isSubsetOf(
+ DataEvaluation.DataDisallowedReason.DATA_DISABLED)).isTrue();
+ assertThat(mDataEvaluationUT.isSubsetOf(
+ DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+ }
+
+ @Test
+ public void testContainsOnly() {
+ mDataEvaluationUT = new DataEvaluation(DataEvaluation.DataEvaluationReason.DATA_RETRY);
+ assertThat(mDataEvaluationUT.containsOnly(
+ DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+ mDataEvaluationUT.addDataDisallowedReason(
+ DataEvaluation.DataDisallowedReason.DATA_DISABLED);
+ assertThat(mDataEvaluationUT.containsOnly(
+ DataEvaluation.DataDisallowedReason.DATA_DISABLED)).isTrue();
+ assertThat(mDataEvaluationUT.containsOnly(
+ DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+ }
+
}
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 d25a504..5e7213b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -2459,8 +2459,7 @@
new String[]{"source=EUTRAN, target=IWLAN, type=disallowed, capabilities=MMS|IMS",
"source=IWLAN, target=EUTRAN, type=disallowed, capabilities=MMS"});
// Force data config manager to reload the carrier config.
- mDataNetworkControllerUT.getDataConfigManager().obtainMessage(
- 1/*EVENT_CARRIER_CONFIG_CHANGED*/).sendToTarget();
+ carrierConfigChanged();
processAllMessages();
testSetupImsDataNetwork();
@@ -2501,6 +2500,36 @@
}
@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);
+ mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
+ new String[]{"source=EUTRAN, target=IWLAN, type=disallowed, capabilities=MMS|IMS"});
+ carrierConfigChanged();
+
+ testSetupImsDataNetwork();
+
+ // Ringing an active call, should delay handover tear down
+ doReturn(PhoneConstants.State.RINGING).when(mCT).getState();
+ updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+
+ // Verify network is still connected due to active voice call
+ verify(mMockedWwanDataServiceManager, never()).deactivateDataCall(anyInt(),
+ eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
+
+ // Verify tear down after call ends
+ doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
+ mDataNetworkControllerUT.obtainMessage(EVENT_VOICE_CALL_ENDED).sendToTarget();
+ processAllFutureMessages();
+
+ verify(mMockedWwanDataServiceManager).deactivateDataCall(anyInt(),
+ eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
+ }
+
+ @Test
public void testHandoverDataNetworkNotAllowedByRoamingPolicy() throws Exception {
mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
new String[]{"source=EUTRAN|NGRAN|IWLAN, target=EUTRAN|NGRAN|IWLAN, roaming=true, "