Loading src/java/com/android/internal/telephony/data/DataRetryManager.java +62 −36 Original line number Diff line number Diff line Loading @@ -1168,7 +1168,7 @@ public class DataRetryManager extends Handler { // when unthrottling happens, we still want to retry and we'll need // a type there so we know what to retry. Using RETRY_TYPE_NONE // ThrottleStatus is just for API backwards compatibility reason. updateThrottleStatus(dataProfile, requestList, null, throttleDataProfile(dataProfile, requestList, null, ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport, Long.MAX_VALUE); return; } else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) { Loading @@ -1180,7 +1180,7 @@ public class DataRetryManager extends Handler { .setDataProfile(dataProfile) .setTransport(transport) .build(); updateThrottleStatus(dataProfile, requestList, null, throttleDataProfile(dataProfile, requestList, null, ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport, dataSetupRetryEntry.retryElapsedTime); schedule(dataSetupRetryEntry); Loading Loading @@ -1298,7 +1298,7 @@ public class DataRetryManager extends Handler { // when unthrottling happens, we still want to retry and we'll need // a type there so we know what to retry. Using RETRY_TYPE_NONE // ThrottleStatus is just for API backwards compatibility reason. updateThrottleStatus(dataNetwork.getDataProfile(), throttleDataProfile(dataNetwork.getDataProfile(), dataNetwork.getAttachedNetworkRequestList(), dataNetwork, ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport, Long.MAX_VALUE); } else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) { Loading @@ -1308,7 +1308,7 @@ public class DataRetryManager extends Handler { .setDataNetwork(dataNetwork) .build(); updateThrottleStatus(dataNetwork.getDataProfile(), throttleDataProfile(dataNetwork.getDataProfile(), dataNetwork.getAttachedNetworkRequestList(), dataNetwork, ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport, dataHandoverRetryEntry.retryElapsedTime); Loading Loading @@ -1534,7 +1534,7 @@ public class DataRetryManager extends Handler { * @param expirationTime The expiration time of data throttling. This is the time retrieved from * {@link SystemClock#elapsedRealtime()}. */ private void updateThrottleStatus(@NonNull DataProfile dataProfile, private void throttleDataProfile(@NonNull DataProfile dataProfile, @Nullable NetworkRequestList networkRequestList, @Nullable DataNetwork dataNetwork, @RetryType int retryType, @TransportType int transport, @ElapsedRealtimeLong long expirationTime) { Loading Loading @@ -1565,21 +1565,7 @@ public class DataRetryManager extends Handler { ? ThrottleStatus.RETRY_TYPE_NONE : retryType; // Report to the clients. final List<ThrottleStatus> throttleStatusList = new ArrayList<>(); if (dataProfile.getApnSetting() != null) { throttleStatusList.addAll(dataProfile.getApnSetting().getApnTypes().stream() .map(apnType -> new ThrottleStatus.Builder() .setApnType(apnType) .setRetryType(dataRetryType) .setSlotIndex(mPhone.getPhoneId()) .setThrottleExpiryTimeMillis(expirationTime) .setTransportType(transport) .build()) .collect(Collectors.toList())); } mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); notifyThrottleStatus(dataProfile, expirationTime, dataRetryType, transport); } /** Loading Loading @@ -1650,23 +1636,9 @@ public class DataRetryManager extends Handler { // Make it final so it can be used in the lambda function below. final int dataRetryType = retryType; if (unthrottledProfile != null && unthrottledProfile.getApnSetting() != null) { unthrottledProfile.getApnSetting().setPermanentFailed(false); throttleStatusList.addAll(unthrottledProfile.getApnSetting().getApnTypes().stream() .map(apnType -> new ThrottleStatus.Builder() .setApnType(apnType) .setSlotIndex(mPhone.getPhoneId()) .setNoThrottle() .setRetryType(dataRetryType) .setTransportType(transport) .build()) .collect(Collectors.toList())); } mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); if (unthrottledProfile != null) { notifyThrottleStatus(unthrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME, dataRetryType, transport); // cancel pending retries since we will soon schedule an immediate retry cancelRetriesForDataProfile(unthrottledProfile, transport); } Loading Loading @@ -1799,6 +1771,60 @@ public class DataRetryManager extends Handler { && ((DataHandoverRetryEntry) entry).dataNetwork == dataNetwork && entry.getState() == DataRetryEntry.RETRY_STATE_NOT_RETRIED) .forEach(entry -> entry.setState(DataRetryEntry.RETRY_STATE_CANCELLED)); long now = SystemClock.elapsedRealtime(); DataThrottlingEntry dataUnThrottlingEntry = mDataThrottlingEntries.stream() .filter(entry -> dataNetwork == entry.dataNetwork && entry.expirationTimeMillis > now).findAny().orElse(null); if (dataUnThrottlingEntry == null) { return; } log("onCancelPendingHandoverRetry removed throttling entry:" + dataUnThrottlingEntry); DataProfile unThrottledProfile = dataUnThrottlingEntry.dataNetwork.getDataProfile(); final int transport = dataUnThrottlingEntry.transport; notifyThrottleStatus(unThrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME, ThrottleStatus.RETRY_TYPE_HANDOVER, transport); mDataThrottlingEntries.removeIf(entry -> dataNetwork == entry.dataNetwork); } /** * Notify listeners of throttle status for a given data profile * * @param dataProfile Data profile for this throttling status notification * @param expirationTime Expiration time of throttling status. {@link * ThrottleStatus.Builder#NO_THROTTLE_EXPIRY_TIME} indicates un-throttling. * @param dataRetryType Retry type of this throttling notification. * @param transportType Transport type of this throttling notification. */ private void notifyThrottleStatus( @NonNull DataProfile dataProfile, long expirationTime, @RetryType int dataRetryType, @TransportType int transportType) { if (dataProfile.getApnSetting() != null) { final boolean unThrottled = expirationTime == ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME; if (unThrottled) { dataProfile.getApnSetting().setPermanentFailed(false); } final List<ThrottleStatus> throttleStatusList = new ArrayList<>( dataProfile.getApnSetting().getApnTypes().stream() .map(apnType -> { ThrottleStatus.Builder builder = new ThrottleStatus.Builder() .setApnType(apnType) .setSlotIndex(mPhone.getPhoneId()) .setRetryType(dataRetryType) .setTransportType(transportType); if (unThrottled) { builder.setNoThrottle(); } else { builder.setThrottleExpiryTimeMillis(expirationTime); } return builder.build(); }).toList()); mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); } } /** Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +0 −3 Original line number Diff line number Diff line Loading @@ -3485,9 +3485,6 @@ public class DataNetworkControllerTest extends TelephonyTest { // Verify retry is cleared on this network assertThat(mDataNetworkControllerUT.getDataRetryManager() .isAnyHandoverRetryScheduled(network)).isFalse(); // Verify the data profile is still throttled assertThat(mDataNetworkControllerUT.getDataRetryManager().isDataProfileThrottled( network.getDataProfile(), AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).isTrue(); } @Test Loading tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java +25 −4 Original line number Diff line number Diff line Loading @@ -507,17 +507,38 @@ public class DataRetryManagerTest extends TelephonyTest { // Test: cancelPendingHandoverRetry DataNetwork mockDn = Mockito.mock(DataNetwork.class); NetworkRequest request = new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) .build(); TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags); DataNetworkController.NetworkRequestList networkRequestList = new DataNetworkController.NetworkRequestList(tnr); doReturn(networkRequestList).when(mockDn).getAttachedNetworkRequestList(); doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mockDn).getTransport(); doReturn(mDataProfile3).when(mockDn).getDataProfile(); Field field = DataRetryManager.class.getDeclaredField("mDataRetryEntries"); field.setAccessible(true); List<DataRetryEntry> mDataRetryEntries = (List<DataRetryEntry>) field.get(mDataRetryManagerUT); retry = new DataHandoverRetryEntry.Builder<>() .setDataNetwork(mockDn) .build(); mDataRetryEntries.add(retry); mDataRetryManagerUT.evaluateDataHandoverRetry(mockDn, 123, 1000); processAllMessages(); mDataRetryManagerUT.cancelPendingHandoverRetry(mockDn); Mockito.clearInvocations(mDataRetryManagerCallbackMock); processAllMessages(); retry = mDataRetryEntries.get(mDataRetryEntries.size() - 1); ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor = ArgumentCaptor.forClass(List.class); verify(mDataRetryManagerCallbackMock).onThrottleStatusChanged( throttleStatusCaptor.capture()); assertThat(throttleStatusCaptor.getValue()).hasSize(1); ThrottleStatus throttleStatus = throttleStatusCaptor.getValue().get(0); assertThat(throttleStatus.getApnType()).isEqualTo(ApnSetting.TYPE_IMS); assertThat(throttleStatus.getRetryType()) .isEqualTo(ThrottleStatus.RETRY_TYPE_HANDOVER); assertThat(throttleStatus.getThrottleExpiryTimeMillis()).isEqualTo(-1); assertThat(throttleStatus.getTransportType()) .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); assertThat(mDataRetryManagerUT.isAnyHandoverRetryScheduled(mockDn)).isFalse(); assertThat(retry.getState()).isEqualTo(DataRetryEntry.RETRY_STATE_CANCELLED); } Loading Loading
src/java/com/android/internal/telephony/data/DataRetryManager.java +62 −36 Original line number Diff line number Diff line Loading @@ -1168,7 +1168,7 @@ public class DataRetryManager extends Handler { // when unthrottling happens, we still want to retry and we'll need // a type there so we know what to retry. Using RETRY_TYPE_NONE // ThrottleStatus is just for API backwards compatibility reason. updateThrottleStatus(dataProfile, requestList, null, throttleDataProfile(dataProfile, requestList, null, ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport, Long.MAX_VALUE); return; } else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) { Loading @@ -1180,7 +1180,7 @@ public class DataRetryManager extends Handler { .setDataProfile(dataProfile) .setTransport(transport) .build(); updateThrottleStatus(dataProfile, requestList, null, throttleDataProfile(dataProfile, requestList, null, ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport, dataSetupRetryEntry.retryElapsedTime); schedule(dataSetupRetryEntry); Loading Loading @@ -1298,7 +1298,7 @@ public class DataRetryManager extends Handler { // when unthrottling happens, we still want to retry and we'll need // a type there so we know what to retry. Using RETRY_TYPE_NONE // ThrottleStatus is just for API backwards compatibility reason. updateThrottleStatus(dataNetwork.getDataProfile(), throttleDataProfile(dataNetwork.getDataProfile(), dataNetwork.getAttachedNetworkRequestList(), dataNetwork, ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport, Long.MAX_VALUE); } else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) { Loading @@ -1308,7 +1308,7 @@ public class DataRetryManager extends Handler { .setDataNetwork(dataNetwork) .build(); updateThrottleStatus(dataNetwork.getDataProfile(), throttleDataProfile(dataNetwork.getDataProfile(), dataNetwork.getAttachedNetworkRequestList(), dataNetwork, ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport, dataHandoverRetryEntry.retryElapsedTime); Loading Loading @@ -1534,7 +1534,7 @@ public class DataRetryManager extends Handler { * @param expirationTime The expiration time of data throttling. This is the time retrieved from * {@link SystemClock#elapsedRealtime()}. */ private void updateThrottleStatus(@NonNull DataProfile dataProfile, private void throttleDataProfile(@NonNull DataProfile dataProfile, @Nullable NetworkRequestList networkRequestList, @Nullable DataNetwork dataNetwork, @RetryType int retryType, @TransportType int transport, @ElapsedRealtimeLong long expirationTime) { Loading Loading @@ -1565,21 +1565,7 @@ public class DataRetryManager extends Handler { ? ThrottleStatus.RETRY_TYPE_NONE : retryType; // Report to the clients. final List<ThrottleStatus> throttleStatusList = new ArrayList<>(); if (dataProfile.getApnSetting() != null) { throttleStatusList.addAll(dataProfile.getApnSetting().getApnTypes().stream() .map(apnType -> new ThrottleStatus.Builder() .setApnType(apnType) .setRetryType(dataRetryType) .setSlotIndex(mPhone.getPhoneId()) .setThrottleExpiryTimeMillis(expirationTime) .setTransportType(transport) .build()) .collect(Collectors.toList())); } mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); notifyThrottleStatus(dataProfile, expirationTime, dataRetryType, transport); } /** Loading Loading @@ -1650,23 +1636,9 @@ public class DataRetryManager extends Handler { // Make it final so it can be used in the lambda function below. final int dataRetryType = retryType; if (unthrottledProfile != null && unthrottledProfile.getApnSetting() != null) { unthrottledProfile.getApnSetting().setPermanentFailed(false); throttleStatusList.addAll(unthrottledProfile.getApnSetting().getApnTypes().stream() .map(apnType -> new ThrottleStatus.Builder() .setApnType(apnType) .setSlotIndex(mPhone.getPhoneId()) .setNoThrottle() .setRetryType(dataRetryType) .setTransportType(transport) .build()) .collect(Collectors.toList())); } mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); if (unthrottledProfile != null) { notifyThrottleStatus(unthrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME, dataRetryType, transport); // cancel pending retries since we will soon schedule an immediate retry cancelRetriesForDataProfile(unthrottledProfile, transport); } Loading Loading @@ -1799,6 +1771,60 @@ public class DataRetryManager extends Handler { && ((DataHandoverRetryEntry) entry).dataNetwork == dataNetwork && entry.getState() == DataRetryEntry.RETRY_STATE_NOT_RETRIED) .forEach(entry -> entry.setState(DataRetryEntry.RETRY_STATE_CANCELLED)); long now = SystemClock.elapsedRealtime(); DataThrottlingEntry dataUnThrottlingEntry = mDataThrottlingEntries.stream() .filter(entry -> dataNetwork == entry.dataNetwork && entry.expirationTimeMillis > now).findAny().orElse(null); if (dataUnThrottlingEntry == null) { return; } log("onCancelPendingHandoverRetry removed throttling entry:" + dataUnThrottlingEntry); DataProfile unThrottledProfile = dataUnThrottlingEntry.dataNetwork.getDataProfile(); final int transport = dataUnThrottlingEntry.transport; notifyThrottleStatus(unThrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME, ThrottleStatus.RETRY_TYPE_HANDOVER, transport); mDataThrottlingEntries.removeIf(entry -> dataNetwork == entry.dataNetwork); } /** * Notify listeners of throttle status for a given data profile * * @param dataProfile Data profile for this throttling status notification * @param expirationTime Expiration time of throttling status. {@link * ThrottleStatus.Builder#NO_THROTTLE_EXPIRY_TIME} indicates un-throttling. * @param dataRetryType Retry type of this throttling notification. * @param transportType Transport type of this throttling notification. */ private void notifyThrottleStatus( @NonNull DataProfile dataProfile, long expirationTime, @RetryType int dataRetryType, @TransportType int transportType) { if (dataProfile.getApnSetting() != null) { final boolean unThrottled = expirationTime == ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME; if (unThrottled) { dataProfile.getApnSetting().setPermanentFailed(false); } final List<ThrottleStatus> throttleStatusList = new ArrayList<>( dataProfile.getApnSetting().getApnTypes().stream() .map(apnType -> { ThrottleStatus.Builder builder = new ThrottleStatus.Builder() .setApnType(apnType) .setSlotIndex(mPhone.getPhoneId()) .setRetryType(dataRetryType) .setTransportType(transportType); if (unThrottled) { builder.setNoThrottle(); } else { builder.setThrottleExpiryTimeMillis(expirationTime); } return builder.build(); }).toList()); mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onThrottleStatusChanged(throttleStatusList))); } } /** Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +0 −3 Original line number Diff line number Diff line Loading @@ -3485,9 +3485,6 @@ public class DataNetworkControllerTest extends TelephonyTest { // Verify retry is cleared on this network assertThat(mDataNetworkControllerUT.getDataRetryManager() .isAnyHandoverRetryScheduled(network)).isFalse(); // Verify the data profile is still throttled assertThat(mDataNetworkControllerUT.getDataRetryManager().isDataProfileThrottled( network.getDataProfile(), AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).isTrue(); } @Test Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java +25 −4 Original line number Diff line number Diff line Loading @@ -507,17 +507,38 @@ public class DataRetryManagerTest extends TelephonyTest { // Test: cancelPendingHandoverRetry DataNetwork mockDn = Mockito.mock(DataNetwork.class); NetworkRequest request = new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS) .build(); TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags); DataNetworkController.NetworkRequestList networkRequestList = new DataNetworkController.NetworkRequestList(tnr); doReturn(networkRequestList).when(mockDn).getAttachedNetworkRequestList(); doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mockDn).getTransport(); doReturn(mDataProfile3).when(mockDn).getDataProfile(); Field field = DataRetryManager.class.getDeclaredField("mDataRetryEntries"); field.setAccessible(true); List<DataRetryEntry> mDataRetryEntries = (List<DataRetryEntry>) field.get(mDataRetryManagerUT); retry = new DataHandoverRetryEntry.Builder<>() .setDataNetwork(mockDn) .build(); mDataRetryEntries.add(retry); mDataRetryManagerUT.evaluateDataHandoverRetry(mockDn, 123, 1000); processAllMessages(); mDataRetryManagerUT.cancelPendingHandoverRetry(mockDn); Mockito.clearInvocations(mDataRetryManagerCallbackMock); processAllMessages(); retry = mDataRetryEntries.get(mDataRetryEntries.size() - 1); ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor = ArgumentCaptor.forClass(List.class); verify(mDataRetryManagerCallbackMock).onThrottleStatusChanged( throttleStatusCaptor.capture()); assertThat(throttleStatusCaptor.getValue()).hasSize(1); ThrottleStatus throttleStatus = throttleStatusCaptor.getValue().get(0); assertThat(throttleStatus.getApnType()).isEqualTo(ApnSetting.TYPE_IMS); assertThat(throttleStatus.getRetryType()) .isEqualTo(ThrottleStatus.RETRY_TYPE_HANDOVER); assertThat(throttleStatus.getThrottleExpiryTimeMillis()).isEqualTo(-1); assertThat(throttleStatus.getTransportType()) .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); assertThat(mDataRetryManagerUT.isAnyHandoverRetryScheduled(mockDn)).isFalse(); assertThat(retry.getState()).isEqualTo(DataRetryEntry.RETRY_STATE_CANCELLED); } Loading