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

Commit e3ea025b authored by Jack Yu's avatar Jack Yu
Browse files

Support handover retry

The data service now can control whether retry
handover or not.

Fix: 160105644
Test: FrameworksTelephonyTests
Merged-In: Ieb037f529aba3e889205dce6cdb1f26bce0b7274
Change-Id: Ieb037f529aba3e889205dce6cdb1f26bce0b7274
(cherry picked from commit 0330ecd0)
parent 7ba0f259
Loading
Loading
Loading
Loading
+31 −14
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataCallResponse.HandoverFailureMode;
import android.telephony.data.DataProfile;
import android.telephony.data.DataService;
import android.telephony.data.DataServiceCallback;
@@ -263,6 +264,9 @@ public class DataConnection extends StateMachine {
    @DataFailureCause
    private int mDcFailCause;

    @HandoverFailureMode
    private int mHandoverFailureMode;

    private Phone mPhone;
    private DataServiceManager mDataServiceManager;
    private final int mTransportType;
@@ -859,7 +863,8 @@ public class DataConnection extends StateMachine {
            if (apnContext == alreadySent) continue;
            if (reason != null) apnContext.setReason(reason);
            Pair<ApnContext, Integer> pair = new Pair<>(apnContext, cp.mConnectionGeneration);
            Message msg = mDct.obtainMessage(event, mCid, cp.mRequestType, pair);
            Message msg = mDct.obtainMessage(event, cp.mRequestType,
                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, pair);
            AsyncResult.forMessage(msg);
            msg.sendToTarget();
        }
@@ -870,10 +875,11 @@ public class DataConnection extends StateMachine {
     *
     * @param cp is the ConnectionParams
     * @param cause and if no error the cause is DataFailCause.NONE
     * @param handoverFailureMode The action on handover failure
     * @param sendAll is true if all contexts are to be notified
     */
    private void notifyConnectCompleted(ConnectionParams cp, @DataFailureCause int cause,
                                        boolean sendAll) {
            @HandoverFailureMode int handoverFailureMode, boolean sendAll) {
        ApnContext alreadySent = null;

        if (cp != null && cp.mOnCompletedMsg != null) {
@@ -883,8 +889,8 @@ public class DataConnection extends StateMachine {
            alreadySent = cp.mApnContext;

            long timeStamp = System.currentTimeMillis();
            connectionCompletedMsg.arg1 = mCid;
            connectionCompletedMsg.arg2 = cp.mRequestType;
            connectionCompletedMsg.arg1 = cp.mRequestType;
            connectionCompletedMsg.arg2 = handoverFailureMode;

            if (cause == DataFailCause.NONE) {
                mCreateTime = timeStamp;
@@ -999,6 +1005,7 @@ public class DataConnection extends StateMachine {
        mUplinkBandwidth = 14;
        mIsSuspended = false;
        mHandoverState = HANDOVER_STATE_IDLE;
        mHandoverFailureMode = DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN;
    }

    /**
@@ -1743,7 +1750,8 @@ public class DataConnection extends StateMachine {
                case EVENT_CONNECT:
                    if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
                    ConnectionParams cp = (ConnectionParams) msg.obj;
                    notifyConnectCompleted(cp, DataFailCause.UNKNOWN, false);
                    notifyConnectCompleted(cp, DataFailCause.UNKNOWN,
                            DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, false);
                    break;

                case EVENT_DISCONNECT:
@@ -1821,12 +1829,13 @@ public class DataConnection extends StateMachine {
     */
    private class DcInactiveState extends State {
        // Inform all contexts we've failed connecting
        public void setEnterNotificationParams(ConnectionParams cp,
                                               @DataFailureCause int cause) {
        public void setEnterNotificationParams(ConnectionParams cp, @DataFailureCause int cause,
                @HandoverFailureMode int handoverFailureMode) {
            if (VDBG) log("DcInactiveState: setEnterNotificationParams cp,cause");
            mConnectionParams = cp;
            mDisconnectParams = null;
            mDcFailCause = cause;
            mHandoverFailureMode = handoverFailureMode;
        }

        // Inform all contexts we've failed disconnected
@@ -1855,6 +1864,7 @@ public class DataConnection extends StateMachine {
                    mApnSetting != null
                        ? mApnSetting.canHandleType(ApnSetting.TYPE_DEFAULT) : false);
            if (mHandoverState == HANDOVER_STATE_BEING_TRANSFERRED) {
                // This is from source data connection to set itself's state
                setHandoverState(HANDOVER_STATE_COMPLETED);
            }

@@ -1890,7 +1900,7 @@ public class DataConnection extends StateMachine {
                    log("DcInactiveState: enter notifyConnectCompleted +ALL failCause="
                            + mDcFailCause);
                }
                notifyConnectCompleted(mConnectionParams, mDcFailCause, true);
                notifyConnectCompleted(mConnectionParams, mDcFailCause, mHandoverFailureMode, true);
            }
            if (mDisconnectParams != null) {
                if (DBG) {
@@ -1943,7 +1953,7 @@ public class DataConnection extends StateMachine {
                    if (!initConnection(cp)) {
                        log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed");
                        notifyConnectCompleted(cp, DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
                                false);
                                DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, false);
                        transitionTo(mInactiveState);
                        return HANDLED;
                    }
@@ -1951,7 +1961,8 @@ public class DataConnection extends StateMachine {
                    int cause = connect(cp);
                    if (cause != DataFailCause.NONE) {
                        log("DcInactiveState: msg.what=EVENT_CONNECT connect failed");
                        notifyConnectCompleted(cp, cause, false);
                        notifyConnectCompleted(cp, cause,
                                DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, false);
                        transitionTo(mInactiveState);
                        return HANDLED;
                    }
@@ -2051,7 +2062,8 @@ public class DataConnection extends StateMachine {
                            // Vendor ril rejected the command and didn't connect.
                            // Transition to inactive but send notifications after
                            // we've entered the mInactive state.
                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
                                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN);
                            transitionTo(mInactiveState);
                            break;
                        case ERROR_INVALID_ARG:
@@ -2083,7 +2095,10 @@ public class DataConnection extends StateMachine {
                            // Save the cause. DcTracker.onDataSetupComplete will check this
                            // failure cause and determine if we need to retry this APN later
                            // or not.
                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
                            mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
                                    // TODO: The actual failure mode should come from the underlying
                                    //  data service
                                    DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY);
                            transitionTo(mInactiveState);
                            break;
                        case ERROR_STALE:
@@ -2285,7 +2300,8 @@ public class DataConnection extends StateMachine {
                    if (DBG) {
                        log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this);
                    }
                    notifyConnectCompleted(cp, DataFailCause.NONE, false);
                    notifyConnectCompleted(cp, DataFailCause.NONE,
                            DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, false);
                    retVal = HANDLED;
                    break;
                }
@@ -2693,7 +2709,8 @@ public class DataConnection extends StateMachine {
                        // Transition to inactive but send notifications after
                        // we've entered the mInactive state.
                        mInactiveState.setEnterNotificationParams(cp,
                                DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER);
                                DataFailCause.UNACCEPTABLE_NETWORK_PARAMETER,
                                DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN);
                        transitionTo(mInactiveState);
                    } else {
                        if (DBG) {
+39 −24
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.SimState;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataCallResponse.HandoverFailureMode;
import android.telephony.data.DataProfile;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -483,7 +485,8 @@ public class DcTracker extends Handler {
        }
    }

    private void onDataReconnect(ApnContext apnContextforRetry, int subId) {
    private void onDataReconnect(ApnContext apnContextforRetry, int subId,
            @RequestNetworkType int requestType) {
        int phoneSubId = mPhone.getSubId();
        String apnType = apnContextforRetry.getApnType();
        String reason =  apnContextforRetry.getReason();
@@ -2286,16 +2289,17 @@ public class DcTracker extends Handler {
        return retry;
    }

    protected void startReconnect(long delay, ApnContext apnContext) {
    protected void startReconnect(long delay, ApnContext apnContext,
            @RequestNetworkType int requestType) {
        Message msg = obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
                       mPhone.getSubId(), mTransportType, apnContext);
                       mPhone.getSubId(), requestType, apnContext);
        cancelReconnect(apnContext);
        sendMessageDelayed(msg, delay);

        if (DBG) {
            log("startReconnect: delay=" + delay + " apn="
                    + apnContext + "reason: " + apnContext.getReason()
                    + " subId: " + mPhone.getSubId());
                    + " subId=" + mPhone.getSubId() + " request type=" + requestType);
        }
    }

@@ -2467,6 +2471,7 @@ public class DcTracker extends Handler {
    private void sendRequestNetworkCompleteMsg(Message message, boolean success,
                                               @TransportType int transport,
                                               @RequestNetworkType int requestType,
                                               @HandoverFailureMode int handoverFailureMode,
                                               @DataFailureCause int cause) {
        if (message == null) return;

@@ -2474,11 +2479,11 @@ public class DcTracker extends Handler {
        b.putBoolean(DATA_COMPLETE_MSG_EXTRA_SUCCESS, success);
        b.putInt(DATA_COMPLETE_MSG_EXTRA_REQUEST_TYPE, requestType);
        b.putInt(DATA_COMPLETE_MSG_EXTRA_TRANSPORT_TYPE, transport);
        // TODO: For now this is the only fail cause that we know modem keeps data connection on
        // original transport. Might add more complicated logic or mapping in the future.
        b.putBoolean(DATA_COMPLETE_MSG_EXTRA_HANDOVER_FAILURE_FALLBACK,
                (requestType == REQUEST_TYPE_HANDOVER
                        && cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED));
                (handoverFailureMode == DataCallResponse.HANDOVER_FAILURE_MODE_DO_FALLBACK
                        || (handoverFailureMode
                        == DataCallResponse.HANDOVER_FAILURE_MODE_LEGACY
                        && cause == DataFailCause.HANDOFF_PREFERENCE_CHANGED)));
        message.sendToTarget();
    }

@@ -2494,7 +2499,7 @@ public class DcTracker extends Handler {
        if (apnContext == null) {
            loge("onEnableApn(" + apnType + "): NO ApnContext");
            sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
                    DataFailCause.NONE);
                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, DataFailCause.NONE);
            return;
        }

@@ -2510,7 +2515,7 @@ public class DcTracker extends Handler {
            if (DBG) log(str);
            apnContext.requestLog(str);
            sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType, requestType,
                    DataFailCause.NONE);
                    DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, DataFailCause.NONE);
            return;
        }

@@ -2526,13 +2531,15 @@ public class DcTracker extends Handler {
                    if (DBG) log("onEnableApn: 'CONNECTED' so return");
                    // Don't add to local log since this is so common
                    sendRequestNetworkCompleteMsg(onCompleteMsg, true, mTransportType,
                            requestType, DataFailCause.NONE);
                            requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                            DataFailCause.NONE);
                    return;
                case DISCONNECTING:
                    if (DBG) log("onEnableApn: 'DISCONNECTING' so return");
                    apnContext.requestLog("onEnableApn state=DISCONNECTING, so return");
                    sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
                            requestType, DataFailCause.NONE);
                            requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                            DataFailCause.NONE);
                    return;
                case IDLE:
                    // fall through: this is unexpected but if it happens cleanup and try setup
@@ -2561,7 +2568,8 @@ public class DcTracker extends Handler {
                addRequestNetworkCompleteMsg(onCompleteMsg, apnType);
            } else {
                sendRequestNetworkCompleteMsg(onCompleteMsg, false, mTransportType,
                        requestType, DataFailCause.NONE);
                        requestType, DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN,
                        DataFailCause.NONE);
            }
        } else {
            log("onEnableApn: config not ready yet.");
@@ -2832,12 +2840,13 @@ public class DcTracker extends Handler {
     * there is an error this method will call {@link #onDataSetupCompleteError}.
     */
    protected void onDataSetupComplete(ApnContext apnContext, boolean success, int cause,
                                     @RequestNetworkType int requestType) {
            @RequestNetworkType int requestType, @HandoverFailureMode int handoverFailureMode) {
        int apnType = ApnSetting.getApnTypesBitmaskFromString(apnContext.getApnType());
        List<Message> messageList = mRequestNetworkCompletionMsgs.get(apnType);
        if (messageList != null) {
            for (Message msg : messageList) {
                sendRequestNetworkCompleteMsg(msg, success, mTransportType, requestType, cause);
                sendRequestNetworkCompleteMsg(msg, success, mTransportType, requestType,
                        handoverFailureMode, cause);
            }
            messageList.clear();
        }
@@ -2995,7 +3004,7 @@ public class DcTracker extends Handler {
     * Error has occurred during the SETUP {aka bringUP} request and the DCT
     * should either try the next waiting APN or start over from the
     * beginning if the list is empty. Between each SETUP request there will
     * be a delay defined by {@link #getApnDelay()}.
     * be a delay defined by {@link ApnContext#getDelayForNextApn(boolean)}.
     */
    protected void onDataSetupCompleteError(ApnContext apnContext,
                                          @RequestNetworkType int requestType) {
@@ -3009,7 +3018,7 @@ public class DcTracker extends Handler {
            // Wait a bit before trying the next APN, so that
            // we're not tying up the RIL command channel

            startReconnect(delay, apnContext);
            startReconnect(delay, apnContext, requestType);
        } else {
            // If we are not going to retry any APN, set this APN context to failed state.
            // This would be the final state of a data connection.
@@ -3089,7 +3098,7 @@ public class DcTracker extends Handler {
            if (delay > 0) {
                // Data connection is in IDLE state, so when we reconnect later, we'll rebuild
                // the waiting APN list, which will also reset/reconfigure the retry manager.
                startReconnect(delay, apnContext);
                startReconnect(delay, apnContext, REQUEST_TYPE_NORMAL);
            }
        } else {
            boolean restartRadioAfterProvisioning = mPhone.getContext().getResources().getBoolean(
@@ -3518,6 +3527,7 @@ public class DcTracker extends Handler {
        ApnContext apnContext;
        int generation;
        int requestType;
        int handoverFailureMode;
        switch (msg.what) {
            case DctConstants.EVENT_DATA_CONNECTION_DETACHED:
                onDataConnectionDetached();
@@ -3666,7 +3676,8 @@ public class DcTracker extends Handler {
                pair = (Pair<ApnContext, Integer>) ar.userObj;
                apnContext = pair.first;
                generation = pair.second;
                requestType = msg.arg2;
                requestType = msg.arg1;
                handoverFailureMode = msg.arg2;
                if (apnContext.getConnectionGeneration() == generation) {
                    boolean success = true;
                    int cause = DataFailCause.UNKNOWN;
@@ -3674,7 +3685,8 @@ public class DcTracker extends Handler {
                        success = false;
                        cause = (int) ar.result;
                    }
                    onDataSetupComplete(apnContext, success, cause, requestType);
                    onDataSetupComplete(apnContext, success, cause, requestType,
                            handoverFailureMode);
                } else {
                    loge("EVENT_DATA_SETUP_COMPLETE: Dropped the event because generation "
                            + "did not match.");
@@ -3686,9 +3698,9 @@ public class DcTracker extends Handler {
                pair = (Pair<ApnContext, Integer>) ar.userObj;
                apnContext = pair.first;
                generation = pair.second;
                requestType = msg.arg2;
                handoverFailureMode = msg.arg2;
                if (apnContext.getConnectionGeneration() == generation) {
                    onDataSetupCompleteError(apnContext, requestType);
                    onDataSetupCompleteError(apnContext, handoverFailureMode);
                } else {
                    loge("EVENT_DATA_SETUP_COMPLETE_ERROR: Dropped the event because generation "
                            + "did not match.");
@@ -3837,8 +3849,11 @@ public class DcTracker extends Handler {
                break;
            }
            case DctConstants.EVENT_DATA_RECONNECT:
                if (DBG) log("EVENT_DATA_RECONNECT: subId=" + msg.arg1);
                onDataReconnect((ApnContext) msg.obj, msg.arg1);
                if (DBG) {
                    log("EVENT_DATA_RECONNECT: subId=" + msg.arg1 + ", type="
                            + requestTypeToString(msg.arg2));
                }
                onDataReconnect((ApnContext) msg.obj, msg.arg1, msg.arg2);
                break;
            case DctConstants.EVENT_DATA_SERVICE_BINDING_CHANGED:
                onDataServiceBindingChanged((Boolean) ((AsyncResult) msg.obj).result);
+4 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.telephony.DataFailCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.data.DataCallResponse.HandoverFailureMode;
import android.view.WindowManager;

import com.android.internal.telephony.DctConstants;
@@ -131,7 +132,7 @@ public class VendorDcTracker extends DcTracker {

    @Override
    protected void onDataSetupComplete(ApnContext apnContext, boolean success, int cause,
            @RequestNetworkType int requestType) {
            @RequestNetworkType int requestType, @HandoverFailureMode int handoverFailureMode) {
        boolean isPdpRejectConfigEnabled = mPhone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_pdp_reject_enable_retry);
        if (success) {
@@ -142,7 +143,7 @@ public class VendorDcTracker extends DcTracker {
            mPdpRejectCauseCode = cause;
        }

        super.onDataSetupComplete(apnContext, success, cause, requestType);
        super.onDataSetupComplete(apnContext, success, cause, requestType, handoverFailureMode);
    }

    @Override
@@ -187,7 +188,7 @@ public class VendorDcTracker extends DcTracker {
            // Wait a bit before trying the next APN, so that
            // we're not tying up the RIL command channel

            startReconnect(delay, apnContext);
            startReconnect(delay, apnContext, requestType);
        } else {
            // If we are not going to retry any APN, set this APN context to failed state.
            // This would be the final state of a data connection.
+2 −4
Original line number Diff line number Diff line
@@ -744,8 +744,7 @@ public class DcTrackerTest extends TelephonyTest {
        //Send event for reconnecting data
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
                        mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                        mApnContext));
                        mPhone.getPhoneId(), DcTracker.REQUEST_TYPE_NORMAL, mApnContext));
        waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());

        // Data connection is running on a different thread. Have to wait.
@@ -1303,8 +1302,7 @@ public class DcTrackerTest extends TelephonyTest {
        //Send event for reconnecting data
        initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL});
        mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_DATA_RECONNECT,
                        mPhone.getPhoneId(), AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                        mApnContext));
                        mPhone.getPhoneId(), DcTracker.RELEASE_TYPE_NORMAL, mApnContext));
        waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());

        // Data connection is running on a different thread. Have to wait.