数据连接过程
关键词:Android,GPRS, APN, Service,Client, Connection, Tracke
数据连接的整体框架简单如下图所示:
第一部分:UI 部分
用户发起数据流程的连接或断开,最终都是要将结果反馈给用户,让用户明白当前的数
据连接的状态。这部分一个主要的对象是 Settings 对象(com.android.phone.Settings),向
ConnectivityManager 发起数据连接请求。
1. Settings.java-> onPreferenceTreeClick():
public boolean onPreferenceTreeClick(…)
{
……
if (preference == mButtonDataEnabled)
{
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if (TelephonyManager.getPhoneCount() > 1)
{
cm.setMobileDataEnabledByPhoneId(mSubId, mButtonDataEnabled.isChecked()); //2
}
else
{
cm.setMobileDataEnabled(mButtonDataEnabled.isChecked());
}
return true;
}
……
}
第二部分:Mobile Data Service 部分
这部分是相当于数据业务的中转站了,向上响应用户的请求,向下向 telephony 派发用
户请求并处理来自 telephony 的状态变化。这里面很重要的对象,包括:
(1)ConnectivityService:ConnectivityManager 是它的客户端,两者通过著名的 binder 机制
进行通信,调用 ConnectivityManager 这里等同于调用到 ConnectivityService。
(2)MobileDataStateTracker,这是移动数据业务的"追踪器",又向 telephony 进行交互,它
的对象组合在 ConnectivityService 对象里面,当然 ConnectivityService 对象还管理着其它的
数据连接类型,包括 WifiStateTracker。
2. ConnectivityManager.java-> setMobileDataEnabledByPhoneId():
public void setMobileDataEnabledByPhoneId(int phoneId, boolean enabled)
{
try{
mService.setMobileDataEnabledByPhoneId(phoneId, enabled); //3
} catch (RemoteException e){
}
}
3. ConnectivityService.java-> setMobileDataEnabledByPhoneId():
private NetworkStateTracker mNetTrackers[];
public synchronized void setMobileDataEnabledByPhoneId(int phoneId, boolean enabled)
{
……
int defaultDataPhoneId = TelephonyManager.getDefaultDataPhoneId(mContext);
if (enabled)
{
if (phoneId == defaultDataPhoneId)
{
if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null)
{
mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect(); //4
}
}
}
else
{
……
}
}
由于 MobileDataStateTracker extends NetworkStateTracker,所以这里的 mNetTrackers 是
一个 MobileDataStateTracke,包含各种移动数据连接,包裹 MMS,SUPL,DUN。
4. MobileDataStateTracker.java-> reconnect():
public boolean reconnect()
{
……
switch (setEnableApn(mApnType, true)) //5
{
……
}
}
5. MobileDataStateTracker.java-> setEnableApn ():
private int setEnableApn(String apnType, boolean enable)
{
getPhoneService(false); //6
……
try {
if (enable)
{
return mPhoneService.enableApnType(apnType); //7
}
else
{
return mPhoneService.disableApnType(apnType);
}
} catch (RemoteException e) {
if (retry == 0) getPhoneService(true);
}
}
6. MobileDataStateTracker.java-> getPhoneService ():
mPhoneService 是电话的服务的客户端,它的 server 端实际上是 PhoneInterfaceManager
对象(com.android.phone.PhoneInterfaceManager),MobileDataStateTracker 通过如下方式调用
获取 ITelephony 接口的服务端。
private void getPhoneService(boolean forceRefresh)
{
mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService(PhoneFactory
.getServiceName("phone", getPhoneId())));
}
7. PhoneInterfaceManager.java-> enableApnType():
public int enableApnType(String type)
{
enforceModifyPermission();
return mPhone.enableApnType(type); //8
}
其中,mPhone 是 PhoneProxy 对象。这样,就将连接 apn 的请求发送到 telephony 框架
层下去了。apn 在设置应用里面有里面指定了,一般在工程目录下的 system/etc/apns-conf.xml
文件。
第三部分:Telephony 部分
8. PhoneProxy.java-> enableApnType():
public int enableApnType(String type)
{
return mActivePhone.enableApnType(type); //9
}
其中,mActivePhone 是 GSMPhone 或者 CDMAPhone 的上溯接口 PhoneBase 对象。
9.PhoneBase.java-> enableApnType():
public DataConnectionTracker mDataConnection;
public int enableApnType(String type)
{
return mDataConnection.enableApnType(type); //10
}
10. DataConnectionTracker.java-> enableApnType():
public synchronized int enableApnType(String type)
{
……
setEnabled(id, true); //11
……
}
11. DataConnectionTracker.java-> setEnabled ():
protected void setEnabled(int id, boolean enable)
{
Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
msg.arg1 = id;
msg.arg2 = (enable ? ENABLED : DISABLED);
sendMessage(msg); //12
}
12. DataConnectionTracker.java-> handleMessage ():
public void handleMessage (Message msg)
{
switch (msg.what)
{
case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2); //13
break;
……
}
}
13. DataConnectionTracker.java-> onEnableApn():
protected synchronized void onEnableApn(int apnId, int enabled)
{
……
onEnableNewApn(); //14
……
}
onEnableNewApn()方法在 DataConnectionTracker 的派生类 GsmDataConnectionTracker
和 CdmaDataConnectionTracker 中实现,从而区别不同类型 PHONE 的数据连接流程。以 GSM
为例。
14. GsmDataConnectionTracker.java->onEnableNewApn():
protected void onEnableNewApn()
{
……
cleanUpConnection(true, Phone.REASON_APN_SWITCHED); //15
……
}
15. GsmDataConnectionTracker.java-> cleanUpConnection ():
protected ArrayList pdpList;
protected void cleanUpConnection(boolean tearDown, String reason)
{
……
for (DataConnection conn : pdpList)
{
……
conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE, reason)); //16
……
}
……
}
conn 是 DataConnection 对象,标识一种数据连接,可以看出这里实际上实现了一个数
据连接的状态机。在 DataConnection 对象里面数据连接的状态分为以下几种:
DcDefaultState,默认状态。
DcInactiveState,非激活状态。
DcActivatingState,正在激活状态
DcActiveState,激活状态
DcDisconnectingState,正在断开状态
DcDisconnectingBadDnsState,断开状态(因为错误的 DNS)
状态转换如下图所示:
而动态图如下图所示:
数据连接包含几种状态,构造函数里面必须添加这几种状态,并且指定一个初始状态,
根据 DataConnection 类的构造函数:
DataConnection.java-> DataConnection():
protected DataConnection(PhoneBase phone, String name)
{
……
clearSettings();
setDbg(false);
addState(mDefaultState);
addState(mInactiveState, mDefaultState);
addState(mActivatingState, mDefaultState);
addState(mActiveState, mDefaultState);
addState(mDisconnectingState, mDefaultState);
addState(mDisconnectingBadDnsState, mDefaultState);
setInitialState(mInactiveState); //
}
设置初始化状态为 mInactiveState,意思是未激活的连接。
private DcInactiveState mInactiveState = new DcInactiveState();
所有的状态类都是继承自 HierarchicalState,例如:
private class DcInactiveState extends HierarchicalState