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

Commit 6ffe0b1b authored by Jack Yu's avatar Jack Yu Committed by Gerrit Code Review
Browse files

Merge changes Id354c362,I96d5f7f7

* changes:
  Fixed that data throttling was not properly enforced
  Fixed IWLAN handover issues
parents f24f9a73 46cff6bb
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.telephony.dataconnection;

import com.android.internal.annotations.VisibleForTesting;

import java.util.HashSet;

/**
@@ -70,7 +72,14 @@ public class DataConnectionReasons {
        return mDataDisallowedReasonSet.size() == 0;
    }

    boolean contains(DataDisallowedReasonType reason) {
    /**
     * Check if it contains a certain disallowed reason.
     *
     * @param reason The disallowed reason to check.
     * @return {@code true} if the provided reason matches one of the disallowed reasons.
     */
    @VisibleForTesting
    public boolean contains(DataDisallowedReasonType reason) {
        return mDataDisallowedReasonSet.contains(reason);
    }

@@ -137,7 +146,10 @@ public class DataConnectionReasons {
        DATA_SERVICE_NOT_READY(true),
        // Qualified networks service does not allow certain types of APN brought up on either
        // cellular or IWLAN.
        DISABLED_BY_QNS(true);
        DISABLED_BY_QNS(true),
        // Data is throttled. The network explicitly requested device not to establish data
        // connection for a certain period.
        DATA_THROTTLED(true);

        private boolean mIsHardReason;

+23 −2
Original line number Diff line number Diff line
@@ -1457,6 +1457,12 @@ public class DcTracker extends Handler {
                    apnContext.getApnTypeBitmask()) && requestType != REQUEST_TYPE_HANDOVER) {
                reasons.add(DataDisallowedReasonType.ON_OTHER_TRANSPORT);
            }

            // Check if the device is under data throttling.
            long retryTime = mDataThrottler.getRetryTime(apnContext.getApnTypeBitmask());
            if (retryTime > SystemClock.elapsedRealtime()) {
                reasons.add(DataDisallowedReasonType.DATA_THROTTLED);
            }
        }

        boolean isDataEnabled = apnContext == null ? mDataEnabledSettings.isDataEnabled()
