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

Commit 783061ca authored by fionaxu's avatar fionaxu Committed by John Huang
Browse files

Infer Zero Rating based on NetworkCapabilities

when user toggle Disabled Cellular Data, we teared down all
DataConnections which are Metered(every APN type in the APN settings
are non-metered otherwise metered).

bug: 27788524
Change-Id: I0228e6ca166516f4f43e1c15d505fc29c31356df
parent 9e51994d
Loading
Loading
Loading
Loading
+24 −19
Original line number Diff line number Diff line
@@ -404,8 +404,7 @@ public class ApnSetting {
        return false;
    }

    public boolean isMetered(Context context, int subId) {

    public static boolean isMeteredApnType(String type, Context context, int subId) {
        synchronized (sMeteredApnTypes) {
            HashSet<String> meteredApnSet = sMeteredApnTypes.get(subId);

@@ -435,21 +434,17 @@ public class ApnSetting {

                meteredApnSet = new HashSet<String>(Arrays.asList(meteredApnTypes));
                sMeteredApnTypes.put(subId, meteredApnSet);
            }

                if (DBG) {
                    Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are " +
                            Arrays.toString(meteredApnSet.toArray()));
                }

            }
            // If all types of APN are metered, then this APN setting must be metered.
            if (meteredApnSet.contains(PhoneConstants.APN_TYPE_ALL)) {
                if (DBG) Rlog.d(LOG_TAG, "All APN types are metered.");
                return true;
            }

            for (String type : types) {
                // If one of the APN type is metered, then this APN setting is metered.
            if (meteredApnSet.contains(type)) {
                if (DBG) Rlog.d(LOG_TAG, type + " is metered.");
                return true;
@@ -462,8 +457,18 @@ public class ApnSetting {
                }
            }
        }
        if (DBG) Rlog.d(LOG_TAG, type + " is not metered.");
        return false;
    }

    public boolean isMetered(Context context, int subId) {
        for (String type : types) {
            // If one of the APN type is metered, then this APN setting is metered.
            if (isMeteredApnType(type, context, subId)) {
                if (DBG) Rlog.d(LOG_TAG, "Metered. APN = " + toString());
                return true;
            }
        }
        if (DBG) Rlog.d(LOG_TAG, "Not metered. APN = " + toString());
        return false;
    }
+9 −3
Original line number Diff line number Diff line
@@ -1461,8 +1461,10 @@ public class DcTracker extends Handler {
        boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY);
        final ServiceStateTracker sst = mPhone.getServiceStateTracker();

        // set to false if apn type is non-metered.
        boolean checkUserDataEnabled =
                    !(apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS));
                !(ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(),
                        mPhone.getSubId()));

        StringBuilder failureReason = new StringBuilder();
        if (apnContext.isConnectable() && (isEmergencyApn ||
@@ -1588,8 +1590,12 @@ public class DcTracker extends Handler {
        for (ApnContext apnContext : mApnContexts.values()) {
            if (apnContext.isDisconnected() == false) didDisconnect = true;
            if (specificdisable) {
                if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS)) {
                    if (DBG) log("ApnConextType: " + apnContext.getApnType());
                // Use ApnSetting to decide metered or non-metered.
                // Tear down all metered data connections.
                ApnSetting apnSetting = apnContext.getApnSetting();
                if (apnSetting != null && apnSetting.isMetered(mPhone.getContext(),
                        mPhone.getSubId())) {
                    if (DBG) log("clean up metered ApnContext Type: " + apnContext.getApnType());
                    apnContext.setReason(reason);
                    cleanUpConnection(tearDown, apnContext);
                }
+101 −2
Original line number Diff line number Diff line
@@ -27,7 +27,9 @@ import android.net.Uri;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
@@ -59,6 +61,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -97,6 +100,8 @@ public class DcTrackerTest extends TelephonyTest {

    private AlarmManager mAlarmManager;

    private PersistableBundle mBundle;

    private final ApnSettingContentProvider mApnSettingContentProvider =
            new ApnSettingContentProvider();

@@ -228,7 +233,7 @@ public class DcTrackerTest extends TelephonyTest {
                            "",                     // user
                            "",                     // password
                            3,                      // authtype
                            "default,supl",         // types
                            "ims",                  // types
                            "IP",                   // protocol
                            "IP",                   // roaming_protocol
                            1,                      // carrier_enabled
@@ -292,6 +297,7 @@ public class DcTrackerTest extends TelephonyTest {
                new String[]{"36,2"});

        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        mBundle = mContextFixture.getCarrierConfigBundle();

        new DcTrackerTestHandler(getClass().getSimpleName()).start();
        waitUntilReady();
@@ -503,4 +509,97 @@ public class DcTrackerTest extends TelephonyTest {
        // Verify connected with APN2 setting.
        verifyDataConnected(FAKE_APN2);
    }

    @Test
    @MediumTest
    public void testUserDisableData() throws Exception {
        //step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
        //set Default and MMS to be metered in the CarrierConfigManager
        boolean dataEnabled = mDct.getDataEnabled();
        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
        mDct.setEnabled(5, true);
        mDct.setEnabled(0, true);

        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);

        logd("Sending DATA_ENABLED_CMD");
        mDct.setDataEnabled(true);

        waitForMs(200);
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));

        logd("Sending DATA_DISABLED_CMD");
        mDct.setDataEnabled(false);
        waitForMs(200);

        // expected tear down all metered DataConnections
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
                any(Message.class));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));

        // reset the setting at the end of this test
        mDct.setDataEnabled(dataEnabled);
        waitForMs(200);
    }

    @Test
    @MediumTest
    public void testUserDisableRoaming() throws Exception {
        //step 1: setup two DataCalls one for Metered: default, another one for Non-metered: IMS
        //set Default and MMS to be metered in the CarrierConfigManager
        boolean roamingEnabled = mDct.getDataOnRoamingEnabled();
        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
        mDct.setEnabled(5, true);
        mDct.setEnabled(0, true);

        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);

        logd("Sending DATA_ENABLED_CMD");
        mDct.setDataEnabled(true);

        waitForMs(200);
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(0), eq(FAKE_APN1),
                eq(""), eq(""), eq(0), eq("IP"), any(Message.class));
        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                eq(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS), eq(2), eq(FAKE_APN3),
                eq(""), eq(""), eq(3), eq("IP"), any(Message.class));

        logd("Sending DISABLE_ROAMING_CMD");
        mDct.setDataOnRoamingEnabled(false);
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_ROAMING_ON));
        waitForMs(200);

        // expected tear down all metered DataConnections
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(anyInt(), anyInt(),
                any(Message.class));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));

        // reset roaming settings at end of this test
        mDct.setDataOnRoamingEnabled(roamingEnabled);
        waitForMs(200);
    }
}