Honor retry timer from setup data call response for emergency request
For emergency network request, added an option for data frameworks to
honor retry timer returned from the previous setup data call response.
Bug: 321119000
Test: Basic telephony functionality tests
Test: atest DataNetworkControllerTest
Merged-In: I4aa32fc550dc47770e060abbe8f30156cc7d682e
Change-Id: I4aa32fc550dc47770e060abbe8f30156cc7d682e
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index f7fe4ad..832eb61 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -1352,6 +1352,17 @@
}
/**
+ * @return Indicating whether the retry timer from setup data call response for data throttling
+ * should be honored for emergency network request. By default this is off, meaning emergency
+ * network requests will ignore the previous retry timer passed in from setup data call
+ * response.
+ */
+ public boolean shouldHonorRetryTimerForEmergencyNetworkRequest() {
+ return mResources.getBoolean(
+ com.android.internal.R.bool.config_honor_data_retry_timer_for_emergency_network);
+ }
+
+ /**
* Log debug messages.
* @param s debug messages
*/
@@ -1394,6 +1405,8 @@
pw.increaseIndent();
mDataHandoverRetryRules.forEach(pw::println);
pw.decreaseIndent();
+ pw.println("shouldHonorRetryTimerForEmergencyNetworkRequest="
+ + shouldHonorRetryTimerForEmergencyNetworkRequest());
pw.println("mSetupDataCallAnomalyReport=" + mSetupDataCallAnomalyReportThreshold);
pw.println("mNetworkUnwantedAnomalyReport=" + mNetworkUnwantedAnomalyReportThreshold);
pw.println("mImsReleaseRequestAnomalyReport=" + mImsReleaseRequestAnomalyReportThreshold);
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 57a0f5a..db78b8f 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1453,9 +1453,25 @@
// Bypass all checks for emergency network request.
if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
+ DataProfile emergencyProfile = mDataProfileManager.getDataProfileForNetworkRequest(
+ networkRequest, getDataNetworkType(transport), true);
+
+ // Check if the profile is being throttled.
+ if (mDataConfigManager.shouldHonorRetryTimerForEmergencyNetworkRequest()
+ && emergencyProfile != null
+ && mDataRetryManager.isDataProfileThrottled(emergencyProfile, transport)) {
+ evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_THROTTLED);
+ log("Emergency network request is throttled by the previous setup data "
+ + "call response.");
+ log(evaluation.toString());
+ networkRequest.setEvaluation(evaluation);
+ return evaluation;
+ }
+
evaluation.addDataAllowedReason(DataAllowedReason.EMERGENCY_REQUEST);
- evaluation.setCandidateDataProfile(mDataProfileManager.getDataProfileForNetworkRequest(
- networkRequest, getDataNetworkType(transport), true));
+ if (emergencyProfile != null) {
+ evaluation.setCandidateDataProfile(emergencyProfile);
+ }
networkRequest.setEvaluation(evaluation);
log(evaluation.toString());
return evaluation;
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 d96bac4..e49d304 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -577,8 +577,26 @@
private void serviceStateChanged(@NetworkType int networkType,
@RegistrationState int dataRegState, @RegistrationState int voiceRegState,
@RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri) {
+ boolean isEmergencyOnly = false;
+ if (dataRegState == NetworkRegistrationInfo.REGISTRATION_STATE_DENIED) {
+ isEmergencyOnly = true;
+ }
ServiceState ss = createSS(networkType, networkType, dataRegState, voiceRegState,
- iwlanRegState, dsri);
+ iwlanRegState, dsri, isEmergencyOnly);
+
+ doReturn(ss).when(mSST).getServiceState();
+ doReturn(ss).when(mPhone).getServiceState();
+
+ mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
+ processAllMessages();
+ }
+
+ private void serviceStateChanged(@NetworkType int networkType,
+ @RegistrationState int dataRegState, @RegistrationState int voiceRegState,
+ @RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri,
+ boolean isEmergencyOnly) {
+ ServiceState ss = createSS(networkType, networkType, dataRegState, voiceRegState,
+ iwlanRegState, dsri, isEmergencyOnly);
doReturn(ss).when(mSST).getServiceState();
doReturn(ss).when(mPhone).getServiceState();
@@ -590,7 +608,8 @@
private ServiceState createSS(@NetworkType int dataNetworkType,
@NetworkType int voiceNetworkType,
@RegistrationState int dataRegState, @RegistrationState int voiceRegState,
- @RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri) {
+ @RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri,
+ boolean isEmergencyOnly) {
if (dsri == null) {
dsri = new DataSpecificRegistrationInfo.Builder(8)
.setNrAvailable(true)
@@ -609,6 +628,7 @@
.setRegistrationState(dataRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
+ .setEmergencyOnly(isEmergencyOnly)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
@@ -616,6 +636,7 @@
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(iwlanRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setEmergencyOnly(isEmergencyOnly)
.build());
ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
@@ -623,6 +644,7 @@
.setAccessNetworkTechnology(voiceNetworkType)
.setRegistrationState(voiceRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+ .setEmergencyOnly(isEmergencyOnly)
.build());
ss.setDataRoamingFromRegistration(dataRegState
@@ -725,10 +747,18 @@
mCarrierConfig.putIntArray(CarrierConfigManager
.KEY_CAPABILITIES_EXEMPT_FROM_SINGLE_DC_CHECK_INT_ARRAY,
new int[]{NetworkCapabilities.NET_CAPABILITY_IMS});
+ mCarrierConfig.putBooleanArray(
+ CarrierConfigManager.KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY,
+ new boolean[] {false, false, true, false, false}
+ );
+ mCarrierConfig.putLongArray(CarrierConfigManager.KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY,
+ new long[] {180000, 180000, 180000, 180000});
mContextFixture.putResource(com.android.internal.R.string.config_bandwidthEstimateSource,
"bandwidth_estimator");
+ mContextFixture.putBooleanResource(com.android.internal.R.bool
+ .config_honor_data_retry_timer_for_emergency_network, true);
mContextFixture.putIntResource(com.android.internal.R.integer
.config_delay_for_ims_dereg_millis, 3000);
mContextFixture.putBooleanResource(com.android.internal.R.bool
@@ -1928,6 +1958,53 @@
}
@Test
+ public void testEmergencyRequestWithThrottling() throws Exception {
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, /* data */
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, /* voice */
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, /* iwlan */
+ null, false);
+ mDataNetworkControllerUT.getDataRetryManager()
+ .registerCallback(mMockedDataRetryManagerCallback);
+
+ setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.PROTOCOL_ERRORS,
+ 10000, false);
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_EIMS));
+ processAllMessages();
+
+ // There should be only one attempt, and no retry should happen because the second one
+ // was throttled.
+ verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+
+ ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor =
+ ArgumentCaptor.forClass(List.class);
+ verify(mMockedDataRetryManagerCallback)
+ .onThrottleStatusChanged(throttleStatusCaptor.capture());
+ assertThat(throttleStatusCaptor.getValue()).hasSize(1);
+ ThrottleStatus throttleStatus = throttleStatusCaptor.getValue().get(0);
+ assertThat(throttleStatus.getApnType()).isEqualTo(ApnSetting.TYPE_EMERGENCY);
+ assertThat(throttleStatus.getRetryType())
+ .isEqualTo(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION);
+ assertThat(throttleStatus.getTransportType())
+ .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ Mockito.reset(mMockedWwanDataServiceManager);
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_DENIED, /* data */
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, /* voice */
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, /* iwlan */
+ null, true);
+
+ // No retry should happen because the second one was throttled.
+ verify(mMockedWwanDataServiceManager, never()).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+ }
+
+ @Test
public void testHandoverRuleFromString() {
HandoverRule handoverRule = new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, "
+ "target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed");
@@ -4503,7 +4580,7 @@
TelephonyManager.NETWORK_TYPE_1xRTT /* voice RAT */,
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING ,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
- NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null);
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null, true);
doReturn(ss).when(mSST).getServiceState();
mDataNetworkControllerUT.obtainMessage(17/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
mDataNetworkControllerUT.removeNetworkRequest(request);