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

Commit 6d96b8b3 authored by Jordan Liu's avatar Jordan Liu
Browse files

DcTracker prioritizes preferred apn set

Bug: 70172263
Test: DcTrackerTest#testFetchDunApnWithPreferredApnSet and manually
verify that trySetupData sets waiting apns in correct order depending on
user selected default APN
Change-Id: Icf84e4a2fa118644761d348e6b4a3a363aba3aa5
Merged-In: Icf84e4a2fa118644761d348e6b4a3a363aba3aa5
parent 29c29857
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -2111,7 +2111,6 @@ public class DataConnection extends StateMachine {
                String logStr = "Changed from " + mNetworkCapabilities + " to "
                        + networkCapabilities + ", Data RAT="
                        + mPhone.getServiceState().getRilDataRadioTechnology()
                        + ", DUN APN=\"" + mDct.fetchDunApn() + "\""
                        + ", mApnSetting=" + mApnSetting;
                mNetCapsLocalLog.log(logStr);
                log(logStr);
+95 −43
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.telephony.dataconnection;

import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
@@ -1689,27 +1690,27 @@ public class DcTracker extends Handler {
    }

    /**
     * Fetch dun apn
     * @return ApnSetting to be used for dun
     * Fetch the DUN apns
     * @return a list of DUN ApnSetting objects
     */
    @VisibleForTesting
    public ApnSetting fetchDunApn() {
    public @NonNull ArrayList<ApnSetting> fetchDunApns() {
        if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)) {
            log("fetchDunApn: net.tethering.noprovisioning=true ret: null");
            return null;
            log("fetchDunApns: net.tethering.noprovisioning=true ret: empty list");
            return new ArrayList<ApnSetting>(0);
        }
        int bearer = mPhone.getServiceState().getRilDataRadioTechnology();
        IccRecords r = mIccRecords.get();
        String operator = (r != null) ? r.getOperatorNumeric() : "";
        ArrayList<ApnSetting> dunCandidates = new ArrayList<ApnSetting>();
        ApnSetting retDunSetting = null;
        ArrayList<ApnSetting> retDunSettings = new ArrayList<ApnSetting>();

        // Places to look for tether APN in order: TETHER_DUN_APN setting (to be deprecated soon),
        // APN database, and config_tether_apndata resource (to be deprecated soon).
        String apnData = Settings.Global.getString(mResolver, Settings.Global.TETHER_DUN_APN);
        if (!TextUtils.isEmpty(apnData)) {
            dunCandidates.addAll(ApnSetting.arrayFromString(apnData));
            if (VDBG) log("fetchDunApn: dunCandidates from Setting: " + dunCandidates);
            if (VDBG) log("fetchDunApns: dunCandidates from Setting: " + dunCandidates);
        }

        // todo: remove this and config_tether_apndata after APNs are moved from overlay to apns xml
@@ -1724,7 +1725,7 @@ public class DcTracker extends Handler {
                    // apn may be null if apnString isn't valid or has error parsing
                    if (apn != null) dunCandidates.add(apn);
                }
                if (VDBG) log("fetchDunApn: dunCandidates from resource: " + dunCandidates);
                if (VDBG) log("fetchDunApns: dunCandidates from resource: " + dunCandidates);
            }
        }

@@ -1735,7 +1736,7 @@ public class DcTracker extends Handler {
                        dunCandidates.add(apn);
                    }
                }
                if (VDBG) log("fetchDunApn: dunCandidates from database: " + dunCandidates);
                if (VDBG) log("fetchDunApns: dunCandidates from database: " + dunCandidates);
            }
        }

