Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d459cc6 authored by Sewook Seo's avatar Sewook Seo Committed by Android (Google) Code Review
Browse files

Merge "Clear handover throttling entry at DN DISCONNECTED" into main

parents eeccdbc8 300ee0dc
Loading
Loading
Loading
Loading
+62 −36
Original line number Diff line number Diff line
@@ -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) {
@@ -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);
@@ -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) {
@@ -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);
@@ -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) {
@@ -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);
    }

    /**
@@ -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);
        }
@@ -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)));
        }
    }

    /**
+0 −3
Original line number Diff line number Diff line
@@ -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
+25 −4
Original line number Diff line number Diff line
@@ -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);
    }