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

Commit 3ed07a6e authored by Jack Yu's avatar Jack Yu Committed by Daniel Bright
Browse files

Use actual data connection state

ApnContext's states are not always in sync with actual
data connection states, especially when the connection
is in lingering.

Bug: 143011233
Test: Manual
Change-Id: I7e2a0333361d80412c480dca1e1736424a0e3279
parent 3f8bfc7a
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -4142,7 +4142,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    public boolean areAllDataDisconnected() {
        if (mTransportManager != null) {
            for (int transport : mTransportManager.getAvailableTransports()) {
                if (getDcTracker(transport) != null && !getDcTracker(transport).isDisconnected()) {
                if (getDcTracker(transport) != null
                        && !getDcTracker(transport).areAllDataDisconnected()) {
                    return false;
                }
            }
@@ -4154,7 +4155,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mAllDataDisconnectedRegistrants.addUnique(h, what, null);
        if (mTransportManager != null) {
            for (int transport : mTransportManager.getAvailableTransports()) {
                if (getDcTracker(transport) != null && !getDcTracker(transport).isDisconnected()) {
                if (getDcTracker(transport) != null
                        && !getDcTracker(transport).areAllDataDisconnected()) {
                    getDcTracker(transport).registerForAllDataDisconnected(
                            this, EVENT_ALL_DATA_DISCONNECTED);
                }
+30 −79
Original line number Diff line number Diff line
@@ -1202,52 +1202,6 @@ public class DcTracker extends Handler {
        return false;
    }

    // Return state of overall
    public DctConstants.State getOverallState() {
        boolean isConnecting = false;
        boolean isFailed = true; // All enabled Apns should be FAILED.
        boolean isAnyEnabled = false;

        for (ApnContext apnContext : mApnContexts.values()) {
            if (apnContext.isEnabled()) {
                isAnyEnabled = true;
                switch (apnContext.getState()) {
                    case CONNECTED:
                    case DISCONNECTING:
                        if (VDBG) log("overall state is CONNECTED");
                        return DctConstants.State.CONNECTED;
                    case CONNECTING:
                        isConnecting = true;
                        isFailed = false;
                        break;
                    case IDLE:
                    case RETRYING:
                        isFailed = false;
                        break;
                    default:
                        isAnyEnabled = true;
                        break;
                }
            }
        }

        if (!isAnyEnabled) { // Nothing enabled. return IDLE.
            if (VDBG) log( "overall state is IDLE");
            return DctConstants.State.IDLE;
        }

        if (isConnecting) {
            if (VDBG) log( "overall state is CONNECTING");
            return DctConstants.State.CONNECTING;
        } else if (!isFailed) {
            if (VDBG) log( "overall state is IDLE");
            return DctConstants.State.IDLE;
        } else {
            if (VDBG) log( "overall state is FAILED");
            return DctConstants.State.FAILED;
        }
    }

    //****** Called from ServiceStateTracker
    /**
     * Invoked when ServiceStateTracker observes a transition from GPRS
@@ -1268,7 +1222,7 @@ public class DcTracker extends Handler {
    private void onDataConnectionAttached() {
        if (DBG) log("onDataConnectionAttached");
        mAttached.set(true);
        if (getOverallState() == DctConstants.State.CONNECTED) {
        if (isAnyDataConnected()) {
            if (DBG) log("onDataConnectionAttached: start polling notify attached");
            startNetStatPoll();
            startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
@@ -2127,10 +2081,6 @@ public class DcTracker extends Handler {
     * Handles changes to the APN database.
     */
    private void onApnChanged() {
        DctConstants.State overallState = getOverallState();
        boolean isDisconnected = (overallState == DctConstants.State.IDLE ||
                overallState == DctConstants.State.FAILED);

        if (mPhone instanceof GsmCdmaPhone) {
            // The "current" may no longer be valid.  MMS depends on this to send properly. TBD
            ((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider();
@@ -2142,7 +2092,7 @@ public class DcTracker extends Handler {
        createAllApnList();
        setDataProfilesAsNeeded();
        setInitialAttachApn();
        cleanUpConnectionsOnUpdatedApns(!isDisconnected, Phone.REASON_APN_CHANGED);
        cleanUpConnectionsOnUpdatedApns(isAnyDataConnected(), Phone.REASON_APN_CHANGED);

        // FIXME: See bug 17426028 maybe no conditional is needed.
        if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
@@ -2742,7 +2692,7 @@ public class DcTracker extends Handler {
            log("onRadioAvailable: We're on the simulator; assuming data is connected");
        }

        if (getOverallState() != DctConstants.State.IDLE) {
        if (!areAllDataDisconnected()) {
            cleanUpConnectionInternal(true, RELEASE_TYPE_DETACH, null);
        }
    }
@@ -3046,7 +2996,7 @@ public class DcTracker extends Handler {
        }
        // if all data connection are gone, check whether Airplane mode request was
        // pending.
        if (isDisconnected()) {
        if (areAllDataDisconnected()) {
            if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
                if (DBG) log("onDisconnectDone: radio will be turned off, no retries");
                // Radio will be turned off. No need to retry data setup
@@ -3110,7 +3060,8 @@ public class DcTracker extends Handler {
    private void onVoiceCallStarted() {
        if (DBG) log("onVoiceCallStarted");
        mInVoiceCall = true;
        if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
        if (isAnyDataConnected()
                && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
            if (DBG) log("onVoiceCallStarted stop polling");
            stopNetStatPoll();
            stopDataStallAlarm();
@@ -3121,7 +3072,7 @@ public class DcTracker extends Handler {
    protected void onVoiceCallEnded() {
        if (DBG) log("onVoiceCallEnded");
        mInVoiceCall = false;
        if (isConnected()) {
        if (isAnyDataConnected()) {
            if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                startNetStatPoll();
                startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
@@ -3134,26 +3085,28 @@ public class DcTracker extends Handler {
        // reset reconnect timer
        setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);
    }

    protected boolean isConnected() {
        for (ApnContext apnContext : mApnContexts.values()) {
            if (apnContext.getState() == DctConstants.State.CONNECTED) {
                // At least one context is connected, return true
    /**
     * @return {@code true} if there is any data in connected state.
     */
    @VisibleForTesting
    public boolean isAnyDataConnected() {
        for (DataConnection dc : mDataConnections.values()) {
            if (dc.isActive()) {
                return true;
            }
        }
        // There are not any contexts connected, return false
        return false;
    }

    public boolean isDisconnected() {
        for (ApnContext apnContext : mApnContexts.values()) {
            if (!apnContext.isDisconnected()) {
                // At least one context was not disconnected return false
    /**
     * @return {@code true} if all data connections are in disconnected state.
     */
    public boolean areAllDataDisconnected() {
        for (DataConnection dc : mDataConnections.values()) {
            if (!dc.isInactive()) {
                return false;
            }
        }
        // All contexts were disconnected so return true
        return true;
    }

@@ -3557,7 +3510,7 @@ public class DcTracker extends Handler {
                 */
                if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
                mIsPsRestricted  = false;
                if (isConnected()) {
                if (isAnyDataConnected()) {
                    startNetStatPoll();
                    startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
                } else {
@@ -3740,7 +3693,7 @@ public class DcTracker extends Handler {

                    mDataStallNoRxEnabled = !enabled;
                    if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled()
                            && (getOverallState() == DctConstants.State.CONNECTED)
                            && isAnyDataConnected()
                            && (!mInVoiceCall ||
                                    mPhone.getServiceStateTracker()
                                        .isConcurrentVoiceAndDataAllowed())) {
@@ -3991,7 +3944,7 @@ public class DcTracker extends Handler {
    public void registerForAllDataDisconnected(Handler h, int what) {
        mAllDataDisconnectedRegistrants.addUnique(h, what, null);

        if (isDisconnected()) {
        if (areAllDataDisconnected()) {
            log("notify All Data Disconnected");
            notifyAllDataDisconnected();
        }
@@ -4248,7 +4201,7 @@ public class DcTracker extends Handler {
        pw.println(" mReregisterOnReconnectFailure=" + mReregisterOnReconnectFailure);
        pw.println(" canSetPreferApn=" + mCanSetPreferApn);
        pw.println(" mApnObserver=" + mApnObserver);
        pw.println(" getOverallState=" + getOverallState());
        pw.println(" isAnyDataConnected=" + isAnyDataConnected());
        pw.println(" mAttached=" + mAttached.get());
        mDataEnabledSettings.dump(fd, pw, args);
        pw.flush();
@@ -4408,7 +4361,7 @@ public class DcTracker extends Handler {
            }
        }

        if (!isConnected()) {
        if (!isAnyDataConnected()) {
            stopNetStatPoll();
            stopDataStallAlarm();
        }
@@ -4430,9 +4383,8 @@ public class DcTracker extends Handler {
        mNetStatPollPeriod = POLL_NETSTAT_MILLIS;
    }

    protected void startNetStatPoll() {
        if (getOverallState() == DctConstants.State.CONNECTED
                && mNetStatPollEnabled == false) {
    private void startNetStatPoll() {
        if (isAnyDataConnected() && !mNetStatPollEnabled) {
            if (DBG) {
                log("startNetStatPoll");
            }
@@ -4710,7 +4662,7 @@ public class DcTracker extends Handler {
        }

        public void doRecovery() {
            if (getOverallState() == DctConstants.State.CONNECTED) {
            if (isAnyDataConnected()) {
                // Go through a series of recovery steps, each action transitions to the next action
                @RecoveryAction final int recoveryAction = getRecoveryAction();
                final int signalStrength = mPhone.getSignalStrength().getLevel();
@@ -4874,8 +4826,7 @@ public class DcTracker extends Handler {
    protected void startDataStallAlarm(boolean suspectedStall) {
        int delayInMs;

        if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled()
                && getOverallState() == DctConstants.State.CONNECTED) {
        if (mDsRecoveryHandler.isNoRxDataStallDetectionEnabled() && isAnyDataConnected()) {
            // If screen is on or data stall is currently suspected, set the alarm
            // with an aggressive timeout.
            if (mIsScreenOn || suspectedStall || mDsRecoveryHandler.isAggressiveRecovery()) {
@@ -4921,7 +4872,7 @@ public class DcTracker extends Handler {
    }

    private void restartDataStallAlarm() {
        if (isConnected() == false) return;
        if (!isAnyDataConnected()) return;
        // To be called on screen status change.
        // Do not cancel the alarm if it is set with aggressive timeout.
        if (mDsRecoveryHandler.isAggressiveRecovery()) {
+4 −19
Original line number Diff line number Diff line
@@ -17,32 +17,17 @@
package com.android.internal.telephony.vendor.dataconnection;

import android.app.AlertDialog;
import android.view.WindowManager;

import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.CarrierConfigManager;
import android.telephony.DataFailCause;
import android.telephony.data.ApnSetting;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.view.WindowManager;

import com.android.internal.telephony.dataconnection.ApnContext;
import com.android.internal.telephony.dataconnection.DcTracker;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.AsyncChannel;

import android.database.Cursor;
import android.content.Context;
import android.os.PersistableBundle;
import android.provider.Telephony;
import com.android.internal.telephony.dataconnection.ApnContext;
import com.android.internal.telephony.dataconnection.DcTracker;

import java.util.HashSet;
import java.util.Iterator;
@@ -115,7 +100,7 @@ public class VendorDcTracker extends DcTracker {
    protected void onVoiceCallEnded() {
        if (DBG) log("onVoiceCallEnded");
        mInVoiceCall = false;
        if (isConnected()) {
        if (isAnyDataConnected()) {
            if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                startNetStatPoll();
                startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
+1 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ public class ServiceStateTrackerTest extends TelephonyTest {
        doReturn(mIwlanNetworkServiceStub).when(mIwlanNetworkServiceStub).asBinder();
        addNetworkService();

        doReturn(true).when(mDcTracker).isDisconnected();
        doReturn(true).when(mDcTracker).areAllDataDisconnected();

        doReturn(new ServiceState()).when(mPhone).getServiceState();

+10 −10
Original line number Diff line number Diff line
@@ -599,7 +599,7 @@ public class DcTrackerTest extends TelephonyTest {
        assertEquals(apnSetting, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
        assertArrayEquals(new String[]{PhoneConstants.APN_TYPE_DEFAULT}, mDct.getActiveApnTypes());

        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));

        LinkProperties linkProperties = mDct.getLinkProperties(PhoneConstants.APN_TYPE_DEFAULT);
@@ -793,7 +793,7 @@ public class DcTrackerTest extends TelephonyTest {
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                any(Message.class));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));
    }
@@ -904,7 +904,7 @@ public class DcTrackerTest extends TelephonyTest {
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                any(Message.class));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));

@@ -942,7 +942,7 @@ public class DcTrackerTest extends TelephonyTest {
                any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN3, 2, 64, 0, 0);

        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getState(PhoneConstants.APN_TYPE_IMS));

@@ -990,7 +990,7 @@ public class DcTrackerTest extends TelephonyTest {
                eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 5, 1, NETWORK_TYPE_LTE_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());

        AsyncResult ar = new AsyncResult(null,
                new Pair<>(false, DataEnabledSettings.REASON_DATA_ENABLED_BY_CARRIER), null);
@@ -1003,7 +1003,7 @@ public class DcTrackerTest extends TelephonyTest {
        verify(mSimulatedCommandsVerifier, times(1)).deactivateDataCall(
                eq(DataService.REQUEST_REASON_NORMAL), anyInt(),
                any(Message.class));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
        assertEquals(DctConstants.State.IDLE, mDct.getState(PhoneConstants.APN_TYPE_DEFAULT));
    }

@@ -1283,7 +1283,7 @@ public class DcTrackerTest extends TelephonyTest {
                eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());

        //data rat change from ehrpd to lte
        logd("Sending EVENT_DATA_RAT_CHANGED");
@@ -1321,7 +1321,7 @@ public class DcTrackerTest extends TelephonyTest {
                eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN1, 0, 21, 1, NETWORK_TYPE_LTE_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
    }

    // Test for fetchDunApns()
@@ -1405,7 +1405,7 @@ public class DcTrackerTest extends TelephonyTest {
                eq(false), eq(false), eq(DataService.REQUEST_REASON_NORMAL), any(),
                any(Message.class));
        verifyDataProfile(dpCaptor.getValue(), FAKE_APN4, 0, 21, 2, NETWORK_TYPE_EHRPD_BITMASK);
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());

        // Data rat change from ehrpd to unknown due to OOS
        logd("Sending EVENT_DATA_RAT_CHANGED");
@@ -1437,7 +1437,7 @@ public class DcTrackerTest extends TelephonyTest {

        // Verify the same data connection
        assertEquals(FAKE_APN4, mDct.getActiveApnString(PhoneConstants.APN_TYPE_DEFAULT));
        assertEquals(DctConstants.State.CONNECTED, mDct.getOverallState());
        assertTrue(mDct.isAnyDataConnected());
    }

    // Test provisioning