@@ -1748,24 +1749,36 @@ public class DcTracker extends Handler {
                if (dunSetting.hasMvnoParams()) {
                    if (r != null && ApnSetting.mvnoMatches(r, dunSetting.mvnoType,
                            dunSetting.mvnoMatchData)) {
                        retDunSetting = dunSetting;
                        break;
                        retDunSettings.add(dunSetting);
                    }
                } else if (mMvnoMatched == false) {
                    retDunSetting = dunSetting;
                    break;
                    retDunSettings.add(dunSetting);
                }
            }
        }

        if (VDBG) log("fetchDunApn: dunSetting=" + retDunSetting);
        return retDunSetting;
        if (VDBG) log("fetchDunApns: dunSettings=" + retDunSettings);
        return retDunSettings;
    }

    private int getPreferredApnSetId() {
        Cursor c = mPhone.getContext().getContentResolver()
                .query(Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI,
                    "preferapnset/subId/" + mPhone.getSubId()),
                        new String[] {Telephony.Carriers.APN_SET_ID}, null, null, null);
        if (c.getCount() < 1) {
            loge("getPreferredApnSetId: no APNs found");
            return Telephony.Carriers.NO_SET_SET;
        } else {
            c.moveToFirst();
            return c.getInt(0 /* index of Telephony.Carriers.APN_SET_ID */);
        }
    }

    public boolean hasMatchedTetherApnSetting() {
        ApnSetting matched = fetchDunApn();
        log("hasMatchedTetherApnSetting: APN=" + matched);
        return matched != null;
        ArrayList<ApnSetting> matches = fetchDunApns();
        log("hasMatchedTetherApnSetting: APNs=" + matches);
        return matches.size() > 0;
    }

    /**
@@ -1776,7 +1789,8 @@ public class DcTracker extends Handler {
        final int rilRat = mPhone.getServiceState().getRilDataRadioTechnology();
        if (ServiceState.isCdma(rilRat)) return true;

        return (fetchDunApn() != null);
        ArrayList<ApnSetting> apns = fetchDunApns();
        return apns.size() > 0;
    }

    /**
@@ -2449,10 +2463,10 @@ public class DcTracker extends Handler {

    private DcAsyncChannel checkForCompatibleConnectedApnContext(ApnContext apnContext) {
        String apnType = apnContext.getApnType();
        ApnSetting dunSetting = null;
        ArrayList<ApnSetting> dunSettings = null;

        if (PhoneConstants.APN_TYPE_DUN.equals(apnType)) {
            dunSetting = fetchDunApn();
            dunSettings = sortApnListByPreferred(fetchDunApns());
        }
        if (DBG) {
            log("checkForCompatibleConnectedApnContext: apnContext=" + apnContext );
@@ -2465,7 +2479,8 @@ public class DcTracker extends Handler {
            if (curDcac != null) {
                ApnSetting apnSetting = curApnCtx.getApnSetting();
                log("apnSetting: " + apnSetting);
                if (dunSetting != null) {
                if (dunSettings != null && dunSettings.size() > 0) {
                    for (ApnSetting dunSetting : dunSettings) {
                        if (dunSetting.equals(apnSetting)) {
                            switch (curApnCtx.getState()) {
                                case CONNECTED:
@@ -2479,11 +2494,13 @@ public class DcTracker extends Handler {
                                case CONNECTING:
                                    potentialDcac = curDcac;
                                    potentialApnCtx = curApnCtx;
                                    break;
                                default:
                                    // Not connected, potential unchanged
                                    break;
                            }
                        }
                    }
                } else if (apnSetting != null && apnSetting.canHandleType(apnType)) {
                    switch (curApnCtx.getState()) {
                        case CONNECTED:
@@ -2497,6 +2514,7 @@ public class DcTracker extends Handler {
                        case CONNECTING:
                            potentialDcac = curDcac;
                            potentialApnCtx = curApnCtx;
                            break;
                        default:
                            // Not connected, potential unchanged
                            break;
@@ -3434,11 +3452,13 @@ public class DcTracker extends Handler {
        ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();

        if (requestedApnType.equals(PhoneConstants.APN_TYPE_DUN)) {
            ApnSetting dun = fetchDunApn();
            if (dun != null) {
            ArrayList<ApnSetting> dunApns = fetchDunApns();
            if (dunApns.size() > 0) {
                for (ApnSetting dun : dunApns) {
                    apnList.add(dun);
                    if (DBG) log("buildWaitingApns: X added APN_TYPE_DUN apnList=" + apnList);
                return apnList;
                }
                return sortApnListByPreferred(apnList);
            }
        }

@@ -3479,6 +3499,7 @@ public class DcTracker extends Handler {
                if (ServiceState.bitmaskHasTech(mPreferredApn.networkTypeBitmask,
                        ServiceState.rilRadioTechnologyToNetworkType(radioTech))) {
                    apnList.add(mPreferredApn);
                    apnList = sortApnListByPreferred(apnList);
                    if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
                    return apnList;
                } else {
@@ -3515,10 +3536,41 @@ public class DcTracker extends Handler {
        } else {
            loge("mAllApnSettings is null!");
        }

        apnList = sortApnListByPreferred(apnList);
        if (DBG) log("buildWaitingApns: " + apnList.size() + " APNs in the list: " + apnList);
        return apnList;
    }

    /**
     * Sort a list of ApnSetting objects, with the preferred APNs at the front of the list
     *
     * e.g. if the preferred APN set = 2 and we have
     *   1. APN with apn_set_id = 0 = Carriers.NO_SET_SET (no set is set)
     *   2. APN with apn_set_id = 1 (not preferred set)
     *   3. APN with apn_set_id = 2 (preferred set)
     * Then the return order should be (3, 1, 2) or (3, 2, 1)
     *
     * e.g. if the preferred APN set = Carriers.NO_SET_SET (no preferred set) then the
     * return order can be anything
     */
    @VisibleForTesting
    public ArrayList<ApnSetting> sortApnListByPreferred(ArrayList<ApnSetting> list) {
        if (list == null || list.size() <= 1) return list;
        int preferredApnSetId = getPreferredApnSetId();
        if (preferredApnSetId != Telephony.Carriers.NO_SET_SET) {
            list.sort(new Comparator<ApnSetting>() {
                @Override
                public int compare(ApnSetting apn1, ApnSetting apn2) {
                    if (apn1.apnSetId == preferredApnSetId) return -1;
                    if (apn2.apnSetId == preferredApnSetId) return 1;
                    return 0;
                }
            });
        }
        return list;
    }

    private String apnListToString (ArrayList<ApnSetting> apns) {
        StringBuilder result = new StringBuilder();
        for (int i = 0, size = apns.size(); i < size; i++) {
+26 −14
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
@@ -182,6 +183,7 @@ public class DcTrackerTest extends TelephonyTest {
    }

    private class ApnSettingContentProvider extends MockContentProvider {
        private int mPreferredApnSet = 0;

        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
@@ -383,8 +385,17 @@ public class DcTrackerTest extends TelephonyTest {
                            0,                      // network_type_bitmask
                            0                       // apn_set_id
                    });

                    return mc;
                }
            } else if (uri.isPathPrefixMatch(
                    Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "preferapnset"))) {
                MatrixCursor mc = new MatrixCursor(
                        new String[]{Telephony.Carriers.APN_SET_ID});
                // apn_set_id is the only field used with this URL
                mc.addRow(new Object[]{ mPreferredApnSet });
                mc.addRow(new Object[]{ 0 });
                return mc;
            }

            return null;
