本文转自:http://blog.sina.com.cn/s/blog_40d475e901016t41.html
最近整理下启用数据和关闭数据连接的代码,将流程发出来,方便查看
下面是在真机上抓到的log,机器是锐合的X9,平台厂商是Marvell。(给公司打个广告)
通过log的TAG,相信各位很容易就找的到对应的源码文件,这里就不提供源码文件路径了
本文主要体现业务流程,具体函数功能就不详细介绍了,相信大家就是光看函数名也能猜到用途
D/GsmUmtsOptions( 1477): preferenceTreeClick: return false
D/NetworkSettings( 1477): onPreferenceTreeClick: preference == mButtonDataEnabled.
D/ConnectivityService( 1396): setMobileDataEnabled(false)
D/ConnectivityService( 1396): tearing down Mobile data state: CONNECTED
D/DataConnectionTracker( 1477): disableApnType(default)
D/DataConnectionTracker( 1477): setEnabled(0, false) with old state = true and enabledCount = 1
D/DataConnectionTracker( 1477): GSMDataConnTrack handleMessage { what=23 when=-30ms }
D/DataConnectionTracker( 1477): EVENT_APN_ENABLE_REQUEST 0, 0
D/DataConnectionTracker( 1477): dataEnabled = true, enabledCount = 1, isApnTypeActive = true
D/DataConnectionTracker( 1477): [GsmDataConnectionTracker] Clean up connection due to dataDisabled
D/DataConnectionTracker( 1477): [GsmDataConnectionTracker] cleanUpConnection: teardown, call conn.disconnect
D/GSM ( 1519): [GsmDataConnection-1] DcActiveState msg.what=EVENT_DISCONNECT
D/GSM ( 1519): [GsmDataConnection-1] tearDownData radio is on, call deactivateDataCall
D/RILJ ( 1519): [0100]> DEACTIVATE_DATA_CALL 1
下面就是data call的代码流程了,本文以去激活为例,即disable
1、在设置中取消“已启用数据”的选中状态
D/GsmUmtsOptions( 1477): preferenceTreeClick: return false
D/NetworkSettings( 1477): onPreferenceTreeClick: preference == mButtonDataEnabled.
cm.setMobileDataEnabled(mButtonDataEnabled.isChecked());
2、进入Framework了,如何从ConnectivityManager到ConnectivityService,请大家参考源码
D/ConnectivityService( 1396): setMobileDataEnabled(false)
public void setMobileDataEnabled(boolean enabled) {
enforceChangePermission();
if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
(enabled ? ENABLED : DISABLED), 0));
}
case EVENT_SET_MOBILE_DATA:
{
boolean enabled = (msg.arg1 == ENABLED);
handleSetMobileData(enabled);
break;
}
3、收到EVENT_SET_MOBILE_DATA消息,调用tear down
D/ConnectivityService( 1396): tearing down Mobile data state: CONNECTED
case EVENT_SET_MOBILE_DATA:
{
boolean enabled = (msg.arg1 == ENABLED);
handleSetMobileData(enabled);
break;
}
private void handleSetMobileData(boolean enabled) {
if (getMobileDataEnabled() == enabled) return;
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.MOBILE_DATA, enabled ? 1 : 0);
if (enabled) {
if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
if (DBG) {
Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
}
mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
}
if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
if (DBG) {
Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_WIMAX]);
}
mNetTrackers[ConnectivityManager.TYPE_WIMAX].reconnect();
}
} else {
for (NetworkStateTracker nt : mNetTrackers) {
if (nt == null) continue;
int netType = nt.getNetworkInfo().getType();
if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE && mNetAttributes[netType].isDefault()) {
if (DBG) Slog.d(TAG, "tearing down " + nt);
nt.teardown();
}
}
if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) {
mNetTrackers[ConnectivityManager.TYPE_WIMAX].teardown();
}
}
}
4、进入MobileDataStateTracker
public class MobileDataStateTracker extends NetworkStateTracker {
public boolean teardown() {
// since we won't get a notification currently (TODO - per APN notifications)
// we won't get a disconnect message until all APN's on the current connection's
// APN list are disabled. That means privateRoutes for DNS and such will remain on -
// not a problem since that's all shared with whatever other APN is still on, but
// ugly.
setTeardownRequested(true);
return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
}
private int setEnableApn(String apnType, boolean enable) {
getPhoneService(false);
for (int retry = 0; retry < 2; retry++) {
if (mPhoneService == null) {
Log.w(TAG,
"Ignoring feature request because could not acquire PhoneService");
break;
}
try {
if (enable) {
return mPhoneService.enableApnType(apnType);
} else {
return mPhoneService.disableApnType(apnType);
}
} catch (RemoteException e) {
if (retry == 0) getPhoneService(true);
}
}
Log.w(TAG, "Could not " + (enable ? "enable" : "disable")
+ " APN type "" + apnType + """);
return Phone.APN_REQUEST_FAILED;
}
}
5、进入DataConnectionTracker,从mPhoneService到PhoneBase,PhoneBase中调用DataConnectionTracker的disableApnType
D/DataConnectionTracker( 1477): disableApnType(default)
public synchronized int disableApnType(String type) {
if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
int id = apnTypeToId(type);
if (id == APN_INVALID_ID) {
return Phone.APN_REQUEST_FAILED;
}
if (isEnabled(id)) {
setEnabled(id, false);
return Phone.APN_REQUEST_STARTED;
} else {
return Phone.APN_REQUEST_FAILED;
}
}
6、发送EVENT_ENABLE_NEW_APN
D/DataConnectionTracker( 1477): setEnabled(0, false) with old state = true and enabledCount = 1
private void setEnabled(int id, boolean enable) {
if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " +
dataEnabled[id] + " and enabledCount = " + enabledCount[id]);
if(isApnTypeActive(apnIdToType(id))==false) {
enabledCount[id] = 0;
dataEnabled[id] = false;
}
Message msg = obtainMessage(EVENT_ENABLE_NEW_APN);
msg.arg1 = id;
msg.arg2 = (enable ? ENABLED : DISABLED);
sendMessage(msg);
}
7、处理EVENT_ENABLE_NEW_APN消息,调用onEnableApn,再调用onCleanUpConnection,再调用cleanUpConnection
D/DataConnectionTracker( 1477): GSMDataConnTrack handleMessage { what=23 when=-30ms }
case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2);
break;
D/DataConnectionTracker( 1477): EVENT_APN_ENABLE_REQUEST 0, 0
D/DataConnectionTracker( 1477): dataEnabled = true, enabledCount = 1, isApnTypeActive = true
protected synchronized void onEnableApn(int apnId, int enabled) {
if (DBG) {
Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled);
Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] +
", enabledCount = " + enabledCount[apnId] +
", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId)));
}
if (enabled == ENABLED) {
if (!dataEnabled[apnId]) {
dataEnabled[apnId] = true;
enabledCount[apnId] = 1;
} else {
enabledCount[apnId]++;
}
String type = apnIdToType(apnId);
if (enabledCount[apnId] == 1) { //first time to enable this apn
onEnableNewApn(apnId);
}
Log.d(LOG_TAG, "updated after enabled: dataEnabled = " + dataEnabled[apnId] +
", enabledCount = " + enabledCount[apnId] +
", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId)));
} else {
// disable
if (dataEnabled[apnId]) {
enabledCount[apnId] = 0;
dataEnabled[apnId] = false;
onCleanUpConnection(apnId, Phone.REASON_DATA_DISABLED);
}
Log.d(LOG_TAG, "updated after disabled: dataEnabled = " + dataEnabled[apnId] +
", enabledCount = " + enabledCount[apnId] +
", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId)));
}
}
protected void onCleanUpConnection(int apnId, String reason) {
cleanUpConnection(apnId, reason);
}
8、 调用disconnect
D/DataConnectionTracker( 1477): [GsmDataConnectionTracker] Clean up connection due to dataDisabled
D/DataConnectionTracker( 1477): [GsmDataConnectionTracker] cleanUpConnection: teardown, call conn.disconnect
private void cleanUpConnection(int apnId, String reason) {
if (DBG) log("Clean up connection due to " + reason);
if (perPdpState[apnId]== State.DISCONNECTING) {
if (DBG) log("cleanUpConnection: linda check State is Disconnecting, not set disconnecting again");
return;
}
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
if(mActivePdp[apnId] != null) {
setState(apnId,State.DISCONNECTING);
requestParams para = new requestParams(apnId, reason);
if(!isActivePdpShared(apnId)) {
if (DBG) log("cleanUpConnection: conn.disconnect");
removeFromActiveApnList(mActivePdp[apnId].getApn());
mActivePdp[apnId].disconnect(obtainMessage(EVENT_DISCONNECT_DONE, para));
mActivePdp[apnId] = null;
} else {
if (DBG) log("cleanUpConnection: conn is shared, don't disconnect it");
setState(apnId,State.IDLE);
mActivePdp[apnId] = null;
phone.notifyDataConnection(reason);
}
} else {
setState(apnId,State.IDLE);
phone.notifyDataConnection(reason);
}
}
9、发送消息EVENT_DISCONNECT,调用tearDownData,调用deactivateDataCall
D/GSM ( 1519): [GsmDataConnection-1] DcActiveState msg.what=EVENT_DISCONNECT
D/GSM ( 1519): [GsmDataConnection-1] tearDownData radio is on, call deactivateDataCall
public abstract class DataConnection extends HierarchicalStateMachine {
public void disconnect(Message onCompletedMsg) {
sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(onCompletedMsg)));
}
case EVENT_DISCONNECT:
if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT");
DisconnectParams dp = (DisconnectParams) msg.obj;
dp.tag = mTag;
tearDownData(dp);
transitionTo(mDisconnectingState);
retVal = true;
break;
private void tearDownData(Object o) {
if (phone.mCM.getRadioState().isOn()) {
if (DBG) log("tearDownData radio is on, call deactivateDataCall");
phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, o));
} else {
if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately");
AsyncResult ar = new AsyncResult(o, null, null);
sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, ar));
}
}
}
10、调用RIL的deactivateDataCall,发送原语RIL_REQUEST_DEACTIVATE_DATA_CALL
D/RILJ ( 1519): [0100]> DEACTIVATE_DATA_CALL 1
public final class RIL extends BaseCommands implements CommandsInterface {
public void
deactivateDataCall(int cid, Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DATA_CALL, result);
rr.mp.writeInt(1);
rr.mp.writeString(Integer.toString(cid));
if (RILJ_LOGD) riljLog(rr.serialString() + "> " +
requestToString(rr.mRequest) + " " + cid);
send(rr);
}
}
11、下面的流程就是各个厂商要实现的RIL部分,即AT命令实现部分了,这部分代码就不放上去了。