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

Commit 3e0355f8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Support data profile merging" am: 9d1d82ae am: 0f82e355

Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/2035091

Change-Id: Ibfe8264e31798ffe07d3c8790bf4768b3fe18cb5
parents 47aaaef4 0f82e355
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -253,6 +253,8 @@ public class DataProfileManager extends Handler {
            log("Added default EIMS data profile.");
        }

        dedupeDataProfiles(profiles);

        log("Found " + profiles.size() + " data profiles. profiles = " + profiles);

        boolean profilesChanged = false;
@@ -695,6 +697,115 @@ public class DataProfileManager extends Handler {
        return dataProfile.equals(mPreferredDataProfile);
    }

    /**
     * Dedupe the similar data profiles.
     */
    private void dedupeDataProfiles(@NonNull List<DataProfile> dataProfiles) {
        int i = 0;
        while (i < dataProfiles.size() - 1) {
            DataProfile first = dataProfiles.get(i);
            int j = i + 1;
            while (j < dataProfiles.size()) {
                DataProfile second = dataProfiles.get(j);
                DataProfile merged = mergeDataProfiles(first, second);
                if (merged != null) {
                    log("Created a merged profile " + merged + " from " + first + " and "
                            + second);
                    loge("Merging data profiles will not be supported anymore. Please "
                            + "directly configure the merged profile " + merged + " in the APN "
                            + "config.");
                    dataProfiles.set(i, merged);
                    dataProfiles.remove(j);
                } else {
                    j++;
                }
            }
            i++;
        }
    }

    /**
     * Merge two data profiles if possible.
     *
     * @param dp1 Data profile 1 to be merged.
     * @param dp2 Data profile 2 to be merged.
     *
     * @return The merged data profile. {@code null} if merging is not possible.
     */
    private static @Nullable DataProfile mergeDataProfiles(
            @NonNull DataProfile dp1, @NonNull DataProfile dp2) {
        Objects.requireNonNull(dp1);
        Objects.requireNonNull(dp2);

        // We don't merge data profiles that have different traffic descriptor.
        if (!Objects.equals(dp1.getTrafficDescriptor(), dp2.getTrafficDescriptor())) return null;

        // If one of the APN setting is null, we don't merge.
        if (dp1.getApnSetting() == null || dp2.getApnSetting() == null) return null;

        // If two APN settings are not similar, we don't merge.
        if (!dp1.getApnSetting().similar(dp2.getApnSetting())) return null;

        // Start to merge APN setting 1 and 2.
        ApnSetting apn1 = dp1.getApnSetting();
        ApnSetting apn2 = dp2.getApnSetting();
        ApnSetting.Builder apnBuilder = new ApnSetting.Builder();

        // Special handling id and entry name. We want to keep the default APN as it could be the
        // preferred APN.
        apnBuilder.setId(apn1.getId());
        apnBuilder.setEntryName(apn1.getEntryName());
        if (apn2.canHandleType(ApnSetting.TYPE_DEFAULT)
                && !apn1.canHandleType(ApnSetting.TYPE_DEFAULT)) {
            apnBuilder.setId(apn2.getId());
            apnBuilder.setEntryName(apn2.getEntryName());
        }

        // Merge the following fields from apn1 and apn2.
        apnBuilder.setProxyAddress(TextUtils.isEmpty(apn2.getProxyAddressAsString())
                ? apn1.getProxyAddressAsString() : apn2.getProxyAddressAsString());
        apnBuilder.setProxyPort(apn2.getProxyPort() == -1
                ? apn1.getProxyPort() : apn2.getProxyPort());
        apnBuilder.setMmsc(apn2.getMmsc() == null ? apn1.getMmsc() : apn2.getMmsc());
        apnBuilder.setMmsProxyAddress(TextUtils.isEmpty(apn2.getMmsProxyAddressAsString())
                ? apn1.getMmsProxyAddressAsString() : apn2.getMmsProxyAddressAsString());
        apnBuilder.setMmsProxyPort(apn2.getMmsProxyPort() == -1
                ? apn1.getMmsProxyPort() : apn2.getMmsProxyPort());
        apnBuilder.setUser(TextUtils.isEmpty(apn2.getUser()) ? apn1.getUser() : apn2.getUser());
        apnBuilder.setPassword(TextUtils.isEmpty(apn2.getPassword())
                ? apn1.getPassword() : apn2.getPassword());
        apnBuilder.setAuthType(apn2.getAuthType() == -1
                ? apn1.getAuthType() : apn2.getAuthType());
        apnBuilder.setApnTypeBitmask(apn1.getApnTypeBitmask() | apn2.getApnTypeBitmask());
        apnBuilder.setMtuV4(apn2.getMtuV4() == -1 ? apn1.getMtuV4() : apn2.getMtuV4());
        apnBuilder.setMtuV6(apn2.getMtuV6() == -1 ? apn1.getMtuV6() : apn2.getMtuV6());

        // The following fields in apn1 and apn2 should be the same, otherwise ApnSetting.similar()
        // should fail earlier.
        apnBuilder.setApnName(apn1.getApnName());
        apnBuilder.setProtocol(apn1.getProtocol());
        apnBuilder.setRoamingProtocol(apn1.getRoamingProtocol());
        apnBuilder.setCarrierEnabled(apn1.isEnabled());
        apnBuilder.setNetworkTypeBitmask(apn1.getNetworkTypeBitmask());
        apnBuilder.setLingeringNetworkTypeBitmask(apn1.getLingeringNetworkTypeBitmask());
        apnBuilder.setProfileId(apn1.getProfileId());
        apnBuilder.setPersistent(apn1.isPersistent());
        apnBuilder.setMaxConns(apn1.getMaxConns());
        apnBuilder.setWaitTime(apn1.getWaitTime());
        apnBuilder.setMaxConnsTime(apn1.getMaxConnsTime());
        apnBuilder.setMvnoType(apn1.getMvnoType());
        apnBuilder.setMvnoMatchData(apn1.getMvnoMatchData());
        apnBuilder.setApnSetId(apn1.getApnSetId());
        apnBuilder.setCarrierId(apn1.getCarrierId());
        apnBuilder.setSkip464Xlat(apn1.getSkip464Xlat());
        apnBuilder.setAlwaysOn(apn1.isAlwaysOn());

        return new DataProfile.Builder()
                .setApnSetting(apnBuilder.build())
                .setTrafficDescriptor(dp1.getTrafficDescriptor())
                .build();
    }

    /**
     * Register the callback for receiving information from {@link DataProfileManager}.
     *
+132 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;

import android.annotation.NonNull;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
@@ -57,6 +58,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -139,9 +142,9 @@ public class DataProfileManagerTest extends TelephonyTest {
                        0,                      // max_conns
                        0,                      // wait_time
                        0,                      // max_conns_time
                        0,                      // mtu
                        0,                      // mtu_v4
                        0,                      // mtu_v6
                        -1,                     // mtu
                        1280,                   // mtu_v4
                        1280,                   // mtu_v6
                        "",                     // mvno_type
                        "",                     // mnvo_match_data
                        TelephonyManager.NETWORK_TYPE_BITMASK_LTE
@@ -254,6 +257,42 @@ public class DataProfileManagerTest extends TelephonyTest {
                        -1,                     // carrier_id
                        -1,                     // skip_464xlat
                        0                       // always_on
                },
                // This APN entry is created to test de-duping.
                new Object[]{
                        5,                      // id
                        PLMN,                   // numeric
                        GENERAL_PURPOSE_APN,    // name
                        GENERAL_PURPOSE_APN,    // apn
                        "",                     // proxy
                        "",                     // port
                        "",                     // mmsc
                        "",                     // mmsproxy
                        "",                     // mmsport
                        "",                     // user
                        "",                     // password
                        -1,                     // authtype
                        "fota",                 // types
                        "IPV4V6",               // protocol
                        "IPV4V6",               // roaming_protocol
                        1,                      // carrier_enabled
                        0,                      // profile_id
                        1,                      // modem_cognitive
                        0,                      // max_conns
                        0,                      // wait_time
                        0,                      // max_conns_time
                        -1,                     // mtu
                        -1,                     // mtu_v4
                        -1,                     // mtu_v6
                        "",                     // mvno_type
                        "",                     // mnvo_match_data
                        TelephonyManager.NETWORK_TYPE_BITMASK_LTE
                                | TelephonyManager.NETWORK_TYPE_BITMASK_NR, // network_type_bitmask
                        0,                      // lingering_network_type_bitmask
                        0,                      // apn_set_id
                        -1,                     // carrier_id
                        -1,                     // skip_464xlat
                        0                       // always_on
                }
        );

@@ -352,6 +391,14 @@ public class DataProfileManagerTest extends TelephonyTest {
        return true;
    }

    private void dedupeDataProfiles(@NonNull List<DataProfile> dataProfiles) throws Exception {
        Class[] cArgs = new Class[1];
        cArgs[0] = List.class;
        Method method = DataProfileManager.class.getDeclaredMethod("dedupeDataProfiles", cArgs);
        method.setAccessible(true);
        method.invoke(mDataProfileManagerUT, dataProfiles);
    }

    @Before
    public void setUp() throws Exception {
        logd("DataProfileManagerTest +Setup!");
@@ -615,4 +662,86 @@ public class DataProfileManagerTest extends TelephonyTest {
                TelephonyManager.NETWORK_TYPE_LTE);
        assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(IMS_APN);
    }

    @Test
    public void testDedupeDataProfiles() {
        NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
                .build();
        TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
        // This should get the merged data profile after deduping.
        DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
                TelephonyManager.NETWORK_TYPE_LTE);
        assertThat(dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
    }

    @Test
    public void testDedupeDataProfiles2() throws Exception {

        DataProfile dataProfile1 = new DataProfile.Builder()
                .setApnSetting(new ApnSetting.Builder()
                        .setEntryName("general")
                        .setApnName("apn")
                        .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS
                                | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_HIPRI)
                        .setUser("user")
                        .setPassword("password")
                        .setAuthType(ApnSetting.AUTH_TYPE_CHAP)
                        .setMmsc(Uri.parse("http://mms-s"))
                        .setMmsProxyAddress("mmsc.proxy")
                        .setMmsProxyPort(8080)
                        .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setCarrierEnabled(true)
                        .build())
                .build();

        DataProfile dataProfile2 = new DataProfile.Builder()
                .setApnSetting(new ApnSetting.Builder()
                        .setEntryName("XCAP")
                        .setApnName("apn")
                        .setApnTypeBitmask(ApnSetting.TYPE_XCAP)
                        .setUser("user")
                        .setPassword("password")
                        .setAuthType(ApnSetting.AUTH_TYPE_CHAP)
                        .setProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6)
                        .setCarrierEnabled(true)
                        .build())
                .build();

        logd("apn1=" + dataProfile1.getApnSetting());
        logd("apn2=" + dataProfile2.getApnSetting());
        logd("apn1 can handle default=" + dataProfile1.getApnSetting()
                .canHandleType(ApnSetting.TYPE_DEFAULT));
        logd("apn2 can handle default=" + dataProfile2.getApnSetting()
                .canHandleType(ApnSetting.TYPE_DEFAULT));
        assertThat(dataProfile1.getApnSetting().similar(dataProfile2.getApnSetting())).isTrue();

        List<DataProfile> dataProfiles = new ArrayList<>(Arrays.asList(dataProfile2, dataProfile1));

        dedupeDataProfiles(dataProfiles);
        // After deduping, there should be only one.
        assertThat(dataProfiles).hasSize(1);

        DataProfile dataProfile = dataProfiles.get(0);
        assertThat(dataProfile.getApnSetting()).isNotNull();

        logd("Merged profile=" + dataProfile);
        assertThat(dataProfile.getApnSetting().getEntryName()).isEqualTo("general");
        assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo("apn");
        assertThat(dataProfile.getApnSetting().getApnTypeBitmask()).isEqualTo(
                ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS | ApnSetting.TYPE_SUPL
                        | ApnSetting.TYPE_HIPRI | ApnSetting.TYPE_XCAP);
        assertThat(dataProfile.getApnSetting().getUser()).isEqualTo("user");
        assertThat(dataProfile.getApnSetting().getPassword()).isEqualTo("password");
        assertThat(dataProfile.getApnSetting().getAuthType()).isEqualTo(ApnSetting.AUTH_TYPE_CHAP);
        assertThat(dataProfile.getApnSetting().getMmsc()).isEqualTo(Uri.parse("http://mms-s"));
        assertThat(dataProfile.getApnSetting().getMmsProxyAddressAsString())
                .isEqualTo("mmsc.proxy");
        assertThat(dataProfile.getApnSetting().getMmsProxyPort()).isEqualTo(8080);
        assertThat(dataProfile.getApnSetting().getProtocol()).isEqualTo(ApnSetting.PROTOCOL_IPV4V6);
        assertThat(dataProfile.getApnSetting().getRoamingProtocol())
                .isEqualTo(ApnSetting.PROTOCOL_IPV4V6);
    }
}