@@ -392,7 +403,8 @@ public class DcTrackerTest extends TelephonyTest {

        @Override
        public int update(Uri url, ContentValues values, String where, String[] whereArgs) {
            return 0;
            mPreferredApnSet = values.getAsInteger(Telephony.Carriers.APN_SET_ID);
            return 1;
        }
    }

@@ -1276,7 +1288,7 @@ public class DcTrackerTest extends TelephonyTest {
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
    }

    // Test for fetchDunApn()
    // Test for fetchDunApns()
    @Test
    @SmallTest
    public void testFetchDunApn() {
@@ -1291,20 +1303,19 @@ public class DcTrackerTest extends TelephonyTest {
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.TETHER_DUN_APN, dunApnString);
        // should return APN from Setting
        ApnSetting dunApn = mDct.fetchDunApn();
        ApnSetting dunApn = mDct.fetchDunApns().get(0);
        assertTrue(dunApnExpected.equals(dunApn));

        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.TETHER_DUN_APN, null);
        // should return APN from db
        dunApn = mDct.fetchDunApn();
        dunApn = mDct.fetchDunApns().get(0);
        assertEquals(FAKE_APN5, dunApn.apn);
    }

    // Test for fetchDunApn() with apn set id
    // Test for fetchDunApns() with apn set id
    @Test
    @SmallTest
    @Ignore
    public void testFetchDunApnWithPreferredApnSet() {
        logd("Sending EVENT_RECORDS_LOADED");
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_RECORDS_LOADED, null));
@@ -1312,10 +1323,10 @@ public class DcTrackerTest extends TelephonyTest {

        // apnSetId=1
        String dunApnString1 = "[ApnSettingV5]HOT mobile PC,pc.hotm,,,,,,,,,440,10,,DUN,,,true,"
                + "0,,,,,,,,,1";
        // apnSetId=2
        String dunApnString2 = "[ApnSettingV5]HOT mobile PC,pc.hotm,,,,,,,,,440,10,,DUN,,,true,"
                + "0,,,,,,,,,2";
                + "0,,,,,,,,,,1";
        // apnSetId=0
        String dunApnString2 = "[ApnSettingV5]HOT mobile PC,pc.coldm,,,,,,,,,440,10,,DUN,,,true,"
                + "0,,,,,,,,,,0";

        ApnSetting dunApnExpected = ApnSetting.fromString(dunApnString1);

@@ -1326,11 +1337,12 @@ public class DcTrackerTest extends TelephonyTest {
        // set that we prefer apn set 1
        ContentValues values = new ContentValues();
        values.put(Telephony.Carriers.APN_SET_ID, 1);
        cr.update(PREFERAPN_URI, values, null, null); // currently a noop
        cr.update(PREFERAPN_URI, values, null, null);

        // TODO(70172263) should return APN from Setting with apnSetId=1
        ApnSetting dunApn = mDct.fetchDunApn();
        assertTrue(dunApnExpected.equals(dunApn));
        // return APN from Setting with apnSetId=1
        ArrayList<ApnSetting> dunApns = mDct.sortApnListByPreferred(mDct.fetchDunApns());
        assertEquals(2, dunApns.size());
        assertTrue(dunApnExpected.equals(dunApns.get(0)));
    }

    // Test oos