一 DataConnectionTracker
DataConnectionTracker:控制手机APN加载,数据连接;
包括:APN的创建,开机启动断开连接时,Radio状态改变时,Apn变化时,语音和数据业务切换时,
连接失败及自动重连时,漫游打开关闭时……这些情况下数据连接的处理;
对于CDMA和GSM两种网络通信技术,处理数据连接存在着一些差异,基本流程一致,下面看看CdmaDataConnectionTracker工作流程;
二 APN加载
1 APN概念
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专网系统信息查询和业务处理平台进行访问。
2 APN创建
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
二 数据连接流程
1 开始数据连接
数据连接都会发送消息调用:
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;
}
2 数据连接过程
数据连接是通过类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);
}
}