Android 6.0 Framework telephony中数据业务链接错误处理一般分3种情况:
1. SETUP_DATA_CALL 时返回错误
2. Modem上报DATA_CALL_LIST包含错误码或者链接中断
3. 一段时间内没有上下行数据(TX/RX)
下面具体来看每种情况的处理。
1. SETUP_DATA_CALL失败
DataConnection在收到SETUP_DATA_CALL结果后,用Message通知DcTracker处理:
protected void onDataSetupComplete(AsyncResult ar) {
if (ar.exception == null) {
//链接成功
}else{
...
//标记permanent fail的次数,会影响后面onDataSetupCompleteError的判断
if (isPermanentFail(cause)) apnContext.decWaitingApnsPermFailCount();
apnContext.removeWaitingApn(apnContext.getApnSetting()); //从waiting列表中移除已经失败的APN
onDataSetupCompleteError(ar);//继续处理错误
...
}
}
1. 如果apnContext中的所有waiting APN都失败了,且不是每个都发生permanent fail(永久性错误),则设置delay并重新发起这次连接
2. 如果apnContext中仍有没有尝试的waiting APN,则设置delay并尝试用下一个APN去连接
/**
* Error has occurred during the SETUP {aka bringUP} request and the DCT
* should either try the next waiting APN or start over from the
* beginning if the list is empty. Between each SETUP request there will
* be a delay defined by {@link #getApnDelay()}.
*/
@Override
protected void onDataSetupCompleteError(AsyncResult ar) {
String reason = "";
ApnContext apnContext = getValidApnContext(ar, "onDataSetupCompleteError");
if (apnContext == null) return;
//已经尝试过所有APN
if (apnContext.getWaitingApns().isEmpty()) {
apnContext.setState(DctConstants.State.FAILED);//apnContext state设置成FAILED
mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
//清除DataConnection
apnContext.setDataConnectionAc(null);
//如果所有APN都发生Permanent fail,则不做重试
if (apnContext.getWaitingApnsPermFailCount() == 0) {
if (DBG) {
log("onDataSetupCompleteError: All APN's had permanent failures, stop retrying");
}
} else {
//执行重试
int delay = getApnDelay(Phone.REASON_APN_FAILED);
if (DBG) {
log("onDataSetupCompleteError: Not all APN's had permanent failures delay="
+ delay);
}
startAlarmForRestartTrySetup(delay, apnContext);
}
} else {
//waitingAPN中还有没有尝试的APN,继续尝试下一个
if (DBG) log("onDataSetupCompleteError: Try next APN");
apnContext.setState(DctConstants.State.SCANNING);
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
startAlarmForReconnect(getApnDelay(Phone.REASON_APN_FAILED), apnContext);//试下一个APN
}
}
附:ApnContext的所有状态
/**
* IDLE: ready to start data connection setup, default state
* CONNECTING: state of issued startPppd() but not finish yet
* SCANNING: data connection fails with one apn but other apns are available
* ready to start data connection on other apns (before INITING)
* CONNECTED: IP connection is setup
* DISCONNECTING: Connection.disconnect() has been called, but PDP
* context is not yet deactivated
* FAILED: data connection fail for all apns settings
* RETRYING: data connection failed but we're going to retry.
*
* getDataConnectionState() maps State to DataState
* FAILED or IDLE : DISCONNECTED
* RETRYING or CONNECTING or SCANNING: CONNECTING
* CONNECTED : CONNECTED or DISCONNECTING
*/
public enum State {
IDLE,
CONNECTING,
SCANNING,
CONNECTED,
DISCONNECTING,
FAILED,
RETRYING
}