在之前的博客中,我们分析了数据业务长连接的拨号过程,现在我们来看看Android如何实现去拨号过程。
与拨号过程一样,用户也是通过点击设置界面,发起主动断开数据连接的命令。
从界面到框架,同样经过了CellDataPreference、TelephonyManager、PhoneInterfaceManager、GsmCdmaPhone和DcTracker的处理。去拨号和拨号调用的框架接口是一样的,只是参数不一致。
最终,从DcTracker的onSetUserDataEnabled函数开始,去拨号与拨号的流程产生了分歧:
1 DcTracker
//去拨号时参数为false
private void onSetUserDataEnabled(boolean enabled) {
synchronized (mDataEnabledLock) {
if (mUserDataEnabled != enabled) {
mUserDataEnabled = enabled;
//写数据库,某些情况下发送通知
..............
if (enabled) {
//进入拨号流程
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
//进入去拨号号流程
onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED);
}
}
}
}
private void onCleanUpAllConnections(String cause) {
cleanUpAllConnections(true, cause);
}
我们进一步看看cleanUpAllConnections:
private boolean cleanUpAllConnections(boolean tearDown, String reason) {
boolean didDisconnect = false;
boolean specificDisable = false;
if (!TextUtils.isEmpty(reason)) {
//主动拨号的reason为REASON_DATA_SPECIFIC_DISABLED,将specificDisable置为true
specificDisable = reason.equals(Phone.REASON_DATA_SPECIFIC_DISABLED) ||
reason.equals(Phone.REASON_ROAMING_ON);
}
for (ApnContext apnContext : mApnContexts.values()) {
//根据ApnContext中记录的状态,判断是否有未断开的连接
if (apnContext.isDisconnected() == false) didDisconnect = true;
//specificDisable的值为true
if (specificDisable) {
ApnSetting apnSetting = apnContext.getApnSetting();
//默认的数据拨号,均满足以下条件
//isMetered的返回值,由CarrierConfigManager中的配置决定,default类型将返回true
if (apnSetting != null && apnSetting.isMetered(mPhone.getContext(),
mPhone.getSubId(), mPhone.getServiceState().getDataRoaming())) {
apnContext.setReason(reason);
//进入断开连接的流程
cleanUpConnection(tearDown, apnContext);
}
} else {
............
}
}
//不再检测数据业务数据的收发的情况
//数据业务上下行图标消失
stopNetStatPoll();
//同样,不再检测数据业务是否仅发送无接收
stopDataStallAlarm();
..................
}
随着流程我们进入到cleanUpConnection:
private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
..............
//取出ApnContext中存储的DcTracker与DataConnection通信的AsyncChannel
DcAsyncChannel dcac = apnContext.getDcAc();
..............
if (tearDown) {
if (apnContext.isDisconnected()) {
............
} else {
if (dcac != null) {
if (apnContext.getState() != DctConstants.State.DISCONNECTING) {
...........