数据业务建立流程之发起网络连接过程(原)经过前面这些过程,网络连接所需要的条件就全部准备就绪,接下来就是等待网络接入。
我们把网络接入过程简单分为三个阶段:触发阶段----该阶段是由各种不同事件触发的,比如SIM 载入完毕、PS域Attach成功、通话结束、APN改变等,该阶段的最终都是要调用setupDataOnConnectableApns()方法;准备连接阶段----该阶段是指,在DcTracker收到建立连接的请求之后,需要进行一系列有效性检测,比如APN是否已经激活、PS是否已经就绪、用户是否打开网络开关等,然后创建DataConnection()对象,准备发起连接请求;发送连接命令阶段----该阶段是指,在DataConnection收到DcTracker的请求之后,将请求转交给RILJ的过程,经过该阶段后,请求就发送到了RIL以及Modem层,由底层完成信令的发送和接收;一、触发阶段有多种事件可以触发网络接入过程,具体来说分为以下几个原因:[java] view plain copy //漫游相关static final String REASON_ROAMING_ON = "roamingOn"; static final String REASON_ROAMING_OFF = "roamingOff"; //PS attach static final String REASON_DATA_ATTACHED = "dataAttached"; //APN改变static final String REASON_APN_CHANGED = "apnChanged"; //通话结束static final String REASON_VOICE_CALL_ENDED ="2GVoiceCallEnded"; //SIM载入完毕static final String REASON_SIM_LOADED = "simLoaded"; //网络模式改变static final String REASON_NW_TYPE_CHANGED = "nwTypeChanged"; 我们挑选最常见的REASON_DATA_ATTACHED原因来分析网络连接的发起过程。
什么是Data Attach事件呢?其实就是手机的PS域Attach成功,而PS域是和CS域相对应,简单来说,手机(2G/3G)打电话是在CS域上进行,而数据流量是在PS域上进行,PS域附着(Attach)成功之后才可以发起数据激活的信令,然后才可以上网,默认状态下,手机开机后就会发起PS附着的信令给网络,附着成功之后将会接到成功的消息,由于DcTracker当初初始化时在registerForAllEvents()中注册了Attach的监听器:[java] view plain copy protected void registerForAllEvents() { //监听是否PS域Attach状态mPhone.getServiceStateTracker().registerForDataConnec tionAttached(this,DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null); } 因此当PS域Attach成功之后,将会收到EVENT_DATA_CONNECTION_ATTACHED消息:[java] view plain copy public void handleMessage (Message msg) { switch (msg.what){ caseDctConstants.EVENT_DATA_CONNECTION_ATTACHED: onDataConnectionAttached();break; } } 继续:[java] view plain copy private void onDataConnectionAttached() { mAttached.set(true); if (getOverallState() == DctConstants.State.CONNECTED) { //已经处于连接状态startNetStatPoll();startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); notifyDataConnection(Phone.REASON_DATA_ATTACHE D); } else { //初始化后应该处于IDLE状态notifyOffApnsOfAvailability(Phone.REASON_DATA_ATTA CHED); } if (mAutoAttachOnCreationConfig) { mAutoAttachOnCreation = true; } setupDataOnConnectableApns(Phone.REASON_DATA_A TTACHED); } 当前的连接状态是IDLE,因此会将REASON_DATA_ATTACHED的参数传递给notifyOffApnsOfAvailability(),里面也没什么内容,我们直接来看setupDataOnConnectableApns()的操作。
setupDataOnConnectableApns()就是发起数据连接时使用的方法,调用该方法时需要传递一个原因的参数,该参数标明当前建立数据连接的原因(其实目前也没有发现该参数的具体作用)。
其他诸如SIM载入完毕、通话结束等触发事件也都是通过该方法发起数据连接请求的。
二、准备连接阶段当由于种种原因触发网络连接请求时,就会调用到setupDataOnConnectableApns()方法,并传递各种原因的参数,接下来就需要准备APN并进行各种有效性检测,并最终将请求转交给DataConnection来处理。
[java] view plain copy private void setupDataOnConnectableApns(String reason) { //对于当前环境来说,reason为REASON_DATA_ATTACHED for (ApnContext apnContext : mPrioritySortedApnContexts) { if (apnContext.getState() ==DctConstants.State.FAILED){ apnContext.setState(DctConstants.State.I DLE); } if(apnContext.isConnectable()){ apnContext.setReason(reason); trySetupData(apnContext); } } }在这个方法里面,遍历当前所有的APN参数(mPrioritySortedApnContexts其实等同于mApnContexts,只不过是按照优先级顺序排列了一下而已,项都是一样的),找到可用的APN参数,然后通过trySetupData()发起连接请求,我们来看一下这里如何判断一个APN是否可用,也就是看一下isConnectable()的判断条件:[java] view plain copy @ApnContext.java public boolean isConnectable() { return isReady() && ((mState == DctConstants.State.IDLE) || (mState == DctConstants.State.SCANNING)|| (mState == DctConstants.State.RETRYING)|| (mState == DctConstants.State.FAILED)); }前面我们说过,激活APN的时候,其实就是让isReady()的判断通过,而mState初始值也是IDLE,因此刚才我们激活的APN参数此时就被挑选出来,并进行trySetupData()的操作:[java] view plain copy @DcTracker.java private boolean trySetupData(ApnContext apnContext) { boolean isEmergencyApn =apnContext.getApnType().equals(PhoneConstants.APN_T YPE_EMERGENCY); boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState( ); boolean checkUserDataEnabled= !(apnContext.getApnType().equals(PhoneConstants.AP N_TYPE_IMS)); if (apnContext.isConnectable()&& (isEmergencyApn ||(isDataAllowed(apnContext) && getAnyDataEnabled(checkUserDataEnabled)&& !isEmergency()))) { int radioTech = mPhone.getServiceState().getRilDataRadioTechnology(); if (apnContext.getState() == DctConstants.State.IDLE) { ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech); if (waitingApns.isEmpty()){ notifyNoData(DcFailCause.MISSING _UNKNOWN_APN, apnContext); notifyOffApnsOfAvailability(apnContext.getReason()); return false; } else{ apnContext.setWaitingApns(waitingA pns); } } //建立连接boolean retValue = setupData(apnContext, radioTech); notifyOffApnsOfAvailability(apnContext.getReason()); return retValue; } else { } } 这里主要经历了有效性的检查,其中判断了四个情况:apnContext.isConnectable()----判断当前APN是否已经被激活;isEmergencyApn()----当前APN是否为紧急APN;isDataAllowed()----判断是否已经ATTACH成功,SIM是否初始化完毕,当前手机服务是否支持,漫游下是否允许上网等;getAnyDataEnabled()----该条件主要判断用户是否打开了数据开关;这四个条件我们主要来看最后一个,他里面包含用户数据开关的判断,我们来看一下详情,其中传递的参数checkUserDataEnabled受4G IMS的影响,由于国内暂时都没有部署IMS,因此这里的参数肯定都为true:[java] view plain copy mUserDataEnabled =Settings.Global.getInt( mPhone.getContext().getContentR esolver(), Settings.Global.MOBILE_DATA, 1) == 1;这说明他来自于Settings.Global.MOBILE_DATA这个属性值,而这个属性值恰恰就是当用户打开或关闭移动网络时所改变的属性值,当用户打开数据网络时,该值为1,关闭网络时,该值就是0。