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

Commit 21def163 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic 'iwlan_unit'

* changes:
  Added IWLAN metered APN support
  Fixed flaky tests and added more DcTracker tests.
parents a318ec54 1773b5c3
Loading
Loading
Loading
Loading
+51 −19
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.text.TextUtils;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.uicc.IccRecords;
@@ -404,15 +405,41 @@ public class ApnSetting {
        return false;
    }

    public static boolean isMeteredApnType(String type, Context context, int subId,
                                           boolean isRoaming) {
    /**
     * Check if this APN type is metered.
     *
     * @param type The APN type
     * @param phone The phone object
     * @return True if the APN type is metered, otherwise false.
     */
    public static boolean isMeteredApnType(String type, Phone phone) {
        if (phone == null) {
            return true;
        }

        String carrierConfig = (isRoaming) ?
                CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS :
                CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
        boolean isRoaming = phone.getServiceState().getDataRoaming();
        boolean isIwlan = phone.getServiceState().getRilDataRadioTechnology()
                == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
        int subId = phone.getSubId();

        String carrierConfig;
        // First check if the device is in IWLAN mode. If yes, use the IWLAN metered APN list. Then
        // check if the device is roaming. If yes, use the roaming metered APN list. Otherwise, use
        // the normal metered APN list.
        if (isIwlan) {
            carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS;
        } else if (isRoaming) {
            carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS;
        } else {
            carrierConfig = CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS;
        }

        if (DBG) {
            Rlog.d(LOG_TAG, "isMeteredApnType: isRoaming=" + isRoaming + ", isIwlan=" + isIwlan);
        }

        CarrierConfigManager configManager = (CarrierConfigManager)
                context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
        if (configManager == null) {
            Rlog.e(LOG_TAG, "Carrier config service is not available");
            return true;
@@ -432,44 +459,49 @@ public class ApnSetting {

        HashSet<String> meteredApnSet = new HashSet<>(Arrays.asList(meteredApnTypes));
        if (DBG) {
            Rlog.d(LOG_TAG, "For subId = " + subId + ", metered APN types are " +
                    Arrays.toString(meteredApnSet.toArray()) +
                    " isRoaming: " + isRoaming);
            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. isRoaming: " + isRoaming);
            if (DBG) Rlog.d(LOG_TAG, "All APN types are metered.");
            return true;
        }

        if (meteredApnSet.contains(type)) {
            if (DBG) Rlog.d(LOG_TAG, type + " is metered. isRoaming: " + isRoaming);
            if (DBG) Rlog.d(LOG_TAG, type + " is metered.");
            return true;
        } else if (type.equals(PhoneConstants.APN_TYPE_ALL)) {
            // Assuming no configuration error, if at least one APN type is
            // metered, then this APN setting is metered.
            if (meteredApnSet.size() > 0) {
                if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered. isRoaming: " +
                        isRoaming);
                if (DBG) Rlog.d(LOG_TAG, "APN_TYPE_ALL APN is metered.");
                return true;
            }
        }

        if (DBG) Rlog.d(LOG_TAG, type + " is not metered. isRoaming: " + isRoaming);
        if (DBG) Rlog.d(LOG_TAG, type + " is not metered.");
        return false;
    }

    public boolean isMetered(Context context, int subId, boolean isRoaming ) {
    /**
     * Check if this APN setting is metered.
     *
     * @param phone The phone object
     * @return True if this APN setting is metered, otherwise false.
     */
    public boolean isMetered(Phone phone) {
        if (phone == null) {
            return true;
        }

        for (String type : types) {
            // If one of the APN type is metered, then this APN setting is metered.
            if (isMeteredApnType(type, context, subId, isRoaming)) {
                if (DBG) Rlog.d(LOG_TAG, "Metered. APN = " + toString() +
                        "isRoaming: " + isRoaming);
            if (isMeteredApnType(type, phone)) {
                return true;
            }
        }
        if (DBG) Rlog.d(LOG_TAG, "Not metered. APN = " + toString() + "isRoaming: " + isRoaming);
        return false;
    }

+3 −7
Original line number Diff line number Diff line
@@ -852,8 +852,7 @@ public class DataConnection extends StateMachine {

        // Do we need a restricted network to satisfy the request?
        // Is this network metered?  If not, then don't add restricted
        if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(),
                mPhone.getServiceState().getDataRoaming())) {
        if (!mApnSetting.isMetered(mPhone)) {
            return;
        }

@@ -869,9 +868,7 @@ public class DataConnection extends StateMachine {
            for (String type : mApnSetting.types) {
                if (!mRestrictedNetworkOverride
                        && (mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
                        && ApnSetting.isMeteredApnType(type,
                        mPhone.getContext(), mPhone.getSubId(),
                        mPhone.getServiceState().getDataRoaming())) {
                        && ApnSetting.isMeteredApnType(type, mPhone)) {
                    log("Dropped the metered " + type + " for the unmetered data call.");
                    continue;
                }
@@ -934,8 +931,7 @@ public class DataConnection extends StateMachine {
            // 2. The non-restricted data and is intended for unmetered use only.
            if (((mConnectionParams != null && mConnectionParams.mUnmeteredUseOnly)
                    && !mRestrictedNetworkOverride)
                    || !mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(),
                    mPhone.getServiceState().getDataRoaming())) {
                    || !mApnSetting.isMetered(mPhone)) {
                result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
                mNetworkInfo.setMetered(false);
            } else {
+3 −6
Original line number Diff line number Diff line
@@ -904,8 +904,7 @@ public class DcTracker extends Handler {
                            // data connection.
                            apnContext.setReason(Phone.REASON_DATA_ENABLED);
                            cleanUpConnection(true, apnContext);
                        } else if (apnContext.getApnSetting().isMetered(mPhone.getContext(),
                                mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())
                        } else if (apnContext.getApnSetting().isMetered(mPhone)
                                && (netCaps != null && netCaps.hasCapability(
                                        NetworkCapabilities.NET_CAPABILITY_NOT_METERED))) {
                            if (DBG) {
@@ -1319,8 +1318,7 @@ public class DcTracker extends Handler {
                SubscriptionManager.getDefaultDataSubscriptionId());

        boolean isMeteredApnType = apnContext == null
                || ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone.getContext(),
                        mPhone.getSubId(), mPhone.getServiceState().getDataRoaming());
                || ApnSetting.isMeteredApnType(apnContext.getApnType(), mPhone);

        PhoneConstants.State phoneState = PhoneConstants.State.IDLE;
        // Note this is explicitly not using mPhone.getState.  See b/19090488.
@@ -1646,8 +1644,7 @@ public class DcTracker extends Handler {
                // 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(), mPhone.getServiceState().getDataRoaming())) {
                if (apnSetting != null && apnSetting.isMetered(mPhone)) {
                    if (DBG) log("clean up metered ApnContext Type: " + apnContext.getApnType());
                    apnContext.setReason(reason);
                    cleanUpConnection(tearDown, apnContext);
+262 −134

File changed.

Preview size limit exceeded, changes collapsed.

+197 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony.dataconnection;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
import static com.android.internal.telephony.dataconnection.ApnSettingTest.createApnSetting;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -61,6 +62,7 @@ import android.telephony.SubscriptionManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.LocalLog;

import com.android.internal.telephony.DctConstants;
@@ -113,6 +115,12 @@ public class DcTrackerTest extends TelephonyTest {
    NetworkRequest mNetworkRequest;
    @Mock
    SubscriptionInfo mSubscriptionInfo;
    @Mock
    ApnContext mApnContext;
    @Mock
    ApnSetting mApnSetting;
    @Mock
    DcAsyncChannel mDcac;

    private DcTracker mDct;
    private DcTrackerTestHandler mDcTrackerTestHandler;
@@ -337,6 +345,8 @@ public class DcTrackerTest extends TelephonyTest {
        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        mBundle = mContextFixture.getCarrierConfigBundle();

        mSimulatedCommands.setDataCallResponse(true, createDataCallResponse());

        mDcTrackerTestHandler = new DcTrackerTestHandler(getClass().getSimpleName());
        mDcTrackerTestHandler.start();
        waitUntilReady();
@@ -670,7 +680,6 @@ public class DcTrackerTest extends TelephonyTest {
        waitForMs(200);
    }

    @FlakyTest
    @Test
    @MediumTest
    public void testDataCallOnUserDisableRoaming() throws Exception {
@@ -680,13 +689,16 @@ public class DcTrackerTest extends TelephonyTest {

        boolean roamingEnabled = mDct.getDataRoamingEnabled();
        boolean dataEnabled = mDct.getDataEnabled();
        doReturn(true).when(mServiceState).getDataRoaming();

        //set Default and MMS to be metered in the CarrierConfigManager
        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT, PhoneConstants.APN_TYPE_MMS});
        mDct.setEnabled(5, true);
        mDct.setEnabled(0, true);
        doReturn(true).when(mServiceState).getDataRoaming();

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

        logd("Sending DISABLE_ROAMING_CMD");
        mDct.setDataRoamingEnabled(false);
@@ -699,9 +711,6 @@ public class DcTrackerTest extends TelephonyTest {
        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)).setInitialAttachApn(any(DataProfile.class),
                eq(true), nullable(Message.class));
@@ -826,4 +835,187 @@ public class DcTrackerTest extends TelephonyTest {
        mDct.setDataEnabled(dataEnabled);
        waitForMs(200);
    }

    private void initApns(String targetApn, String[] canHandleTypes) {
        doReturn(targetApn).when(mApnContext).getApnType();
        doReturn(true).when(mApnContext).isConnectable();
        ApnSetting apnSetting = createApnSetting(canHandleTypes);
        doReturn(apnSetting).when(mApnContext).getNextApnSetting();
        doReturn(apnSetting).when(mApnContext).getApnSetting();
        doReturn(mDcac).when(mApnContext).getDcAc();
        doReturn(true).when(mApnContext).isEnabled();
        doReturn(true).when(mApnContext).getDependencyMet();
        doReturn(true).when(mApnContext).isReady();
        doReturn(true).when(mApnContext).hasNoRestrictedRequests(eq(true));
    }

    // Test the emergency APN setup.
    @Test
    @SmallTest
    public void testTrySetupDataEmergencyApn() throws Exception {
        initApns(PhoneConstants.APN_TYPE_EMERGENCY, new String[]{PhoneConstants.APN_TYPE_ALL});
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

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

    // Test the unmetered APN setup when data is disabled.
    @Test
    @SmallTest
    public void testTrySetupDataUnmeteredDataDisabled() throws Exception {
        initApns(PhoneConstants.APN_TYPE_FOTA, new String[]{PhoneConstants.APN_TYPE_ALL});
        mDct.setDataEnabled(false);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

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

    // Test the metered APN setup when data is disabled.
    @Test
    @SmallTest
    public void testTrySetupMeteredDataDisabled() throws Exception {
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        mDct.setDataEnabled(false);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }

    // Test the restricted data request when data is disabled.
    @Test
    @SmallTest
    public void testTrySetupRestrictedDataDisabled() throws Exception {
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        doReturn(false).when(mApnContext).hasNoRestrictedRequests(eq(true));

        mDct.setDataEnabled(false);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(1)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }

    // Test the default data when data is not connectable.
    @Test
    @SmallTest
    public void testTrySetupNotConnectable() throws Exception {
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        doReturn(false).when(mApnContext).isConnectable();
        mDct.setDataEnabled(true);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }

    // Test the default data on IWLAN.
    @Test
    @SmallTest
    public void testTrySetupDefaultOnIWLAN() throws Exception {
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN).when(mServiceState)
                .getRilDataRadioTechnology();
        mDct.setDataEnabled(true);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }

    // Test the default data when the phone is in ECBM.
    @Test
    @SmallTest
    public void testTrySetupDefaultInECBM() throws Exception {
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        doReturn(true).when(mPhone).isInEcm();
        mDct.setDataEnabled(true);

        mBundle.putStringArray(CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS,
                new String[]{PhoneConstants.APN_TYPE_DEFAULT});

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

        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, mApnContext));
        waitForMs(200);

        verify(mSimulatedCommandsVerifier, times(0)).setupDataCall(
                anyInt(), any(DataProfile.class), eq(false), eq(false), any(Message.class));
    }
}