拨号失败重试流程

本文主要分析了拨号失败的重试流程,包括延迟多长时间重试,根据modem建议的返回时间和配置项确定延迟;使用什么apn重试,根据retry值和最大重试次数决定用相同或下一个APN;还探讨了重试和普通正常拨号的区别,主要体现在APN状态和RetryManager设置上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看下拨号失败流程是如何的

1、延迟多长时间重试?

//相关Log
Line 67380: 068195 06-06 08:53:10.952  1760  1885 D RILJ    : [6812]> SETUP_DATA_CALL,radioTechnology=14,isRoaming=false,allowRoaming=false,DataProfile=0/spmode.ne.jp/IPV4V6/0///0/0/0/0/true/1/IPV4V6/0/0///false [SUB0]
Line 67537: 0685C0 06-06 08:53:12.855  1760  1794 D RilRequest: [6812]< SETUP_DATA_CALL error: com.android.internal.telephony.CommandException: GENERIC_FAILURE ret
=DataCallResponse: { status=65535 retry=-1 cid=-1 active=-1 type= ifname= mtu=0 addresses=[] dnses=[] gateways=[] pcscf=[]}

第9步记录了modem建议的返回时间,第15取相关时间重试

如果为如果retry >0小于最大整形,就用retry值作为delay,如果retry < 0,则使用配置项和随机数组合
private long getSuggestedRetryDelay(DataCallResponse response) {
    /** According to ril.h
     * The value < 0 means no value is suggested
     * The value 0 means retry should be done ASAP.
     * The value of Integer.MAX_VALUE(0x7fffffff) means no retry.
     */

    // The value < 0 means no value is suggested
    if (response.getSuggestedRetryTime() < 0) {

 return RetryManager.NO_SUGGESTED_RETRY_DELAY;
}
// The value of Integer.MAX_VALUE(0x7fffffff) means no retry.
 else if (response.getSuggestedRetryTime() == Integer.MAX_VALUE) {
if (DBG) log("Modem suggested not retrying.");
return RetryManager.NO_RETRY;
}

// We need to cast it to long because the value returned from RIL is a 32-bit integer,
 // but the time values used in AlarmManager are all 64-bit long.
 return (long) response.getSuggestedRetryTime();
}
Line 67110: 067E2C 06-06 08:53:10.586  1760  1760 D RetryManager: [default] Setting 1 waiting APNs.
Line 67588: 06863C 06-06 08:53:12.976  1760  1760 D RetryManager: [default] getRetryTimer: 5625

//定时器重试Line 67590: 06863E 06-06 08:53:12.977  1760  1760 D DCT     : [0]startAlarmForReconnect: delay=5625 action=com.android.internal.telephony.data-reconnect.default apn={mApnType=default mState=SCANNING mWaitingApns={[[ApnSettingV3] sp-mode, 2550, 44010, spmode.ne.jp, , , , , , 0, default, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false]} mApnSetting={[ApnSettingV3] sp-mode, 2550, 44010, spmode.ne.jp, , , , , , 0, default, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false} mReason=dataEnabled mDataEnabled=true mDependencyMet=true}

2、使用什么apn重试?

   当Dctracker发起定时器广播后, 最终调到Dctracker中的setupData函数, 在setupData函数中,APN轮询为如下函数
apnContext.getNextApnSetting(); 最后调到RetryManager中的getNextApnSetting
public ApnSetting getNextApnSetting() {

    if (mWaitingApns == null || mWaitingApns.size() == 0) {
        log("Waiting APN list is null or empty.");
        return null;
    }

    // If the modem had suggested a retry delay, we should retry the current APN again
    // (up to MAX_SAME_APN_RETRY times) instead of getting the next APN setting from
    // our own list.
    // 如果modem有建议delay的时间,并且相同APN的重试小于最大次数,则使用相同APN重试
    if (mModemSuggestedDelay != NO_SUGGESTED_RETRY_DELAY &&
            mSameApnRetryCount < MAX_SAME_APN_RETRY) {
        mSameApnRetryCount++;
        return mWaitingApns.get(mCurrentApnIndex);
    }


mSameApnRetryCount = 0;

int index = mCurrentApnIndex;
// Loop through the APN list to find out the index of next non-permanent failed APN.
 while (true) {
if (++index == mWaitingApns.size()) index = 0;

// Stop if we find the non-failed APN.
 if (mWaitingApns.get(index).permanentFailed == false) break;

// If we've already cycled through all the APNs, that means there is no APN we can try
 if (index == mCurrentApnIndex) return null;
}

mCurrentApnIndex = index;
  //使用下一个APN重试
return mWaitingApns.get(mCurrentApnIndex);
}

简单一点如果Log中retry>0 且重试次数< 最大重试次数MAX_SAME_APN_RETRY 则使用相同的APN重试,否则轮询使用其他的 APN


3、重试和普通正常拨号的区别在什么地方?

拨号的函数最后都会调到setupData,如何区分是否重试拨号还是非重试拨号呢? 排查代码分析如下
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状态变成了SCANNING状态
        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(delay, apnContext);

 

在trySetupData中函数中,如果APN状态是DctConstants.State.IDLE状态,重设waitingApn,此逻辑会清空RetryManager的中设置,而拨号失败重试为SCANNING状态,不会清空RetryManager的中设置,因此使用的apn就不一样了
if (apnContext.getState() == DctConstants.State.IDLE) {
    if (waitingApns == null) {
        waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);
    }
    if (waitingApns.isEmpty()) {
        notifyNoData(DcFailCause.MISSING_UNKNOWN_APN, apnContext);
        notifyOffApnsOfAvailability(apnContext.getReason());
        String str = "trySetupData: X No APN found retValue=false";
        if (DBG) log(str);
        apnContext.requestLog(str);
        return false;
    } else {
        apnContext.setWaitingApns(waitingApns);
        if (DBG) {
            log ("trySetupData: Create from mAllApnSettings : "
                        + apnListToString(mAllApnSettings));
        }
    }
}

boolean retValue = setupData(apnContext, radioTech);

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值