@@ -2717,11 +2723,26 @@ public class DcTracker extends Handler {
            DctConstants.State state = apnContext.getState();
            switch(state) {
                case CONNECTING:
                    if (onHandoverCompleteMsg != null) {
                        if (DBG) {
                            log("onEnableApn: already in CONNECTING state. Handover request "
                                    + "will be responded after connected.");
                        }
                        addHandoverCompleteMsg(onHandoverCompleteMsg, apnType);
                    } else {
                        if (DBG) log("onEnableApn: in CONNECTING state. Exit now.");
                    }
                    return;
                case CONNECTED:
                    if (DBG) log("onEnableApn: APN in " + state + " state. Exit now.");
                    if (onHandoverCompleteMsg != null) {
                        sendHandoverCompleteMsg(onHandoverCompleteMsg, false, mTransportType,
                        sendHandoverCompleteMsg(onHandoverCompleteMsg, true, mTransportType,
                                false);
                        if (DBG) {
                            log("onEnableApn: already in CONNECTED state. Consider as handover "
                                    + "succeeded");
                        }
                    } else {
                        if (DBG) log("onEnableApn: APN in CONNECTED state. Exit now.");
                    }
                    return;
                case IDLE:
+18 −2
Original line number Diff line number Diff line
@@ -373,7 +373,8 @@ public class TelephonyNetworkFactory extends NetworkFactory {
                                targetTransport, onCompleteMsg);
                        log("Requested handover " + ApnSetting.getApnTypeString(apnType)
                                + " to "
                                + AccessNetworkConstants.transportTypeToString(targetTransport));
                                + AccessNetworkConstants.transportTypeToString(targetTransport)
                                + ". " + networkRequest);
                        handoverPending = true;
                    } else {
                        // Request is there, but no actual data connection. In this case, just move
@@ -429,7 +430,22 @@ public class TelephonyNetworkFactory extends NetworkFactory {
                    // connection can be re-established on the other transport.
                    : DcTracker.RELEASE_TYPE_DETACH;
            releaseNetworkInternal(networkRequest, releaseType, originTransport);

            // Before updating the network request with the target transport, make sure the request
            // is still there because it's possible that connectivity service has already released
            // the network while handover is ongoing. If connectivity service already released
            // the network request, we need to tear down the just-handovered data connection on the
            // target transport.
            if (mNetworkRequests.containsKey(networkRequest)) {
                // Update it with the target transport.
                mNetworkRequests.put(networkRequest, targetTransport);
            } else {
                log("Network request was released before handover is completed. Now"
                        + " we need to release this network request. "
                        + networkRequest);
                releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL,
                        targetTransport);
            }
        } else {
            // If handover fails and requires to fallback, the context of target transport needs to
            // be released
+5 −3
Original line number Diff line number Diff line
@@ -320,10 +320,12 @@ public class TransportManager extends Handler {
     * @param transport The transport. Must be WWAN or WLAN.
     */
    private synchronized void setCurrentTransport(@ApnType int apnType, int transport) {
        mCurrentTransports.put(apnType, transport);
        Integer previousTransport = mCurrentTransports.put(apnType, transport);
        if (previousTransport == null || previousTransport != transport) {
            logl("setCurrentTransport: apnType=" + ApnSetting.getApnTypeString(apnType)
                    + ", transport=" + AccessNetworkConstants.transportTypeToString(transport));
        }
    }

    private boolean isHandoverPending() {
        return mPendingHandoverApns.size() > 0;
+63 −21
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.AccessNetworkConstants;
@@ -97,6 +98,7 @@ import com.android.internal.telephony.ISub;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType;

import org.junit.After;
import org.junit.Before;
@@ -800,18 +802,6 @@ public class DcTrackerTest extends TelephonyTest {
        assertEquals(FAKE_GATEWAY, linkProperties.getRoutes().get(0).getGateway().getHostAddress());
    }

    private boolean isDataAllowed(DataConnectionReasons dataConnectionReasons) {
        try {
            Method method = DcTracker.class.getDeclaredMethod("isDataAllowed",
                    DataConnectionReasons.class);
            method.setAccessible(true);
            return (boolean) method.invoke(mDct, dataConnectionReasons);
        } catch (Exception e) {
            fail(e.toString());
            return false;
        }
    }

    private boolean isHandoverPending(int apnType) {
        try {
            Method method = DcTracker.class.getDeclaredMethod("isHandoverPending",
@@ -881,7 +871,7 @@ public class DcTrackerTest extends TelephonyTest {
    @MediumTest
    public void testDataSetup() throws Exception {
        DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
        boolean allowed = isDataAllowed(dataConnectionReasons);
        boolean allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertFalse(dataConnectionReasons.toString(), allowed);

        logd("Sending EVENT_ENABLE_APN");
@@ -892,7 +882,7 @@ public class DcTrackerTest extends TelephonyTest {
        sendInitializationEvents();

        dataConnectionReasons = new DataConnectionReasons();
        allowed = isDataAllowed(dataConnectionReasons);
        allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertTrue(dataConnectionReasons.toString(), allowed);

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
@@ -923,7 +913,7 @@ public class DcTrackerTest extends TelephonyTest {
        mSimulatedCommands.setDataCallResult(true, result);

        DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
        boolean allowed = isDataAllowed(dataConnectionReasons);
        boolean allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertFalse(dataConnectionReasons.toString(), allowed);

        logd("Sending EVENT_ENABLE_APN");
@@ -934,7 +924,7 @@ public class DcTrackerTest extends TelephonyTest {
        sendInitializationEvents();

        dataConnectionReasons = new DataConnectionReasons();
        allowed = isDataAllowed(dataConnectionReasons);
        allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertTrue(dataConnectionReasons.toString(), allowed);

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
@@ -2429,6 +2419,12 @@ public class DcTrackerTest extends TelephonyTest {
        return (boolean) field.get(mDct);
    }

    private Map<Integer, List<Message>> getHandoverCompletionMessages() throws Exception {
        Field field = DcTracker.class.getDeclaredField(("mHandoverCompletionMsgs"));
        field.setAccessible(true);
        return (Map<Integer, List<Message>>) field.get(mDct);
    }

    private void setUpTempNotMetered() {
        doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR)
                .when(mPhone).getRadioAccessFamily();
@@ -2728,7 +2724,7 @@ public class DcTrackerTest extends TelephonyTest {
    @Test
    public void testRatChanged() throws Exception {
        DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
        boolean allowed = isDataAllowed(dataConnectionReasons);
        boolean allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertFalse(dataConnectionReasons.toString(), allowed);

        logd("Sending EVENT_ENABLE_APN");
@@ -2738,7 +2734,7 @@ public class DcTrackerTest extends TelephonyTest {
        sendInitializationEvents();

        dataConnectionReasons = new DataConnectionReasons();
        allowed = isDataAllowed(dataConnectionReasons);
        allowed = mDct.isDataAllowed(dataConnectionReasons);
        assertTrue(dataConnectionReasons.toString(), allowed);

        ArgumentCaptor<DataProfile> dpCaptor = ArgumentCaptor.forClass(DataProfile.class);
@@ -2866,20 +2862,66 @@ public class DcTrackerTest extends TelephonyTest {

    @Test
    public void testDataUnthrottled() throws Exception {
        DataThrottler mockedDataThrottler = Mockito.mock(DataThrottler.class);
        replaceInstance(DcTracker.class, "mDataThrottler", mDct, mockedDataThrottler);
        initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
        replaceInstance(DcTracker.class, "mDataThrottler", mDct, mDataThrottler);
        mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_NORMAL, null);
        sendInitializationEvents();
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_APN_UNTHROTTLED,
                new AsyncResult(null, FAKE_APN3, null)));
        waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());

        verify(mockedDataThrottler).setRetryTime(
        verify(mDataThrottler).setRetryTime(
                eq(ApnSetting.TYPE_IMS),
                eq(RetryManager.NO_SUGGESTED_RETRY_DELAY),
                eq(DcTracker.REQUEST_TYPE_NORMAL));
    }

    @Test
    public void testHandlingSecondHandoverRequest() throws Exception {
        initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
        setUpDataConnection();
        SparseArray<ApnContext> apnContextsByType = Mockito.mock(SparseArray.class);
        ConcurrentHashMap<String, ApnContext> apnContexts = Mockito.mock(ConcurrentHashMap.class);
        doReturn(mApnContext).when(apnContextsByType).get(eq(ApnSetting.TYPE_IMS));
        doReturn(mApnContext).when(apnContexts).get(eq(ApnSetting.TYPE_IMS_STRING));
        doReturn(false).when(mApnContext).isConnectable();
        doReturn(DctConstants.State.CONNECTING).when(mApnContext).getState();
        replaceInstance(DcTracker.class, "mApnContextsByType", mDct, apnContextsByType);
        replaceInstance(DcTracker.class, "mApnContexts", mDct, apnContexts);

        sendInitializationEvents();

        logd("Sending EVENT_ENABLE_APN");
        // APN id 0 is APN_TYPE_DEFAULT
        Message msg = mDct.obtainMessage(12345);
        mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_HANDOVER, msg);
        waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
        Map<Integer, List<Message>> msgs = getHandoverCompletionMessages();
        // Make sure the messages was queued properly instead of fired right away.
        assertTrue(msgs.get(ApnSetting.TYPE_IMS).contains(msg));
    }

    @Test
    public void testDataThrottledNotAllowData() throws Exception {
        initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
        replaceInstance(DcTracker.class, "mDataThrottler", mDct, mDataThrottler);
        doReturn(SystemClock.elapsedRealtime() + 100000).when(mDataThrottler)
                .getRetryTime(ApnSetting.TYPE_IMS);
        mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_NORMAL, null);
        sendInitializationEvents();

        DataConnectionReasons dataConnectionReasons = new DataConnectionReasons();
        boolean allowed = mDct.isDataAllowed(mApnContext, DcTracker.REQUEST_TYPE_NORMAL,
                dataConnectionReasons);
        assertFalse(dataConnectionReasons.toString(), allowed);
        assertTrue(dataConnectionReasons.contains(DataDisallowedReasonType.DATA_THROTTLED));

        // Makre sure no data setup request
        verify(mSimulatedCommandsVerifier, never()).setupDataCall(
                anyInt(), any(DataProfile.class), anyBoolean(), anyBoolean(), anyInt(), any(),
                anyInt(), any(), any(), anyBoolean(), any(Message.class));
    }

    @Test
    public void testNotifyDataDisconnected() {
        // Verify notify data disconnected on DCT constructor, initialized in setUp()
Loading