Bug Fixed--Android N Data Call Retry 时间间隔不能有效增加

2018-02-27 11:24:16来源:oschina作者:遇逆境-处之泰然人点击

分享
0. 相关文档链接

Android 6.0 与 Android 7.0 Data Call Retry对比


Android N Data Call流程(准备中...)


1. 关键术语Data call:移动通讯的业务种类分语音业务和数据业务,数据业务包含除移动通讯CS域语音业务外的其他业务,以数据传输和信息交互为技术的移动通讯业务,所有的数据业务必须在data call建立的基础上才可以实施;

APN:(Access Point Name,接入点)一种网络接入技术,是手机上网时必须配置的一个参数,它决定了手机通过哪种接入方式来访问网络。APN的完整说明在3GPP规范TS23.003 Clause 9中进行了详细定义;


PDN:(Public Data Network,公用数据网)一种由电信运营商组建的广域网,提供接入广域网的服务与技术,为用户提供高质量数据传输服务;


DcTracker.java:Android操作系统中Telephony框架中负责数据业务的核心,所有对数据网络的请求(打开关闭数据开关、切换数据卡、修改APN参数等)都会发送到该处理中心进行处理;


RetryManager.java:用于data call激活失败后的重试管理,判断重试的必要性以及配置重试的参数等;


ApnContext:提供数据连接的APN上下文,每一个APN类型都对应一个ApnContext的对象,ApnContext的对象维护对应的APN设置;


IMS:(IP Multimedia Subsystem,IP多媒体子系统)一种全新的多媒体业务形式,它能够满足现在的终端客户更新颖、更多样化多媒体业务的需求。

2. Bug产生原因

Android 7.0在DcTracker中建立data call时,会先判断当前手机是否支持单PDN,如果不支持单PDN,在这种情况下,如果data call建立失败后重试时间间隔则会满足系统要求;如果手机支持单PDN,此时会清除所有非断开状态的PDN连接,在所有连接断开后,会等待20秒去重试建立data call,在重试建立data call过程中,由于请求建立的data call连接也被清除,所以其对应的ApnContext状态变成IDLE状态,重试管理类RetryManager会初始化配置相应的参数,每次重试的时间间隔均为数组的第一个取值。



图1流程解释如下:

手机数据业务开关打开后,检查建立data call条件,由于此时请求连接的ApnContext对象的状态为IDLE,所以在建立data call前会调用RetryManager来初始化重试连接的相关参数,比如时间间隔、是否永久重试等,Android默认的重试时间间隔为:5000,10000,20000,40000,…, 1800000:5000(单位:ms,重试的时间间隔会在此上加0-2000ms的随机数);
第一次建立data call时,由于所有的ApnContext对象的状态均为IDLE,所以手机支持单PDN情况下,不会执行清除所有连接的操作,并且会发出EVENT_CONNECT消息去建立data call;
如果在建立data call失败后,会发出EVENT_DATA_SETUP_COMPLETE_ERROR消息,DcTracker会接收到该消息并进行处理;
DcTracker在处理EVENT_DATA_SETUP_COMPLETE_ERROR时,会将请求连接的ApnContext对象的状态由CONNECTING变成SCANNING,并从RetryManager中获取重试的时间间隔,并利用该时间间隔重试建立data call;
由于此时手机是支持单PDN连接,而当前请求连接的ApnContext的状态为SCANNING,该连接为非断开的连接,按照原生逻辑,会清除该连接,将此ApnContext的状态由SCANNING变成IDLE,完成该流程后,会等待20秒的时间再次重试建立data call;
在重试建立data call时,由于请求连接的ApnContext的状态为IDLE,又会再次通过RetryManager初始化重试的相关参数,这样会导致接下来的data call重试时间取值又为数组的第一个值,即5000ms,因此此后的每一次重试建立data call的时间都是相同的,不符合Android的需求;
如果data call一直没有建立成功,则会重复上述的过程。

抓取的原生log如下表所示:


