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

Commit ced725ec authored by fionaxu's avatar fionaxu
Browse files

cleanup and reset waiting apnlist on RAT change

check apn waiting list update during data rat or apn data change.
If the new waiting list is different with the currentWaitingList,
then cleanup the associated data connection and reset apnWaitingList
with the lastest one which matches with both current data rat and apn
settings. Reuse cleanupConnectionsOnUpdatedApns to detect waiting list change
and cleanup the connections. remove the duplicate logic from
setupDataOnConnectableApns

Bug:31252975
Test:  runtest --path
frameworks/opt/telephony/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
--test-method testUpdateWaitingApnListOnDataRatChange
Change-Id: I8408df09a7b25ed2e17cd38b7bebbb8fd20eca72
parent 327d466a
Loading
Loading
Loading
Loading
+27 −56
Original line number Diff line number Diff line
@@ -1475,8 +1475,6 @@ public class DcTracker extends Handler {
        }

        for (ApnContext apnContext : mPrioritySortedApnContexts) {
            ArrayList<ApnSetting> waitingApns = null;

            if (VDBG) log("setupDataOnConnectableApns: apnContext " + apnContext);

            if (apnContext.getState() == DctConstants.State.FAILED
@@ -1487,27 +1485,12 @@ public class DcTracker extends Handler {
                        mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                    // RetryFailures.ONLY_ON_CHANGE - check if voice concurrency has changed
                    apnContext.releaseDataConnection(reason);
                } else {
                    // RetryFailures.ONLY_ON_CHANGE - check if the apns have changed
                    int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
                    ArrayList<ApnSetting> originalApns = apnContext.getWaitingApns();
                    if (originalApns != null && originalApns.isEmpty() == false) {
                        waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);
                        if (originalApns.size() != waitingApns.size() ||
                                originalApns.containsAll(waitingApns) == false) {
                            apnContext.releaseDataConnection(reason);
                        } else {
                            continue;
                        }
                    } else {
                        continue;
                    }
                }
            }
            if (apnContext.isConnectable()) {
                log("isConnectable() call trySetupData");
                apnContext.setReason(reason);
                trySetupData(apnContext, waitingApns);
                trySetupData(apnContext);
            }
        }
    }
