Android7.0 Framework telephony中数据业务链接错误处理一般分3种情况:
1. SETUP_DATA_CALL 时返回错误
2. Modem上报DATA_CALL_LIST包含错误码或者链接中断
3. 一段时间内没有上下行数据(TX/RX)
下面以第一种情况为例分析:
通过DcTracker.setDataEnabled-->dcac.bringUp-->DataConnection.DcInactiveState.onConnect-->RILJ向MODEM发送SETUP_DATA_CALL的信令后,
由MODEM返回结果,逐层返回DcTracker中的case DctConstants.EVENT_DATA_SETUP_COMPLETE:
case DctConstants.EVENT_DATA_SETUP_COMPLETE:
onDataSetupComplete((AsyncResult) msg.obj);
/**
* A SETUP (aka bringUp) has completed, possibly with an error. If
* there is an error this method will call {@link #onDataSetupCompleteError}.
*/
private void onDataSetupComplete(AsyncResult ar) {
DcFailCause cause = DcFailCause.UNKNOWN;
boolean handleError = false;
ApnContext apnContext = getValidApnContext(ar, "onDataSetupComplete");
if (apnContext == null) return;
if (ar.exception == null) {
//链接成功
...
} else {
cause = (DcFailCause) (ar.result);
if (DBG) {
ApnSetting apn = apnContext.getApnSetting();
log(String.format("onDataSetupComplete: error apn=%s cause=%s",
(apn == null ? "unknown" : apn.apn), cause));
}
if (cause.isEventLoggable()) {
// Log this failure to the Event Logs.
int cid = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
cause.ordinal(), cid, TelephonyManager.getDefault().getNetworkType());
}
ApnSetting apn = apnContext.getApnSetting();
mPhone.notifyPreciseDataConnectionFailed(apnContext.getReason(),
apnContext.getApnType(), apn != null ? apn.apn : "unknown", cause.toString());
// Compose broadcast intent send to the specific carrier signaling receivers
Intent intent = new Intent(TelephonyIntents
.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED);
intent.putExtra(TelephonyIntents.EXTRA_ERROR_CODE_KEY, cause.getErrorCode());
intent.putExtra(TelephonyIntents.EXTRA_APN_TYPE_KEY, apnContext.getApnType());
mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent);
if (cause.isRestartRadioFail() || apnContext.restartOnError(cause.getErrorCode())) {
if (DBG) log("Modem restarted.");
sendRestartRadio();
}
// If the data call failure cause is a permanent failure, we mark the APN as permanent
// failed.
if (isPermanentFail(cause)) {
log("cause = " + cause + ", mark apn as permanent failed. apn = " + apn);
apnContext.markApnPermanentFailed(apn);
}
handleError = true;
}
if (handleError) {
//继续处理链接错误,有条件的重试
onDataSetupCompleteError(ar);
}
/* If flag is set to false after SETUP_DATA_CALL is invoked, we need
* to clean data connections.
*/
if (!mDataEnabledSettings.isInternalDataEnabled()) {
cleanUpAllConnections(Phone.REASON_DATA_DISABLED);
}
}
/**
* 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()}.
*/
private void onDataSetupCompleteError(AsyncResult ar) {
ApnContext apnContext = getValidApnContext(ar, "onDataSetupCompleteError");
if (apnContext == null) return;
long delay = apnContext.getDelayForNextApn(mFailFast);
// Check if we need to retry or not.
if (delay >= 0) {
if (DBG) log("onDataSetupCompleteError: Try next APN. delay = " + delay);
apnContext.setState(DctConstants.State.SCANNING);
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
//在delay时间后发起重试链接
startAlarmForReconnect(delay, apnContext);
} else {
// If we are not going to retry any APN, set this APN context to failed state.
// This would be the final state of a data connection.
apnContext.setState(DctConstants.State.FAILED);
mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
apnContext.setDataConnectionAc(null);
log("onDataSetupCompleteError: Stop retrying APNs.");
}
}
/**
* 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
}
Telephony基础之DataCall业务(网络重连)
最新推荐文章于 2022-08-27 18:49:12 发布