DataConnectionTracker:控制手机APN加载,数据连接;
包括:APN的创建,开机启动断开连接时,Radio状态改变时,Apn变化时,语音和数据业务切换时,
连接失败及自动重连时,漫游打开关闭时……这些情况下数据连接的处理;
对于CDMA和GSM两种网络通信技术,处理数据连接存在着一些差异,基本流程一致,下面看看CdmaDataConnectionTracker工作流程;
APN(Access Point Name),即“接入点名称”,用来标识GPRS的业务种类,目前分为两大类:CMWAP(通过GPRS访问WAP业务)、
CMNET(除了WAP以外的服务目前都用CMNET,比如连接因特网等)。是通过手机上网时必须配置的一个参数,它决定了您的手机通过哪种接入方式来访问网络。
业务流程GPRS专网系统终端上网登录服务器平台的流程为:
1)用户发出GPRS登录请求,请求中包括由移动公司为GPRS专网系统专门分配的专网APN;
2)根据请求中的APN,SGSN向DNS服务器发出查询请求,找到与企业服务器平台连接的GGSN,并将用户请求通过GTP隧道封装送给GGSN;
3)GGSN将用户认证信息(包括手机号码、用户账号、密码等)通过专线送至Radius进行认证;
4)Radius认证服务器看到手机号等认证信息,确认是合法用户发来的请求,向DHCP服务器请求分配用户地址;
5)Radius认证通过后,由Radius向GGSN发送携带用户地址的确认信息;
6)用户得到了IP地址,就可以携带数据包,对GPRS专网系统信息查询和业务处理平台进行访问。
CdmaDataConnectionTracker对象在创建的时候就会加载获取系统提供APN,CDMA中使用了专门的一个类CdmaDataProfileTracker来管理APN。
CdmaDataConnectionTracker(CDMAPhone p) { super(p); mDpt = new CdmaDataProfileTracker(p); mDpt.registerForModemProfileReady(this, EVENT_MODEM_DATA_PROFILE_READY, null); createAllDataConnectionList(); }
CdmaDataProfileTracker加载APN过程:
public void handleMessage (Message msg) { switch (msg.what) { case EVENT_LOAD_PROFILES: //从本机数据库加载
loadProfiles(); break; case EVENT_READ_MODEM_PROFILES: onReadDataProfilesFromModem(); break; case EVENT_GET_DATA_CALL_PROFILE_DONE: //当APN加载完发出通知
onGetDataCallProfileDone((AsyncResult) msg.obj, (int)msg.arg1); break; } }
具体加载过程可以到函数中去看,APN生成和查看问题可以参看这篇文章:
http://myqdroid.blog.51cto.com/2057579/389134
数据连接都会发送消息调用:
protected boolean onTrySetupData(String reason) {
return trySetupData(reason);
}
判断当前条件下是否可以满足并进行数据连接:
private boolean trySetupData(String reason) { //Wifi has been connected already, ignore default type data call setup.
if (FeatureQuery.FEATURE_CT_FMC_SUPPORT && mIsWifiConnected == true
&& mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) { setState(State.IDLE); if (dataEnabled[APN_DEFAULT_ID]) { dataEnabled[APN_DEFAULT_ID] = false; enabledCount--; } return false; } //满足条件则启动数据连接
if ((mState == State.IDLE || mState == State.SCANNING) && isDataAllowed() && getAnyDataEnabled() && !isEmergency()) { boolean retValue = setupData(reason); notifyOffApnsOfAvailability(reason); return retValue; } }
启动数据连接:
private boolean setupData(String reason) { CdmaDataConnection conn = findFreeDataConnection(); mPendingDataConnection = conn; mActiveApn = mDpt.getDataProfile(mRequestedApnType); //连接完成回调消息
Message msg = obtainMessage(); msg.what = EVENT_DATA_SETUP_COMPLETE; msg.obj = reason; conn.bringUp(msg, mActiveApn); setState(State.INITING); notifyDataConnection(reason); return true; }
数据连接是通过类DataConnection完成 ,看看DataConnection类结构图:
从这个相关类结构图可以看出:DataConnection是一个状态机,使用State模式,这样这个过程就能很清楚了;
解决数据连接过程中,对象内部状态的变化时,进行状态切换,执行不同的行为。
启动数据连接接口:
public void bringUp(Message onCompletedMsg, DataProfile apn) { sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg))); }
这里将消息发送给初始化状态进行处理:DcInactiveState
case EVENT_CONNECT: onConnect(cp); transitionTo(mActivatingState); break;
将会调用到CdmaDataConnection中进行connect:
protected void onConnect(ConnectionParams cp) { mApn = cp.apn; Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); msg.obj = cp;
//通过RIL启动数据连接
phone.mCM.setupDataCall( Integer.toString(getRilRadioTechnology(RILConstants.SETUP_DATA_TECH_CDMA)), Integer.toString(dataProfile), mApn.apn, mApn.user, mApn.password, Integer.toString(mApn.authType), mApn.protocol, msg); }
连接完成会发送EVENT_DATA_SETUP_COMPLETE回调消息到DataConnectionTracker:
case EVENT_DATA_SETUP_COMPLETE: mCidActive = msg.arg1; onDataSetupComplete((AsyncResult) msg.obj); break;
连接完成:
protected void onDataSetupComplete(AsyncResult ar) { if (isDataSetupCompleteOk(ar)) { DataProfileCdma mCurrentApn = (DataProfileCdma)mActiveApn; notifyDefaultData(reason); } else { startDelayedRetry(cause, reason, retryOverride); } }