Fixed out of boundary exception in data retry
Network request can be removed before retry happens. We
need to check if the request is still present.
Bug: 226642219
Test: atest FrameworksTelephonyTests
Change-Id: I8ba7dc03e80bddb351ddf264a18c096ee3d50792
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 5dd819c..f5a017d 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -1702,7 +1702,7 @@
* {@link #evaluateDataNetwork(DataNetwork, DataEvaluationReason)}.
* @return The tear down reason.
*/
- private @TearDownReason int getTearDownReason(@NonNull DataEvaluation dataEvaluation) {
+ private static @TearDownReason int getTearDownReason(@NonNull DataEvaluation dataEvaluation) {
if (dataEvaluation.containsDisallowedReasons()) {
switch (dataEvaluation.getDataDisallowedReasons().get(0)) {
case DATA_DISABLED:
@@ -2145,6 +2145,14 @@
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onAnyDataNetworkExistingChanged(mAnyDataNetworkExisting)));
}
+
+ requestList.removeIf(request -> !mAllNetworkRequestList.contains(request));
+ if (requestList.isEmpty()) {
+ log("onDataNetworkSetupFailed: All requests have been released. "
+ + "Will not evaluate retry.");
+ return;
+ }
+
// Data retry manager will determine if retry is needed. If needed, retry will be scheduled.
mDataRetryManager.evaluateDataSetupRetry(dataNetwork.getDataProfile(),
dataNetwork.getTransport(), requestList, cause, retryDelayMillis);
@@ -2179,8 +2187,17 @@
* @param dataSetupRetryEntry The data setup retry entry scheduled by {@link DataRetryManager}.
*/
private void onDataNetworkSetupRetry(@NonNull DataSetupRetryEntry dataSetupRetryEntry) {
+ // The request might be already removed before retry happens. Remove them from the list
+ // if that's the case.
+ dataSetupRetryEntry.networkRequestList.removeIf(
+ request -> !mAllNetworkRequestList.contains(request));
+ if (dataSetupRetryEntry.networkRequestList.isEmpty()) {
+ loge("onDataNetworkSetupRetry: Request list is empty. Abort retry.");
+ return;
+ }
TelephonyNetworkRequest telephonyNetworkRequest =
dataSetupRetryEntry.networkRequestList.get(0);
+
int networkCapability = telephonyNetworkRequest.getApnTypeNetworkCapability();
int preferredTransport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
networkCapability);
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 b2c2bbb..b06db42 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -2061,4 +2061,22 @@
pdcs = pdcsCaptor.getValue();
assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
}
+
+ @Test
+ public void testNetworkRequestRemovedBeforeRetry() {
+ setFailedSetupDataResponse(mMockedWwanDataServiceManager, DataFailCause.CONGESTION,
+ DataCallResponse.RETRY_DURATION_UNDEFINED);
+ TelephonyNetworkRequest networkRequest = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(networkRequest);
+ logd("Removing network request.");
+ mDataNetworkControllerUT.removeNetworkRequest(networkRequest);
+ processAllMessages();
+
+ // There should be only one invocation, which is the original setup data request. There
+ // shouldn't be more than 1 (i.e. should not retry).
+ verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
+ any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(),
+ any(), any(), anyBoolean(), any(Message.class));
+ }
}