01-01 09:09:34.440 D/RILJ ( 1715): [3806]> SETUP_DATA_CALL 11 0 test.net 0 IP [SUB0]
01-01 09:09:38.269 D/RILJ ( 1715): [3806]< SETUP_DATA_CALL DataCallResponse: {version=11 status=19
01-01 09:09:38.271 D/DC-1 ( 1715): DcActivatingState onSetupConnectionCompleted result=ERR_RilError
01-01 09:09:38.278 D/QtiGsmDCT( 1715): [0]getValidApnContext (onDataSetupCompleteError) on {mApnType=default mState=CONNECTING
//第一次失败后,尝试重新建立data call,时间为5s+2s的随机数
01-01 09:09:38.278 D/RetryManager( 1715): [default] getRetryTimer: 6680
01-01 09:09:38.278 D/QtiGsmDCT( 1715): [0]onDataSetupCompleteError: Try next APN. delay = 6680
01-01 09:09:44.962 D/QtiGsmDCT( 1715): [0]onActionIntentReconnectAlarm: mState=IDLE
reason=SinglePdnArbitration
01-01 09:09:44.962 D/QtiGsmDCT( 1715): [0]onActionIntentReconnectAlarm: apnContext state=SCANNING
01-01 09:09:44.965 D/QtiGsmDCT( 1715): [0]setupData: apnContext={mApnType=default mState=SCANNING7
01-01 09:09:44.966 D/QtiGsmDCT( 1715): [0]cleanUpAllConnections: tearDown=true reason=SinglePdnArbitration
01-01 09:09:44.967 D/QtiGsmDCT( 1715): [0]cleanUpConnection: tearing down using gen#1apnContext={
01-01 09:09:44.968 D/DCT ( 1715): DataConnectionAc tearDown: apnContext={mApnType=default mState=SCANNING
01-01 09:09:44.969 D/DC-1 ( 1715): DcInactiveState: msg.what=EVENT_DISCONNECT
01-01 09:09:44.970 D/QtiGsmDCT( 1715): [0]setupData: Some calls are disconnecting first. Wait and retry
01-01 09:09:44.998 D/QtiGsmDCT( 1715): [0]onDisconnectDone: attached, ready and retry after disconnect
01-01 09:09:44.999 D/QtiGsmDCT( 1715): [0]startAlarmForReconnect: delay=20000 action=com.android.
01-01 09:10:05.006 D/QtiGsmDCT( 1715): [0]onActionIntentReconnectAlarm: mState=IDLE
reason=SinglePdnArbitration
01-01 09:10:05.006 D/QtiGsmDCT( 1715): [0]onActionIntentReconnectAlarm: apnContext state=IDLE
//又重新初始化Retry时间的配置,所以每次时间都是一样的
01-01 09:10:05.010 D/QtiGsmDCT( 1715): [0]trySetupData for type:default due to SinglePdnArbitration,
mIsPsRestricted=false
01-01 09:10:05.019 D/QtiGsmDCT( 1715): [0]buildWaitingApns: X added preferred apnList=[[ApnSettingV3] test,
01-01 09:10:05.022 D/RetryManager( 1715): [default] configure:
'default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,320000:5000,640000:5000,1280000:
5000,1800000:5000'01-01 09:10:05.027 D/QtiGsmDCT( 1715): [0]setupData: Single pdp. Continue setting up data call.

基于以上分析,Android原生在手机支持单PDN连接时,建立data call失败后重试连接存在着一些不足。在建立data call失败后,请求连接的ApnContext状态会设定成SCANNING,在单PDN情况下,它是一种非断开的状态,所以该连接会被清除掉。


3. Bug修复思路

在清除所有PDN连接时,不清除请求连接的PDN。在建立data call时,由于手机支持单PDN,在清除所有PDN连接之前,首先遍历所有的ApnContext,将请求连接的ApnContext自身以及IMS类型的ApnContext排除,检查其他的ApnContext状态,如果存在其他非断开状态的PDN连接,才会清除这些PDN连接。



图2流程解释如下:

手机数据业务开关打开后,检查建立data call条件,由于此时请求连接的ApnContext对象的状态为IDLE,所以在建立data call前会调用RetryManager来初始化重试连接时的相关参数;
第一次建立data call时,由于所有的ApnContext对象的状态均为IDLE,所以手机支持单PDN情况下,不会执行清除所有连接的操作,并且会发出EVENT_CONNECT消息会建立data call;
如果建立data call失败后,会发出EVENT_DATA_SETUP_COMPLETE_ERROR消息,DcTracker会接收到该消息并进行处理;
DcTracker在处理EVENT_DATA_SETUP_COMPLETE_ERROR时,会将请求连接的ApnContext对象的状态由CONNECTING变成SCANNING,并从RetryManager中获取重试的时间间隔,并利用该时间间隔重试建立data call;
当手机支持单PDN时,首先遍历所有类型的ApnContext,如果是请求的ApnContext或者IMS类型的ApnContext,则不执行任何操作;如果是其他类型的ApnContext,那么会判断这些连接是否为非断开状态,根据状态决定是否进行清除操作;
由于请求连接的ApnContext没有被清除,那么会按照系统配置的时间间隔去重试建立data call。

修改后的log:


10-24 14:15:05.296 D/DC-1 ( 2663): DcActivatingState onSetupConnectionCompleted result=ERR_RilError
10-24 14:15:05.310 D/RetryManager( 2663): [default] getRetryTimer: 5743
10-24 14:15:05.310 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=5743 action=com.android.
10-24 14:15:11.063 D/QtiGsmDCT( 2663): [0]setupData: Single pdp. Continue setting up data call.
10-24 14:15:11.074 D/QtiGsmDCT( 2663): [0]setupData: initing!
10-24 14:15:11.076 D/RILJ ( 2663): [3979]> SETUP_DATA_CALL 3 0 fourgsmartphone.v6 2 IPV4V6 [SUB0]10
10-24 14:15:13.673 D/RILJ ( 2663): [3979]< SETUP_DATA_CALL DataCallResponse: {version=11 status=19
10-24 14:15:13.683 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=10236 action=
10-24 14:15:26.530 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=21890 action=
10-24 14:15:51.350 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=40164 action=
10-24 14:16:34.304 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=84040 action=
10-24 14:18:01.477 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=160160 action=
10-24 14:20:44.474 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=321645 action=
10-24 14:26:09.057 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=641835 action=
10-24 14:36:53.543 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=1280610 action=
10-24 14:58:16.692 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=1804329 action=
10-24 15:28:24.139 D/QtiGsmDCT( 2663): [0]startAlarmForReconnect: delay=3603251 action=

修改后的流程和原生的主要区别是,在手机支持单PDN时,需要清除所有的连接,在这个操作之前,先判断是否是请求连接的PDN本身,以及判断是否存在其他非断开的连接需要断开,这样就能够保证请求连接的PDN不会被清除。


-------------------------------------------------------------------------------------------------------------


如果需要相关修改代码,请联系我!

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台