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

Commit 1d231588 authored by Jack Yu's avatar Jack Yu
Browse files

Unthrottle data retry in some conditions

1. Moved the APM unthrottle logic to DataThrottler.
2. Added conditional unthrottle when TAC changes.

Fix: 169648447
Test: Manual
Change-Id: I18b7b16d42bb7c74c16c17c7c2a3f10caaa5db63
parent 3caa374e
Loading
Loading
Loading
Loading
+41 −0
Original line number Original line Diff line number Diff line
@@ -242,6 +242,7 @@ public class ServiceStateTracker extends Handler {
    private RegistrantList mNrFrequencyChangedRegistrants = new RegistrantList();
    private RegistrantList mNrFrequencyChangedRegistrants = new RegistrantList();
    private RegistrantList mCssIndicatorChangedRegistrants = new RegistrantList();
    private RegistrantList mCssIndicatorChangedRegistrants = new RegistrantList();
    private final RegistrantList mAirplaneModeChangedRegistrants = new RegistrantList();
    private final RegistrantList mAirplaneModeChangedRegistrants = new RegistrantList();
    private final RegistrantList mAreaCodeChangedRegistrants = new RegistrantList();


    /* Radio power off pending flag and tag counter */
    /* Radio power off pending flag and tag counter */
    private boolean mPendingRadioPowerOffAfterDataOff = false;
    private boolean mPendingRadioPowerOffAfterDataOff = false;
@@ -650,6 +651,9 @@ public class ServiceStateTracker extends Handler {


    private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>();
    private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>();


    /* Last known TAC/LAC */
    private int mLastKnownAreaCode = CellInfo.UNAVAILABLE;

    public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
    public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
        mNitzState = TelephonyComponentFactory.getInstance()
        mNitzState = TelephonyComponentFactory.getInstance()
                .inject(NitzStateMachine.class.getName())
                .inject(NitzStateMachine.class.getName())
@@ -2554,6 +2558,19 @@ public class ServiceStateTracker extends Handler {
        return cid;
        return cid;
    }
    }


    //TODO: Move this and getCidFromCellIdentity to CellIdentityUtils.
    private static int getAreaCodeFromCellIdentity(CellIdentity id) {
        if (id == null) return CellInfo.UNAVAILABLE;
        switch(id.getType()) {
            case CellInfo.TYPE_GSM: return ((CellIdentityGsm) id).getLac();
            case CellInfo.TYPE_WCDMA: return ((CellIdentityWcdma) id).getLac();
            case CellInfo.TYPE_TDSCDMA: return ((CellIdentityTdscdma) id).getLac();
            case CellInfo.TYPE_LTE: return ((CellIdentityLte) id).getTac();
            case CellInfo.TYPE_NR: return ((CellIdentityNr) id).getTac();
            default: return CellInfo.UNAVAILABLE;
        }
    }

    private void setPhyCellInfoFromCellIdentity(ServiceState ss, CellIdentity cellIdentity) {
    private void setPhyCellInfoFromCellIdentity(ServiceState ss, CellIdentity cellIdentity) {
        if (cellIdentity == null) {
        if (cellIdentity == null) {
            if (DBG) {
            if (DBG) {
@@ -3635,6 +3652,12 @@ public class ServiceStateTracker extends Handler {


        mCellIdentity = primaryCellIdentity;
        mCellIdentity = primaryCellIdentity;


        int areaCode = getAreaCodeFromCellIdentity(mCellIdentity);
        if (areaCode != mLastKnownAreaCode && areaCode != CellInfo.UNAVAILABLE) {
            mLastKnownAreaCode = areaCode;
            mAreaCodeChangedRegistrants.notifyRegistrants();
        }

        if (hasRilVoiceRadioTechnologyChanged) {
        if (hasRilVoiceRadioTechnologyChanged) {
            updatePhoneObject();
            updatePhoneObject();
        }
        }
@@ -6222,4 +6245,22 @@ public class ServiceStateTracker extends Handler {
        // worry about unset flag which was set by other client.
        // worry about unset flag which was set by other client.
        mPhone.setAlwaysReportSignalStrength(alwaysReport);
        mPhone.setAlwaysReportSignalStrength(alwaysReport);
    }
    }

    /**
     * Registers for TAC/LAC changed event.
     * @param h handler to notify
     * @param what what code of message when delivered
     * @param obj placed in Message.obj
     */
    public void registerForAreaCodeChanged(Handler h, int what, Object obj) {
        mAreaCodeChangedRegistrants.addUnique(h, what, obj);
    }

    /**
     * Unregisters for TAC/LAC changed event.
     * @param h handler to notify
     */
    public void unregisterForAreaCodeChanged(Handler h) {
        mAreaCodeChangedRegistrants.remove(h);
    }
}
}
+133 −4
Original line number Original line Diff line number Diff line
@@ -17,12 +17,24 @@
package com.android.internal.telephony.dataconnection;
package com.android.internal.telephony.dataconnection;


import android.annotation.ElapsedRealtimeLong;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;
import android.telephony.Annotation;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.ApnType;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting;
import android.telephony.data.ThrottleStatus;
import android.telephony.data.ThrottleStatus;


import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.RetryManager;
import com.android.telephony.Rlog;
import com.android.telephony.Rlog;


@@ -35,11 +47,19 @@ import java.util.concurrent.ConcurrentHashMap;
 * Data throttler tracks the throttling status of the data network and notifies registrants when
 * Data throttler tracks the throttling status of the data network and notifies registrants when
 * there are changes.  The throttler is per phone and per transport type.
 * there are changes.  The throttler is per phone and per transport type.
 */
 */
public class DataThrottler {
public class DataThrottler extends Handler {
    private static final String TAG = DataThrottler.class.getSimpleName();
    private static final String TAG = DataThrottler.class.getSimpleName();


    private static final int EVENT_SET_RETRY_TIME = 1;
    private static final int EVENT_CARRIER_CONFIG_CHANGED = 2;
    private static final int EVENT_RESET = 3;
    private static final int EVENT_AIRPLANE_MODE_CHANGED = 4;
    private static final int EVENT_TRACING_AREA_CODE_CHANGED = 5;

    private final Phone mPhone;
    private final int mSlotIndex;
    private final int mSlotIndex;
    private final @AccessNetworkConstants.TransportType int mTransportType;
    private final @AccessNetworkConstants.TransportType int mTransportType;
    private boolean mResetWhenAreaCodeChanged = false;


    /**
    /**
     * Callbacks that report the apn throttle status.
     * Callbacks that report the apn throttle status.
@@ -52,9 +72,93 @@ public class DataThrottler {
     */
     */
    private final Map<Integer, ThrottleStatus> mThrottleStatus = new ConcurrentHashMap<>();
    private final Map<Integer, ThrottleStatus> mThrottleStatus = new ConcurrentHashMap<>();


    public DataThrottler(int slotIndex, int transportType) {
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        mSlotIndex = slotIndex;
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
                if (mPhone.getPhoneId() == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX,
                        SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
                    if (intent.getBooleanExtra(
                            CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                        // Ignore the rebroadcast one to prevent multiple carrier config changed
                        // event during boot up.
                        return;
                    }
                    int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                            SubscriptionManager.INVALID_SUBSCRIPTION_ID);
                    if (SubscriptionManager.isValidSubscriptionId(subId)) {
                        sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
                    }
                }
            }
        }
    };

    public DataThrottler(Phone phone, int transportType) {
        super(null, false);
        mPhone = phone;
        mSlotIndex = phone.getPhoneId();
        mTransportType = transportType;
        mTransportType = transportType;

        IntentFilter filter = new IntentFilter();
        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone);

        mPhone.getServiceStateTracker().registerForAirplaneModeChanged(this,
                EVENT_AIRPLANE_MODE_CHANGED, null);
        mPhone.getServiceStateTracker().registerForAreaCodeChanged(this,
                EVENT_TRACING_AREA_CODE_CHANGED, null);
    }

    @Override
    public void handleMessage(Message msg) {
        AsyncResult ar;
        switch (msg.what) {
            case EVENT_SET_RETRY_TIME:
                int apnTypes = msg.arg1;
                int newRequestType = msg.arg2;
                long retryElapsedTime = (long) msg.obj;
                setRetryTimeInternal(apnTypes, retryElapsedTime, newRequestType);
                break;
            case EVENT_CARRIER_CONFIG_CHANGED:
                onCarrierConfigChanged();
                break;
            case EVENT_RESET:
                resetInternal();
                break;
            case EVENT_AIRPLANE_MODE_CHANGED:
                ar = (AsyncResult) msg.obj;
                if (!(Boolean) ar.result) {
                    resetInternal();
                }
                break;
            case EVENT_TRACING_AREA_CODE_CHANGED:
                if (mResetWhenAreaCodeChanged) {
                    resetInternal();
                }
                break;
        }
    }

    @NonNull
    private PersistableBundle getCarrierConfig() {
        CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
        if (configManager != null) {
            // If an invalid subId is used, this bundle will contain default values.
            PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
            if (config != null) {
                return config;
            }
        }
        // Return static default defined in CarrierConfigManager.
        return CarrierConfigManager.getDefaultConfig();
    }

    private void onCarrierConfigChanged() {
        PersistableBundle config = getCarrierConfig();
        mResetWhenAreaCodeChanged = config.getBoolean(
                CarrierConfigManager.KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
    }
    }


    /**
    /**
@@ -65,8 +169,23 @@ public class DataThrottler {
     * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist.
     * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist.
     * {@link RetryManager#NO_RETRY} indicates retry should never happen.
     * {@link RetryManager#NO_RETRY} indicates retry should never happen.
     */
     */
    public void setRetryTime(@ApnType int apnTypes, long retryElapsedTime,
    public void setRetryTime(@ApnType int apnTypes, @ElapsedRealtimeLong long retryElapsedTime,
            @DcTracker.RequestNetworkType int newRequestType) {
            @DcTracker.RequestNetworkType int newRequestType) {
        sendMessage(obtainMessage(EVENT_SET_RETRY_TIME, apnTypes, newRequestType,
                retryElapsedTime));
    }

    /**
     * Set the retry time and handover failure mode for the give APN types. This is running on the
     * handler thread.
     *
     * @param apnTypes APN types
     * @param retryElapsedTime The elapsed time that data connection for APN types should not be
     * retried. {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates throttling does not exist.
     * {@link RetryManager#NO_RETRY} indicates retry should never happen.
     */
    private void setRetryTimeInternal(@ApnType int apnTypes, @ElapsedRealtimeLong
            long retryElapsedTime, @DcTracker.RequestNetworkType int newRequestType) {
        if (retryElapsedTime < 0) {
        if (retryElapsedTime < 0) {
            retryElapsedTime = RetryManager.NO_SUGGESTED_RETRY_DELAY;
            retryElapsedTime = RetryManager.NO_SUGGESTED_RETRY_DELAY;
        }
        }
@@ -103,6 +222,9 @@ public class DataThrottler {
    /**
    /**
     * Get the earliest retry time for the given APN type. The time is the system's elapse time.
     * Get the earliest retry time for the given APN type. The time is the system's elapse time.
     *
     *
     * Note the DataThrottler is running phone process's main thread, which is most of the telephony
     * components running on. Calling this method from other threads might run into race conditions.
     *
     * @param apnType APN type
     * @param apnType APN type
     * @return The earliest retry time for APN type. The time is the system's elapse time.
     * @return The earliest retry time for APN type. The time is the system's elapse time.
     * {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates there is no throttling for given APN
     * {@link RetryManager#NO_SUGGESTED_RETRY_DELAY} indicates there is no throttling for given APN
@@ -131,6 +253,13 @@ public class DataThrottler {
     * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}.
     * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}.
     */
     */
    public void reset() {
    public void reset() {
        sendEmptyMessage(EVENT_RESET);
    }

    /**
     * Resets retry times for all APNs to {@link RetryManager.NO_SUGGESTED_RETRY_DELAY}.
     */
    private void resetInternal() {
        final List<Integer> apnTypes = new ArrayList<>();
        final List<Integer> apnTypes = new ArrayList<>();
        for (ThrottleStatus throttleStatus : mThrottleStatus.values()) {
        for (ThrottleStatus throttleStatus : mThrottleStatus.values()) {
            apnTypes.add(throttleStatus.getApnType());
            apnTypes.add(throttleStatus.getApnType());
+1 −10
Original line number Original line Diff line number Diff line
@@ -739,7 +739,7 @@ public class DcTracker extends Handler {


        mTransportType = transportType;
        mTransportType = transportType;
        mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix);
        mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix);
        mDataThrottler = new DataThrottler(mPhone.getPhoneId(), transportType);
        mDataThrottler = new DataThrottler(mPhone, transportType);


        mResolver = mPhone.getContext().getContentResolver();
        mResolver = mPhone.getContext().getContentResolver();
        mAlarmManager =
        mAlarmManager =
@@ -822,8 +822,6 @@ public class DcTracker extends Handler {
                DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
                DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
                DctConstants.EVENT_DATA_RAT_CHANGED, null);
                DctConstants.EVENT_DATA_RAT_CHANGED, null);
        mPhone.getServiceStateTracker().registerForAirplaneModeChanged(this,
                DctConstants.EVENT_AIRPLANE_MODE_CHANGED, null);
    }
    }


    public void unregisterServiceStateTrackerEvents() {
    public void unregisterServiceStateTrackerEvents() {
@@ -4098,13 +4096,6 @@ public class DcTracker extends Handler {
                String apn = (String) ar.result;
                String apn = (String) ar.result;
                onApnUnthrottled(apn);
                onApnUnthrottled(apn);
                break;
                break;
            case DctConstants.EVENT_AIRPLANE_MODE_CHANGED:
                ar = (AsyncResult) msg.obj;
                if (!(Boolean) ar.result) {
                    log("Airplane Mode switched off, resetting data throttler");
                    mDataThrottler.reset();
                }
                break;
            default:
            default:
                Rlog.e("DcTracker", "Unhandled event=" + msg);
                Rlog.e("DcTracker", "Unhandled event=" + msg);
                break;
                break;
+29 −10
Original line number Original line Diff line number Diff line
@@ -65,7 +65,7 @@ public class DataThrottlerTest extends TelephonyTest {
    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        super.setUp(getClass().getSimpleName());
        mDataThrottler = new DataThrottler(1, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        mDataThrottler = new DataThrottler(mPhone, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback1);
        mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback1);
    }
    }


@@ -87,9 +87,9 @@ public class DataThrottlerTest extends TelephonyTest {
        processAllMessages();
        processAllMessages();
        expectedStatuses.add(List.of());
        expectedStatuses.add(List.of());



        mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L,
        mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L,
                REQUEST_TYPE_NORMAL);
                REQUEST_TYPE_NORMAL);
        processAllMessages();
        assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));
        assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
@@ -97,14 +97,14 @@ public class DataThrottlerTest extends TelephonyTest {
        processAllMessages();
        processAllMessages();
        expectedStatuses.add(List.of(
        expectedStatuses.add(List.of(
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(ApnSetting.TYPE_HIPRI)
                        .setApnType(ApnSetting.TYPE_HIPRI)
                        .setThrottleExpiryTimeMillis(1234567890L)
                        .setThrottleExpiryTimeMillis(1234567890L)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_NEW_CONNECTION)
                        .build(),
                        .build(),
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                    .setSlotIndex(1)
                    .setSlotIndex(0)
                    .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                    .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                    .setApnType(DEFAULT_APN_TYPE)
                    .setApnType(DEFAULT_APN_TYPE)
                    .setThrottleExpiryTimeMillis(1234567890L)
                    .setThrottleExpiryTimeMillis(1234567890L)
@@ -115,27 +115,28 @@ public class DataThrottlerTest extends TelephonyTest {


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


        processAllMessages();
        processAllMessages();
        expectedStatuses.add(List.of(
        expectedStatuses.add(List.of(
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(ApnSetting.TYPE_HIPRI)
                        .setApnType(ApnSetting.TYPE_HIPRI)
                        .setThrottleExpiryTimeMillis(13579L)
                        .setThrottleExpiryTimeMillis(13579L)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER)
                        .build(),
                        .build(),
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(ApnSetting.TYPE_DUN)
                        .setApnType(ApnSetting.TYPE_DUN)
                        .setThrottleExpiryTimeMillis(13579L)
                        .setThrottleExpiryTimeMillis(13579L)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_HANDOVER)
                        .build(),
                        .build(),
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(DEFAULT_APN_TYPE)
                        .setApnType(DEFAULT_APN_TYPE)
                        .setThrottleExpiryTimeMillis(13579L)
                        .setThrottleExpiryTimeMillis(13579L)
@@ -146,12 +147,13 @@ public class DataThrottlerTest extends TelephonyTest {


        mDataThrottler.setRetryTime(ApnSetting.TYPE_MMS, -10,
        mDataThrottler.setRetryTime(ApnSetting.TYPE_MMS, -10,
                REQUEST_TYPE_NORMAL);
                REQUEST_TYPE_NORMAL);
        processAllMessages();
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
                mDataThrottler.getRetryTime(ApnSetting.TYPE_MMS));
        processAllMessages();
        processAllMessages();
        expectedStatuses.add(List.of(
        expectedStatuses.add(List.of(
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setNoThrottle()
                        .setNoThrottle()
                        .setApnType(ApnSetting.TYPE_MMS)
                        .setApnType(ApnSetting.TYPE_MMS)
@@ -165,14 +167,14 @@ public class DataThrottlerTest extends TelephonyTest {
        processAllMessages();
        processAllMessages();
        expectedStatuses.add(List.of(
        expectedStatuses.add(List.of(
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(ApnSetting.TYPE_EMERGENCY)
                        .setApnType(ApnSetting.TYPE_EMERGENCY)
                        .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY)
                        .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_NONE)
                        .setRetryType(ThrottleStatus.RETRY_TYPE_NONE)
                        .build(),
                        .build(),
                new ThrottleStatus.Builder()
                new ThrottleStatus.Builder()
                        .setSlotIndex(1)
                        .setSlotIndex(0)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                        .setApnType(ApnSetting.TYPE_FOTA)
                        .setApnType(ApnSetting.TYPE_FOTA)
                        .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY)
                        .setThrottleExpiryTimeMillis(RetryManager.NO_RETRY)
@@ -213,4 +215,21 @@ public class DataThrottlerTest extends TelephonyTest {


        this.mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback2);
        this.mDataThrottler.registerForThrottleStatusChanges(mMockChangedCallback2);
    }
    }

    /**
     * Test the behavior of a retry manager with no waiting APNs set.
     */
    @Test
    @SmallTest
    public void testUnthrottle() throws Exception {
        mDataThrottler.setRetryTime(ApnSetting.TYPE_DEFAULT, 1234567890L,
                REQUEST_TYPE_NORMAL);
        processAllMessages();
        assertEquals(1234567890L, mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));

        mDataThrottler.reset();
        processAllMessages();
        assertEquals(RetryManager.NO_SUGGESTED_RETRY_DELAY,
                mDataThrottler.getRetryTime(ApnSetting.TYPE_DEFAULT));
    }
}
}