@@ -1519,10 +1502,6 @@ public class DcTracker extends Handler {
    }

    private boolean trySetupData(ApnContext apnContext) {
        return trySetupData(apnContext, null);
    }

    private boolean trySetupData(ApnContext apnContext, ArrayList<ApnSetting> waitingApns) {

        if (mPhone.getSimulatedRadioControl() != null) {
            // Assume data is connected on the simulator
@@ -1551,9 +1530,8 @@ public class DcTracker extends Handler {
            apnContext.setConcurrentVoiceAndDataAllowed(mPhone.getServiceStateTracker()
                    .isConcurrentVoiceAndDataAllowed());
            if (apnContext.getState() == DctConstants.State.IDLE) {
                if (waitingApns == null) {
                    waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);
                }
                ArrayList<ApnSetting> waitingApns =
                        buildWaitingApns(apnContext.getApnType(), radioTech);
                if (waitingApns.isEmpty()) {
                    notifyNoData(DcFailCause.MISSING_UNKNOWN_APN, apnContext);
                    notifyOffApnsOfAvailability(apnContext.getReason());
@@ -1821,6 +1799,7 @@ public class DcTracker extends Handler {
        if (dunCandidates.isEmpty()) {
            String[] apnArrayData = mPhone.getContext().getResources()
                .getStringArray(R.array.config_tether_apndata);
            if (!ArrayUtils.isEmpty(apnArrayData)) {
                for (String apnString : apnArrayData) {
                    ApnSetting apn = ApnSetting.fromString(apnString);
                    // apn may be null if apnString isn't valid or has error parsing
@@ -1828,6 +1807,7 @@ public class DcTracker extends Handler {
                }
                if (VDBG) log("fetchDunApn: dunCandidates from resource: " + dunCandidates);
            }
        }

        for (ApnSetting dunSetting : dunCandidates) {
            if (!ServiceState.bitmaskHasTech(dunSetting.bearerBitmask, bearer)) continue;
@@ -2188,7 +2168,7 @@ public class DcTracker extends Handler {
        if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
        createAllApnList();
        setInitialAttachApn();
        cleanUpConnectionsOnUpdatedApns(!isDisconnected);
        cleanUpConnectionsOnUpdatedApns(!isDisconnected, Phone.REASON_APN_CHANGED);

        // FIXME: See bug 17426028 maybe no conditional is needed.
        if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
@@ -3777,6 +3757,7 @@ public class DcTracker extends Handler {
                break;

            case DctConstants.EVENT_DATA_RAT_CHANGED:
                cleanUpConnectionsOnUpdatedApns(false, Phone.REASON_NW_TYPE_CHANGED);
                //May new Network allow setupData, so try it here
                setupDataOnConnectableApns(Phone.REASON_NW_TYPE_CHANGED,
                        RetryFailures.ONLY_ON_CHANGE);
@@ -4378,41 +4359,31 @@ public class DcTracker extends Handler {
        }
    }

    private void cleanUpConnectionsOnUpdatedApns(boolean tearDown) {
    private void cleanUpConnectionsOnUpdatedApns(boolean tearDown, String reason) {
        if (DBG) log("cleanUpConnectionsOnUpdatedApns: tearDown=" + tearDown);
        if (mAllApnSettings.isEmpty()) {
        if (mAllApnSettings != null && mAllApnSettings.isEmpty()) {
            cleanUpAllConnections(tearDown, Phone.REASON_APN_CHANGED);
        } else {
            for (ApnContext apnContext : mApnContexts.values()) {
                if (VDBG) log("cleanUpConnectionsOnUpdatedApns for "+ apnContext);

                boolean cleanUpApn = true;
                ArrayList<ApnSetting> currentWaitingApns = apnContext.getWaitingApns();

                if ((currentWaitingApns != null) && (!apnContext.isDisconnected())) {
                int radioTech = mPhone.getServiceState().getRilDataRadioTechnology();
                ArrayList<ApnSetting> waitingApns = buildWaitingApns(
                        apnContext.getApnType(), radioTech);
                if (VDBG) log("new waitingApns:" + waitingApns);
                    if (waitingApns.size() == currentWaitingApns.size()) {
                        cleanUpApn = false;
                        for (int i = 0; i < waitingApns.size(); i++) {
                            if (!currentWaitingApns.get(i).equals(waitingApns.get(i))) {
                                if (VDBG) log("new waiting apn is different at " + i);
                                cleanUpApn = true;
                if ((currentWaitingApns != null)
                        && ((waitingApns.size() != currentWaitingApns.size())
                        || (!currentWaitingApns.containsAll(waitingApns)))) {
                    if (VDBG) log("new waiting apn is different for " + apnContext);
                    apnContext.setWaitingApns(waitingApns);
                                break;
                            }
                        }
                    }
                }

                if (cleanUpApn) {
                    apnContext.setReason(Phone.REASON_APN_CHANGED);
                    if (!apnContext.isDisconnected()) {
                        if (VDBG) log("cleanUpConnectionsOnUpdatedApns for " + apnContext);
                        apnContext.setReason(reason);
                        cleanUpConnection(true, apnContext);
                    }
                }
            }
        }

        if (!isConnected()) {
            stopNetStatPoll();
+114 −25
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import static org.mockito.Mockito.verify;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -51,7 +50,6 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Settings;
import android.provider.Telephony;
import android.support.test.filters.FlakyTest;
import android.telephony.CarrierConfigManager;
@@ -69,7 +67,6 @@ import com.android.internal.telephony.ISub;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.TestApplication;

import org.junit.After;
import org.junit.Before;
@@ -97,10 +94,13 @@ public class DcTrackerTest extends TelephonyTest {

    private final static List<String> sApnTypes = Arrays.asList(
            "default", "mms", "cbs", "fota", "supl", "ia", "emergency", "dun", "hipri", "ims");

    private static final int LTE_BEARER_BITMASK = 1 << (ServiceState.RIL_RADIO_TECHNOLOGY_LTE - 1);
    private static final int EHRPD_BEARER_BITMASK =
            1 << (ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD - 1);
    public static final String FAKE_APN1 = "FAKE APN 1";
    public static final String FAKE_APN2 = "FAKE APN 2";
    public static final String FAKE_APN3 = "FAKE APN 3";
    public static final String FAKE_APN4 = "FAKE APN 4";
    public static final String FAKE_IFNAME = "FAKE IFNAME";
    public static final String FAKE_PCSCF_ADDRESS = "22.33.44.55";
    public static final String FAKE_GATEWAY = "11.22.33.44";
@@ -208,7 +208,7 @@ public class DcTrackerTest extends TelephonyTest {
                            "IP",                   // protocol
                            "IP",                   // roaming_protocol
                            1,                      // carrier_enabled
                            0,                      // bearer
                            ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer
                            0,                      // bearer_bitmask
                            0,                      // profile_id
                            0,                      // modem_cognitive
@@ -237,7 +237,7 @@ public class DcTrackerTest extends TelephonyTest {
                            "IP",                   // protocol
                            "IP",                   // roaming_protocol
                            1,                      // carrier_enabled
                            0,                      // bearer
                            ServiceState.RIL_RADIO_TECHNOLOGY_LTE, // bearer,
                            0,                      // bearer_bitmask
                            0,                      // profile_id
                            0,                      // modem_cognitive
@@ -278,6 +278,35 @@ public class DcTrackerTest extends TelephonyTest {
                            ""                      // mnvo_match_data
                    });

                    mc.addRow(new Object[]{
                            2166,                   // id
                            plmn,                   // numeric
                            "sp-mode ehrpd",        // name
                            FAKE_APN4,              // apn
                            "",                     // proxy
                            "",                     // port
                            "",                     // mmsc
                            "",                     // mmsproxy
                            "",                     // mmsport
                            "",                     // user
                            "",                     // password
                            -1,                     // authtype
                            "default,supl",         // types
                            "IP",                   // protocol
                            "IP",                   // roaming_protocol
                            1,                      // carrier_enabled
                            ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD, // bearer
                            0,                      // bearer_bitmask
                            0,                      // profile_id
                            0,                      // modem_cognitive
                            0,                      // max_conns
                            0,                      // wait_time
                            0,                      // max_conns_time
                            0,                      // mtu
                            "",                     // mvno_type
                            ""                      // mnvo_match_data
                    });

                    return mc;
                }
            }
@@ -293,6 +322,8 @@ public class DcTrackerTest extends TelephonyTest {

        doReturn("fake.action_detached").when(mPhone).getActionDetached();
        doReturn("fake.action_attached").when(mPhone).getActionAttached();
        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
                .getRilDataRadioTechnology();
        doReturn("44010").when(mSimRecords).getOperatorNumeric();

        mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
@@ -367,21 +398,21 @@ public class DcTrackerTest extends TelephonyTest {
    }

    private void verifyDataProfile(DataProfile dp, String apn, int profileId,
                                   int supportedApnTypesBitmap) {
                                   int supportedApnTypesBitmap, int type, int bearerBitmask) {
        assertEquals(profileId, dp.profileId);
        assertEquals(apn, dp.apn);
        assertEquals("IP", dp.protocol);
        assertEquals(0, dp.authType);
        assertEquals("", dp.user);
        assertEquals("", dp.password);
        assertEquals(0, dp.type);
        assertEquals(type, dp.type);
        assertEquals(0, dp.maxConnsTime);
        assertEquals(0, dp.maxConns);
        assertEquals(0, dp.waitTime);
        assertTrue(dp.enabled);
        assertEquals(supportedApnTypesBitmap, dp.supportedApnTypesBitmap);
        assertEquals("IP", dp.roamingProtocol);
        assertEquals(0, dp.bearerBitmap);
        assertEquals(bearerBitmask, dp.bearerBitmap);
        assertEquals(0, dp.mtu);
        assertEquals("", dp.mvnoType);
        assertEquals("", dp.mvnoMatchData);
@@ -476,9 +507,9 @@ public class DcTrackerTest extends TelephonyTest {
        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        // Verify if RIL command was sent properly.
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);

        verifyDataConnected(FAKE_APN1);
    }
@@ -542,9 +573,9 @@ public class DcTrackerTest extends TelephonyTest {
        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        // Verify if RIL command was sent properly.
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);

        // Make sure we never notify connected because the data call setup is supposed to fail.
        verify(mPhone, never()).notifyDataConnection(eq(Phone.REASON_CONNECTED),
@@ -568,9 +599,9 @@ public class DcTrackerTest extends TelephonyTest {
        dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        // Verify if RIL command was sent properly.
        verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN2, 0, 5, 1, LTE_BEARER_BITMASK);

        // Verify connected with APN2 setting.
        verifyDataConnected(FAKE_APN2);
@@ -603,9 +634,9 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(200);
        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);

        logd("Sending DATA_DISABLED_CMD");
        mDct.setDataEnabled(false);
@@ -654,9 +685,9 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(300);
        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);

        //user is in roaming
        doReturn(true).when(mServiceState).getDataRoaming();
@@ -712,9 +743,9 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(200);
        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);

        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
@@ -814,9 +845,9 @@ public class DcTrackerTest extends TelephonyTest {

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        verify(mSimulatedCommandsVerifier, times(2)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), dpCaptor.capture(),
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5);
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());

        Message msg = mDct.obtainMessage(DctConstants.EVENT_SET_CARRIER_DATA_ENABLED);
@@ -858,7 +889,7 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), any(DataProfile.class),
                eq(mServiceState.getRilDataRadioTechnology()), any(DataProfile.class),
                eq(false), eq(false), any(Message.class));
    }

@@ -884,7 +915,7 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), any(DataProfile.class),
                eq(mServiceState.getRilDataRadioTechnology()), any(DataProfile.class),
                eq(false), eq(false), any(Message.class));
    }

@@ -1018,4 +1049,62 @@ public class DcTrackerTest extends TelephonyTest {
        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }

    // Test update waiting apn list when on data rat change
    @Test
    @SmallTest
    public void testUpdateWaitingApnListOnDataRatChange() throws Exception {
        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD).when(mServiceState)
                .getRilDataRadioTechnology();
        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});
        mDct.setEnabled(0, true);
        mDct.setDataEnabled(true);
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});

        logd("Sending EVENT_RECORDS_LOADED");
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
        waitForMs(200);

        logd("Sending EVENT_DATA_CONNECTION_ATTACHED");
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null));
        waitForMs(200);

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
        // Verify if RIL command was sent properly.
        verify(mSimulatedCommandsVerifier).setupDataCall(
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 5, 2, EHRPD_BEARER_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());

        //data rat change from ehrpd to lte
        logd("Sending EVENT_DATA_RAT_CHANGED");
        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
                .getRilDataRadioTechnology();
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RAT_CHANGED, null));
        waitForMs(200);

        // Verify the disconnected data call due to rat change and retry manger schedule another
        // data call setup
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
                any(Message.class));
        verify(mAlarmManager, times(1)).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
                anyLong(), any(PendingIntent.class));

        // Simulate the timer expires.
        Intent intent = new Intent("com.android.internal.telephony.data-reconnect.default");
        intent.putExtra("reconnect_alarm_extra_type", PhoneConstants.APN_TYPE_DEFAULT);
        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, 0);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendBroadcast(intent);
        waitForMs(200);

        // Verify if RIL command was sent properly.
        verify(mSimulatedCommandsVerifier).setupDataCall(
                eq(mServiceState.getRilDataRadioTechnology()), dpCaptor.capture(),
                eq(false), eq(false), any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, LTE_BEARER_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
    }
}