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

Commit b077af12 authored by Yashdev Singh's avatar Yashdev Singh
Browse files

Handle DATA_CALL_LIST in DCC and update dataActivity properly

Update mActivity in DCC before notifyDataActivity. Without this change,
the notifyDataActivity was notifying incorrect data activity status
due to race condition between DCT when mActivity was updated and
DCC thread where notifyDataActivity was called.

Bug: 11596853
Change-Id: Iffb7bf369062264dd773338c732bc69318d90b73
parent 89edee05
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.telephony.Rlog;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
@@ -208,7 +209,11 @@ class DcController extends StateMachine {
            // and any that are in active need to be retried.
            ArrayList<ApnContext> apnsToCleanup = new ArrayList<ApnContext>();

            boolean isAnyDataCallDormant = false;
            boolean isAnyDataCallActive = false;

            for (DataCallResponse newState : dcsList) {

                DataConnection dc = mDcListActiveByCid.get(newState.cid);
                if (dc == null) {
                    // UNSOL_DATA_CALL_LIST_CHANGED arrived before SETUP_DATA_CALL completed.
@@ -297,8 +302,35 @@ class DcController extends StateMachine {
                        }
                    }
                }

                if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_UP) {
                    isAnyDataCallActive = true;
                }
                if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT) {
                    isAnyDataCallDormant = true;
                }
            }

            if (isAnyDataCallDormant && !isAnyDataCallActive) {
                // There is no way to indicate link activity per APN right now. So
                // Link Activity will be considered dormant only when all data calls
                // are dormant.
                // If a single data call is in dormant state and none of the data
                // calls are active broadcast overall link state as dormant.
                if (DBG) {
                    log("onDataStateChanged: Data Activity updated to DORMANT. stopNetStatePoll");
                }
                mDct.sendStopNetStatPoll(DctConstants.Activity.DORMANT);
            } else {
                if (DBG) {
                    log("onDataStateChanged: Data Activity updated to NONE. " +
                            "isAnyDataCallActive = " + isAnyDataCallActive +
                            " isAnyDataCallDormant = " + isAnyDataCallDormant);
                }
                if (isAnyDataCallActive) {
                    mDct.sendStartNetStatPoll(DctConstants.Activity.NONE);
                }
            }
            mPhone.notifyDataActivity();

            if (DBG) {
                lr("onDataStateChanged: dcsToRetry=" + dcsToRetry
+1 −78
Original line number Diff line number Diff line
@@ -121,8 +121,7 @@ public final class DcTracker extends DcTrackerBase {
        p.mCi.registerForAvailable (this, DctConstants.EVENT_RADIO_AVAILABLE, null);
        p.mCi.registerForOffOrNotAvailable(this, DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE,
                null);
        p.mCi.registerForDataNetworkStateChanged (this, DctConstants.EVENT_DATA_STATE_CHANGED,
                null);

        p.getCallTracker().registerForVoiceCallEnded (this, DctConstants.EVENT_VOICE_CALL_ENDED,
                null);
        p.getCallTracker().registerForVoiceCallStarted (this, DctConstants.EVENT_VOICE_CALL_STARTED,
@@ -1109,67 +1108,6 @@ public final class DcTracker extends DcTrackerBase {
        return null;
    }

    /**
     * @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
     * or RIL_UNSOL_DATA_CALL_LIST_CHANGED
     */
    private void onDataStateChanged (AsyncResult ar) {
        ArrayList<DataCallResponse> dataCallStates;

        if (DBG) log("onDataStateChanged(ar): E");
        dataCallStates = (ArrayList<DataCallResponse>)(ar.result);

        if (ar.exception != null) {
            // This is probably "radio not available" or something
            // of that sort. If so, the whole connection is going
            // to come down soon anyway
            if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
            return;
        }
        if (DBG) log("onDataStateChanged(ar): DataCallResponse size=" + dataCallStates.size());

        // Create a hash map to store the dataCallState of each DataConnectionAc
        HashMap<DataCallResponse, DcAsyncChannel> dataCallStateToDcac;
        dataCallStateToDcac = new HashMap<DataCallResponse, DcAsyncChannel>();
        for (DataCallResponse dataCallState : dataCallStates) {
            DcAsyncChannel dcac = findDataConnectionAcByCid(dataCallState.cid);

            if (dcac != null) dataCallStateToDcac.put(dataCallState, dcac);
        }

        // Check if we should start or stop polling, by looking
        // for dormant and active connections.
        boolean isAnyDataCallDormant = false;
        boolean isAnyDataCallActive = false;
        for (DataCallResponse newState : dataCallStates) {
            if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_UP) isAnyDataCallActive = true;
            if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_DOWN) isAnyDataCallDormant = true;
        }

        if (isAnyDataCallDormant && !isAnyDataCallActive) {
            // There is no way to indicate link activity per APN right now. So
            // Link Activity will be considered dormant only when all data calls
            // are dormant.
            // If a single data call is in dormant state and none of the data
            // calls are active broadcast overall link state as dormant.
            mActivity = DctConstants.Activity.DORMANT;
            if (DBG) {
                log("onDataStateChanged: Data Activity updated to DORMANT. stopNetStatePoll");
            }
            stopNetStatPoll();
        } else {
            mActivity = DctConstants.Activity.NONE;
            if (DBG) {
                log("onDataStateChanged: Data Activity updated to NONE. " +
                         "isAnyDataCallActive = " + isAnyDataCallActive +
                         " isAnyDataCallDormant = " + isAnyDataCallDormant);
            }
            if (isAnyDataCallActive) startNetStatPoll();
        }

        if (DBG) log("onDataStateChanged(ar): X");
    }

    // TODO: For multiple Active APNs not exactly sure how to do this.
    @Override
    protected void gotoIdleAndNotifyDataConnection(String reason) {
@@ -1866,13 +1804,6 @@ public final class DcTracker extends DcTrackerBase {
        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
    }

    protected void onPollPdp() {
        if (getOverallState() == DctConstants.State.CONNECTED) {
            // only poll when connected
            mPhone.mCi.getDataCallList(obtainMessage(DctConstants.EVENT_DATA_STATE_CHANGED));
            sendMessageDelayed(obtainMessage(DctConstants.EVENT_POLL_PDP), POLL_PDP_MILLIS);
        }
    }

    @Override
    protected void onVoiceCallStarted() {
@@ -2206,14 +2137,6 @@ public final class DcTracker extends DcTrackerBase {
                onDataConnectionAttached();
                break;

            case DctConstants.EVENT_DATA_STATE_CHANGED:
                onDataStateChanged((AsyncResult) msg.obj);
                break;

            case DctConstants.EVENT_POLL_PDP:
                onPollPdp();
                break;

            case DctConstants.EVENT_DO_RECOVERY:
                doRecovery();
                break;
+48 −4
Original line number Diff line number Diff line
@@ -595,6 +595,12 @@ public abstract class DcTrackerBase extends Handler {
        return mActivity;
    }

    void setActivity(DctConstants.Activity activity) {
        log("setActivity = " + activity);
        mActivity = activity;
        mPhone.notifyDataActivity();
    }

    public boolean isApnTypeActive(String type) {
        // TODO: support simultaneous with List instead
        if (PhoneConstants.APN_TYPE_DUN.equals(type)) {
@@ -936,6 +942,14 @@ public abstract class DcTrackerBase extends Handler {
                restartRadio();
                break;
            }
            case DctConstants.CMD_NET_STAT_POLL: {
                if (msg.arg1 == DctConstants.ENABLED) {
                    handleStartNetStatPoll((DctConstants.Activity)msg.obj);
                } else if (msg.arg1 == DctConstants.DISABLED) {
                    handleStopNetStatPoll((DctConstants.Activity)msg.obj);
                }
                break;
            }
            default:
                Rlog.e("DATA", "Unidentified event msg=" + msg);
                break;
@@ -1378,20 +1392,50 @@ public abstract class DcTrackerBase extends Handler {

    protected abstract DctConstants.State getOverallState();

    protected void startNetStatPoll() {
    void startNetStatPoll() {
        if (getOverallState() == DctConstants.State.CONNECTED
                && mNetStatPollEnabled == false) {
            if (DBG) log("startNetStatPoll");
            if (DBG) {
                log("startNetStatPoll");
            }
            resetPollStats();
            mNetStatPollEnabled = true;
            mPollNetStat.run();
        }
    }

    protected void stopNetStatPoll() {
    void stopNetStatPoll() {
        mNetStatPollEnabled = false;
        removeCallbacks(mPollNetStat);
        if (DBG) log("stopNetStatPoll");
        if (DBG) {
            log("stopNetStatPoll");
        }
    }

    public void sendStartNetStatPoll(DctConstants.Activity activity) {
        Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL);
        msg.arg1 = DctConstants.ENABLED;
        msg.obj = activity;
        sendMessage(msg);
    }

    protected void handleStartNetStatPoll(DctConstants.Activity activity) {
        startNetStatPoll();
        startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
        setActivity(activity);
    }

    public void sendStopNetStatPoll(DctConstants.Activity activity) {
        Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL);
        msg.arg1 = DctConstants.DISABLED;
        msg.obj = activity;
        sendMessage(msg);
    }

    protected void handleStopNetStatPoll(DctConstants.Activity activity) {
        stopNetStatPoll();
        stopDataStallAlarm();
        setActivity(activity);
    }

    public void updateDataActivity() {