mobile data setup flow(移动网络--建立数据业务部分)

DcTracker.java

firstly, needs to get usable DcAsyncChannel for the current ApnContext to establish datacall.

the process try to find out if any channel is able to be used directly: checkForCompatibleConnectedApnContext() and findFreeDataConnection().

the first check if any connected APN type that whose ApnSetting is compatible with the current requested one exists so that it can be reused directly; while the other try to get freed DcAsyncChannel from mDataConnectionAcHashMap directly.

if no existed one found, create one instance by calling createDataConnection().

at last, a msg will be created and passed to the dcac's API bringUp(). the msg will be used when we get response from lower layer so that the result will be send to back to DcTracker. we will find the point where it is used later.

    private boolean setupData(ApnContext apnContext) {
...
        dcac = checkForCompatibleConnectedApnContext(apnContext);
...
        if (dcac == null) {
            dcac = findFreeDataConnection();

            if (dcac == null) {
                dcac = createDataConnection();
            }
...
...
        Message msg = obtainMessage();
        msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
        msg.obj = apnContext;
        dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, msg);

DcAsyncChannel.java

in fact the API here is very simple, just pass related params to DataConnection with wrapped new msg.

    public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId,
            Message onCompletedMsg) {
        sendMessage(DataConnection.EVENT_CONNECT,
                    new ConnectionParams(apnContext, initialMaxRetry, profileId, onCompletedMsg));
    }

DataConnection.java

different state will have different behaviour. for example, if in DefaultState, will reply directy as below code showed:

    private class DcDefaultState extends State {
...
        public boolean processMessage(Message msg) {
            boolean retVal = HANDLED;
            AsyncResult ar;
...
            switch (msg.what) {
...
                case EVENT_CONNECT:
                    ConnectionParams cp = (ConnectionParams) msg.obj;
                    notifyConnectCompleted(cp, DcFailCause.UNKNOWN, false);
                    break;
here we suppose that all are OK and the request should go on, so the progress will be like

    private class DcInactiveState extends State {
...
        public boolean processMessage(Message msg) {
            boolean retVal;

            switch (msg.what) {
...
                case EVENT_CONNECT:
                    if (initConnection(cp)) {
                        onConnect(mConnectionParams);
                        transitionTo(mActivatingState);
                    } else {
...

initConnection() will check APNSettings and records the request into both mConnectionParams and ApnContexts, at last it will set the retry config for use later if there is any problem from modem when data call not setup OK.
then we go to onConnect and the state transition to ActiviatingState

    private void onConnect(ConnectionParams cp) {
...
        Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
        msg.obj = cp;
...
        mPhone.mCi.setupDataCall(
                Integer.toString(getRilRadioTechnology()),
                Integer.toString(cp.mProfileId),
                mApnSetting.apn, mApnSetting.user, mApnSetting.password,
                Integer.toString(authType),
                protocol, msg);
here also just wrap the ConnectionParams into Message and then call setupDataCall with the message. this wrapped msg will be used by RIL to notify the result to DataConnection.

after this, the connection request is passed into RIL.java
for the rough flow of request handler in RIL.java, you can reference my previous article.

so, waiting for completing............

    private class DcActivatingState extends State {
        @Override
        public boolean processMessage(Message msg) {
            boolean retVal;
            AsyncResult ar;
            ConnectionParams cp;
...
            switch (msg.what) {
...
                case EVENT_SETUP_DATA_CONNECTION_DONE:
                    ar = (AsyncResult) msg.obj;
                    cp = (ConnectionParams) ar.userObj;

                    DataCallResponse.SetupResult result = onSetupConnectionCompleted(ar);
                    switch (result) {
we will not always so lucky to make sure the results is OK, with diff result, the behaviour will also diff...

if all OK, it will go to ActiveState to do what we all expect to do. :-D

                        case SUCCESS:
                            // All is well
                            mDcFailCause = DcFailCause.NONE;
                            transitionTo(mActiveState);
else if failed from modem and has chance to reestablish, get the configed retry delay settings and startRetryAlarm, go to RetryingState to waiting for our retry chance.

                        case ERR_RilError:
                            int delay = mDcRetryAlarmController.getSuggestedRetryTime(
                                                                    DataConnection.this, ar);
...
                            if (delay >= 0) {
                                mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION,
                                                            mTag, delay);
                                transitionTo(mRetryingState);
                            } else {
here supposed that we get all right now and go into activeState now.

    private class DcActiveState extends State {
...
            if (mRetryManager.getRetryCount() != 0) {
                mRetryManager.setRetryCount(0);
            }
            notifyAllOfConnected(Phone.REASON_CONNECTED);
            mRetryManager.restoreCurMaxRetryCount();
            mDcController.addActiveDcByCid(DataConnection.this);
first reset the retry count and then notify to the upper layer, at last add itself into DcController.

the notify function sends the msg back to DcTracker

    private void notifyAllOfConnected(String reason) {
        notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason);
    }


DcTrackerBase.java
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
...
            case DctConstants.EVENT_DATA_SETUP_COMPLETE:
                mCidActive = msg.arg1;
                onDataSetupComplete((AsyncResult) msg.obj);
                break;
see, we back now!

    protected void onDataSetupComplete(AsyncResult ar) {
...
        if(ar.userObj instanceof ApnContext){
            apnContext = (ApnContext)ar.userObj;
...
        if (ar.exception == null) {
            DcAsyncChannel dcac = apnContext.getDcAc();	
...
            if (dcac == null) {
                log("onDataSetupComplete: no connection to DC, handle as error");
                cause = DcFailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN;
                handleError = true;
            } else {
                ApnSetting apn = apnContext.getApnSetting();
...
                        ProxyProperties proxy = new ProxyProperties(apn.proxy,
                                Integer.parseInt(port), null);
                        dcac.setLinkPropertiesHttpProxySync(proxy);
...
                notifyDefaultData(apnContext);
            }
        } else {
            cause = (DcFailCause) (ar.result);

            if (cause.isPermanentFail()) apnContext.decWaitingApnsPermFailCount();
            apnContext.removeWaitingApn(apnContext.getApnSetting());
            handleError = true;
        }			
        if (handleError) {
            onDataSetupCompleteError(ar);
        }

if all go well, set proxy into LinkProperties and call notifyDefaultData() to info upper layer.

if any error detected, goto error handle flow onDataSetupCompleteError().

    private void notifyDefaultData(ApnContext apnContext) {
        apnContext.setState(DctConstants.State.CONNECTED);
        mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
        startNetStatPoll();
        startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
    }

the function just updates the ApnContext state, notify overall the system about the data connection change, and start net stats poll process.

mPhone.notifyDataConnection() will notify MobileDataStateTracker, which send msg to ConnectivityService infoing that current Mobile type connected.

after this, ConnectivityService will change the network related config such as DNS/Routing and then send Broadcast of CONNECTIVITY_CHANGE, which is used for all interested modules.

NOTICE:

more simple for the total flow, no much details.

error handle and retry part can be a topic.

ConnectivityService's handle of network change and config can also be one huge topic.


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值