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

Commit e3817780 authored by Daniel Bright's avatar Daniel Bright
Browse files

Fixup retry logic

* Preserve request type on data reconnect and retry
* Add in logic to calculate the new request type of a retry based
  on the handover failure mode

Bug: 174892203
Test: FrameworksTelephonyTests
Change-Id: I86b2610a573f1d4f58a559d86b9783ee0a4a9eb3
Merged-In: I86b2610a573f1d4f58a559d86b9783ee0a4a9eb3
parent 7342ceb3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2317,8 +2317,10 @@ public class DataConnection extends StateMachine {
                            } else if (delay >= 0) {
                                retryTime = SystemClock.elapsedRealtime() + delay;
                            }
                            int newRequestType = DcTracker.calculateNewRetryRequestType(
                                    mHandoverFailureMode, cp.mRequestType, mDcFailCause);
                            mDct.getDataThrottler().setRetryTime(mApnSetting.getApnTypeBitmask(),
                                    retryTime, dataCallResponse.getHandoverFailureMode());
                                    retryTime, newRequestType);

                            String str = "DcActivatingState: ERROR_DATA_SERVICE_SPECIFIC_ERROR "
                                    + " delay=" + delay
+15 −18
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.telephony.Annotation;
import android.telephony.Annotation.ApnType;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnThrottleStatus;
import android.telephony.data.DataCallResponse;

import com.android.internal.telephony.RetryManager;
import com.android.telephony.Rlog;
@@ -67,7 +66,7 @@ public class DataThrottler {
     * {@link RetryManager#NO_RETRY} indicates retry should never happen.
     */
    public void setRetryTime(@ApnType int apnTypes, long retryElapsedTime,
            @DataCallResponse.HandoverFailureMode int handoverFailureMode) {
            @DcTracker.RequestNetworkType int newRequestType) {
        if (retryElapsedTime < 0) {
            retryElapsedTime = RetryManager.NO_SUGGESTED_RETRY_DELAY;
        }
@@ -79,8 +78,7 @@ public class DataThrottler {
            int apnType = apnTypes & -apnTypes;

            //Update the apn throttle status
            ApnThrottleStatus newStatus =
                    createStatus(apnType, retryElapsedTime, handoverFailureMode);
            ApnThrottleStatus newStatus = createStatus(apnType, retryElapsedTime, newRequestType);

            ApnThrottleStatus oldStatus = mApnThrottleStatus.get(apnType);

@@ -130,13 +128,13 @@ public class DataThrottler {
    }

    private ApnThrottleStatus createStatus(@Annotation.ApnType int apnType, long retryElapsedTime,
            @DataCallResponse.HandoverFailureMode int handoverFailureMode) {
            @DcTracker.RequestNetworkType int newRequestType) {
        ApnThrottleStatus.Builder builder = new ApnThrottleStatus.Builder();

        if (retryElapsedTime == RetryManager.NO_SUGGESTED_RETRY_DELAY) {
            builder
                    .setNoThrottle()
                    .setRetryType(getRetryType(handoverFailureMode));
                    .setRetryType(getRetryType(newRequestType));
        } else if (retryElapsedTime == RetryManager.NO_RETRY) {
            builder
                    .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY)
@@ -144,7 +142,7 @@ public class DataThrottler {
        } else {
            builder
                    .setThrottleExpiryTimeMillis(retryElapsedTime)
                    .setRetryType(getRetryType(handoverFailureMode));
                    .setRetryType(getRetryType(newRequestType));
        }
        return builder
                .setSlotIndex(mSlotIndex)
@@ -153,18 +151,17 @@ public class DataThrottler {
                .build();
    }

    private static int getRetryType(@DataCallResponse.HandoverFailureMode int handoverFailureMode) {
        int retryType;
        int requestType = DcTracker.calcRequestType(handoverFailureMode);
        if (requestType == DcTracker.REQUEST_TYPE_NORMAL) {
            retryType = ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION;
        } else if (requestType == DcTracker.REQUEST_TYPE_HANDOVER) {
            retryType = ApnThrottleStatus.RETRY_TYPE_HANDOVER;
        } else {
            loge("createStatus: Unknown requestType=" + requestType);
            retryType = ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION;
    private static int getRetryType(@DcTracker.RequestNetworkType int newRequestType) {
        if (newRequestType == DcTracker.REQUEST_TYPE_NORMAL) {
            return ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION;
        }

        if (newRequestType == DcTracker.REQUEST_TYPE_HANDOVER) {
            return  ApnThrottleStatus.RETRY_TYPE_HANDOVER;
        }
        return retryType;

        loge("createStatus: Unknown requestType=" + newRequestType);
        return ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION;
    }

    private void sendApnThrottleStatusChanged(List<ApnThrottleStatus> statuses) {
+51 −33
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.telephony.data.ApnSetting.TYPE_DEFAULT;
import static android.telephony.data.ApnSetting.TYPE_IA;
import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK;
import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY;
import static android.telephony.data.DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL;

import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
@@ -534,7 +535,8 @@ public class DcTracker extends Handler {
                if (DBG) log("onDataReconnect: keep associated");
            }
            // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
            sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
            sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, requestType,
                    0, apnContext));
        }
    }

@@ -2421,7 +2423,7 @@ public class DcTracker extends Handler {
            if (ac != null) {
                @ApnType int apnTypes = ac.getApnTypeBitmask();
                mDataThrottler.setRetryTime(apnTypes, RetryManager.NO_SUGGESTED_RETRY_DELAY,
                        DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL);
                        REQUEST_TYPE_NORMAL);
            } else {
                loge("EVENT_APN_UNTHROTTLED: Invalid APN passed: " + apn);
            }
@@ -2496,20 +2498,19 @@ public class DcTracker extends Handler {
    private void sendRequestNetworkCompleteMsg(Message message, boolean success,
                                               @TransportType int transport,
                                               @RequestNetworkType int requestType,
                                               @HandoverFailureMode int handoverFailureMode,
                                               @DataFailureCause int cause) {
                                               boolean doFallbackOnFailedHandover) {
        if (message == null) return;

        Bundle b = message.getData();
        b.putBoolean(DATA_COMPLETE_MSG_EXTRA_SUCCESS, success);
        b.putInt(DATA_COMPLETE_MSG_EXTRA_REQUEST_TYPE, requestType);
        b.putInt(DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE, transport);
        b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK,
                shouldFallbackOnFailedHandover(handoverFailureMode, requestType, cause));
        b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK, doFallbackOnFailedHandover);
        message.sendToTarget();
    }

    private boolean shouldFallbackOnFailedHandover(@HandoverFailureMode int handoverFailureMode,
    private static boolean shouldFallbackOnFailedHandover(
                               @HandoverFailureMode int handoverFailureMode,
                               @RequestNetworkType int requestType,
                               @DataFailureCause int cause) {
        if (requestType != REQUEST_TYPE_HANDOVER) {
@@ -2524,6 +2525,33 @@ public class DcTracker extends Handler {
        }
    }

    /**
     * Calculates the new request type that will be used the next time a data connection retries
     * after a failed data call attempt.
     */
    @RequestNetworkType
    public static int calculateNewRetryRequestType(@HandoverFailureMode int handoverFailureMode,
            @RequestNetworkType int requestType,
            @DataFailureCause int cause) {
        boolean fallbackOnFailedHandover =
                shouldFallbackOnFailedHandover(handoverFailureMode, requestType, cause);
        if (requestType != REQUEST_TYPE_HANDOVER) {
            //The fallback is only relevant if the request is a handover
            return requestType;
        }

        if (fallbackOnFailedHandover) {
            // Since fallback is happening, the request type is really "NONE".
            return REQUEST_TYPE_NORMAL;
        }

        if (handoverFailureMode == HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_SETUP_NORMAL) {
            return REQUEST_TYPE_NORMAL;
        }

        return REQUEST_TYPE_HANDOVER;
    }

    public void enableApn(@ApnType int apnType, @RequestNetworkType int requestType,
            Message onCompleteMsg) {
        sendMessage(obtainMessage(DctConstants.EVENT_ENABLE_APN, apnType, requestType,
@@ -2536,7 +2564,7 @@ public class DcTracker extends Handler {
        if (apnContext == null) {
            loge("onEnableApn(" + apnType + "): NO ApnContext");
            sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, DataFailCause.NONE);
                    false);
            return;
        }

@@ -2552,7 +2580,7 @@ public class DcTracker extends Handler {
            if (DBG) log(str);
            apnContext.requestLog(str);
            sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, DataFailCause.NONE);
                    false);
            return;
        }

@@ -2568,15 +2596,13 @@ public class DcTracker extends Handler {
                    if (DBG) log("onEnableApn: 'CONNECTED' so return");
                    // Don't add to local log since this is so common
                    sendRequestNetworkCompleteMsg(onCompleteMsg, true, mTransportType,
                            requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                            DataFailCause.NONE);
                            requestType, false);
                    return;
                case DISCONNECTING:
                    if (DBG) log("onEnableApn: 'DISCONNECTING' so return");
                    apnContext.requestLog("onEnableApn state=DISCONNECTING, so return");
                    sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
                            requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                            DataFailCause.NONE);
                            requestType, false);
                    return;
                case IDLE:
                    // fall through: this is unexpected but if it happens cleanup and try setup
@@ -2605,8 +2631,7 @@ public class DcTracker extends Handler {
                addRequestNetworkCompleteMsg(onCompleteMsg, apnType);
            } else {
                sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
                        requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                        DataFailCause.NONE);
                        requestType, false);
            }
        } else {
            log("onEnableApn: config not ready yet.");
@@ -2879,6 +2904,9 @@ public class DcTracker extends Handler {
    protected void onDataSetupComplete(ApnContext apnContext, boolean success,
            @DataFailureCause int cause, @RequestNetworkType int requestType,
            @HandoverFailureMode int handoverFailureMode) {
        boolean fallbackOnFailedHandover = shouldFallbackOnFailedHandover(
                handoverFailureMode, requestType, cause);

        if (success && (handoverFailureMode != DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN
                && handoverFailureMode != DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY)) {
            Log.wtf(mLogTag, "bad failure mode: "
@@ -2890,7 +2918,7 @@ public class DcTracker extends Handler {
            if (messageList != null) {
                for (Message msg : messageList) {
                    sendRequestNetworkCompleteMsg(msg, success, mTransportType, requestType,
                            handoverFailureMode, cause);
                            fallbackOnFailedHandover);
                }
                messageList.clear();
            }
@@ -3044,22 +3072,13 @@ public class DcTracker extends Handler {
                apnContext.markApnPermanentFailed(apn);
            }

            requestType = calcRequestType(handoverFailureMode);
            onDataSetupCompleteError(apnContext, requestType,
                    shouldFallbackOnFailedHandover(handoverFailureMode, requestType, cause));
            int newRequestType = calculateNewRetryRequestType(handoverFailureMode, requestType,
                    cause);
            onDataSetupCompleteError(apnContext, newRequestType, fallbackOnFailedHandover);
        }
    }

    /**
     * Converts the handover failure mode to the corresponding request network type.
     */
    @RequestNetworkType
    public static int calcRequestType(
            @HandoverFailureMode int handoverFailureMode) {
        return (handoverFailureMode
            == DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER)
            ? REQUEST_TYPE_HANDOVER : REQUEST_TYPE_NORMAL;
    }


    /**
     * Error has occurred during the SETUP {aka bringUP} request and the DCT
@@ -3068,11 +3087,10 @@ public class DcTracker extends Handler {
     * be a delay defined by {@link ApnContext#getDelayForNextApn(boolean)}.
     */
    protected void onDataSetupCompleteError(ApnContext apnContext,
            @RequestNetworkType int requestType, boolean fallback) {
            @RequestNetworkType int requestType, boolean fallbackOnFailedHandover) {
        long delay = apnContext.getDelayForNextApn(mFailFast);

        // Check if we need to retry or not.
        if (delay >= 0 && delay != RetryManager.NO_RETRY && !fallback) {
        if (delay >= 0 && delay != RetryManager.NO_RETRY && !fallbackOnFailedHandover) {
            if (DBG) {
                log("onDataSetupCompleteError: APN type=" + apnContext.getApnType()
                        + ". Request type=" + requestTypeToString(requestType) + ", Retry in "
@@ -3652,7 +3670,7 @@ public class DcTracker extends Handler {
                break;

            case DctConstants.EVENT_TRY_SETUP_DATA:
                trySetupData((ApnContext) msg.obj, REQUEST_TYPE_NORMAL);
                trySetupData((ApnContext) msg.obj, msg.arg1);
                break;

            case DctConstants.EVENT_CLEAN_UP_CONNECTION:
+3 −2
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ public class VendorDcTracker extends DcTracker {

    @Override
    protected void onDataSetupCompleteError(ApnContext apnContext,
            @RequestNetworkType int requestType, boolean fallback) {
            @RequestNetworkType int requestType, boolean fallbackOnFailedHandover) {
        long delay = apnContext.getDelayForNextApn(mFailFast);
        if (mPhone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_pdp_reject_enable_retry)) {
@@ -275,7 +275,8 @@ public class VendorDcTracker extends DcTracker {
                    cancelReconnect(apnContext);
                    if (retry) {
                        if (DBG) log("onResetEvent: retry data call on apnContext=" + apnContext);
                        sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
                        sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA,
                                REQUEST_TYPE_NORMAL, 0, apnContext));
                    }
                }
            }
+7 −6
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.internal.telephony.dataconnection;

import static com.android.internal.telephony.dataconnection.DcTracker.REQUEST_TYPE_HANDOVER;
import static com.android.internal.telephony.dataconnection.DcTracker.REQUEST_TYPE_NORMAL;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -23,7 +26,6 @@ import static org.mockito.Mockito.verify;
import android.telephony.AccessNetworkConstants;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnThrottleStatus;
import android.telephony.data.DataCallResponse;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -87,7 +89,7 @@ public class DataThrottlerTest extends TelephonyTest {


        mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L,
                DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN);
                REQUEST_TYPE_NORMAL);
        assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
@@ -112,7 +114,7 @@ public class DataThrottlerTest extends TelephonyTest {


        mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_DUN, 13579L,
                DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
                REQUEST_TYPE_HANDOVER);
        assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));
        assertEquals(13579L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DUN));

@@ -143,7 +145,7 @@ public class DataThrottlerTest extends TelephonyTest {


        mDataThrottler.setRetryTime(ApnSetting.TYPE_MMS, -10,
                DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN);
                REQUEST_TYPE_NORMAL);
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
        processAllMessages();
@@ -158,8 +160,7 @@ public class DataThrottlerTest extends TelephonyTest {
        ));

        mDataThrottler.setRetryTime(ApnSetting.TYPE_FOTA | ApnSetting.TYPE_EMERGENCY,
                RetryManager.NO_RETRY,
                DataCallResponse.HANDOVER_FAILURE_MODE_NO_FALLBACK_RETRY_HANDOVER);
                RetryManager.NO_RETRY, REQUEST_TYPE_HANDOVER);

        processAllMessages();
        expectedStatuses.add(List.of(