Android 关机时的radio相关关闭流程

针对插单卡,开数据业务情况下radio关机流程分析。

先贴一下ShutdownThread的log:

05-24 03:48:17.226  1354  1354 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
05-24 03:48:17.298  1354  4205 I ShutdownThread: Sending shutdown broadcast...
05-24 03:48:17.422  1354  4205 I ShutdownThread: Shutting down activity manager...
05-24 03:48:17.500  1354  4205 I ShutdownThread: Shutting down package manager...
05-24 03:48:17.511  1354  4213 W ShutdownThread: Turning off cellular radios...
05-24 03:48:17.516  1354  4213 I ShutdownThread: Waiting for Radio...
05-24 03:48:18.422  1354  4213 I ShutdownThread: Radio turned off.
05-24 03:48:18.422  1354  4213 I ShutdownThread: Radio shutdown complete.
05-24 03:48:19.226  1354  4205 I ShutdownThread: Shutdown critical subsyslist is :modem : 
05-24 03:48:19.226  1354  4205 I ShutdownThread: Waiting for a maximum of 10000ms
05-24 03:48:19.227  1354  4205 I ShutdownThread: Vendor subsystem(s) shutdown successful
05-24 03:48:19.734  1354  4205 I ShutdownThread: Performing low-level shutdown...

每一步的耗时时间:

05-24 03:48:17.422  1354  4205 D ShutdownTiming: SendShutdownBroadcast took to complete: 124ms
05-24 03:48:17.500  1354  4205 D ShutdownTiming: ShutdownActivityManager took to complete: 77ms
05-24 03:48:17.509  1354  4205 D ShutdownTiming: ShutdownPackageManager took to complete: 9ms
05-24 03:48:18.422  1354  4213 D ShutdownTiming: ShutdownRadio took to complete: 911ms
05-24 03:48:18.422  1354  4205 D ShutdownTiming: ShutdownRadios took to complete: 914ms
//在rebootorShutdown函数前的每一步耗时
05-24 03:48:18.422  1354  4205 D ShutdownTiming: SystemServerShutdown took to complete: 1133ms

ShutdownThread.shutdown()

Notifying thread to start shutdown longPressBehavior=1 打印出现在shutdownInner函数中。当重启或关机时会分别触发shutdown或reboot函数。最终都会走到shutdownInner函数。shutdownInner函数会触发ShutdownThread 中static实例的start函数。因为其继承自thread,所以会触发run函数。

关机画面

shutdownInner中调用beginShutdownSequence
确保此函数只进入一次。Android 关机时的radio相关关闭流程_第1张图片
接着调用showShutdwonDialog()判断是否去显示关机动画。
在这里插入图片描述
然后触发ShutdownThread.run()

在这里插入图片描述

ShutdownThread.run()

发送广播

Android 关机时的radio相关关闭流程_第2张图片
注意其在调用sendOrderedBraodcastAsUser的参数br,即在发送广播的同时,br会成为此广播的最后一个接受者。br的作用是为了确保所有上层应用都收到关机广播再走下面的流程。

等待广播发送完毕

br最后收到广播,将mActionDone设置为true。 run函数中轮询mActionDone,为true时退出,走下面的流程。
在这里插入图片描述
在这里插入图片描述

Android 关机时的radio相关关闭流程_第3张图片

关闭ActivityManager和PackageManager

Android 关机时的radio相关关闭流程_第4张图片

关闭radio

调用shutdownRadio函数
在这里插入图片描述
shutdownRadio函数启动一个thread执行关闭radio的操作。

shutdownRadio

首先判断radio是否需要shutdown,若是则调用phone.shutdownMobileRadios来关闭radio。
在这里插入图片描述
然后轮询needMobileRadioShutdown()状态。如果radiooff则走下一步。
Android 关机时的radio相关关闭流程_第5张图片

关闭radio

接下来针对关闭radio 重点分析一下流程。

判断是否需要关闭radio

Android 关机时的radio相关关闭流程_第6张图片

Android 关机时的radio相关关闭流程_第7张图片
Android 关机时的radio相关关闭流程_第8张图片
Android 关机时的radio相关关闭流程_第9张图片
从上面截图可以知道,就是判断RIL.java的mState变量值。如果是RADIO_UNAVAILABLE则认为不需要关机,否则需要关机。

mState状态如何转变为UNAVAILABLE

有两个情况会变为UNAVAILBALBE:

radioIndication.java 被通知radioStateChanged时

Android 关机时的radio相关关闭流程_第10张图片
对应log:

05-24 03:48:19.179  2128  2287 D RILJ    : [UNSL]< UNSOL_RESPONSE_RADIO_STATE_CHANGED radioStateChanged: RADIO_UNAVAILABLE [SUB0]
05-24 03:48:19.184  2128  2287 D RILJ    : [UNSL]< UNSOL_RESPONSE_RADIO_STATE_CHANGED radioStateChanged: RADIO_UNAVAILABLE [SUB1]

RIL_REQUEST_SHUTDOWN请求返回时

详细流程如下:
RILC 返回response时通过RadioResponse的对应接口返回。
对应RIL_REQUEST_SHUTDOWN是requestShutdownResponse().
Android 关机时的radio相关关闭流程_第11张图片
Android 关机时的radio相关关闭流程_第12张图片
在responseVoid函数中,先通过RIL.java的processResponse做一些处理。
然后通过sendMessageResponse通知AP上层的发送方,命令执行情况。
最后通过processResponseDone来打印收到的response信息。
Android 关机时的radio相关关闭流程_第13张图片
Android 关机时的radio相关关闭流程_第14张图片
对应log:

05-24 03:48:18.120  2128  2128 D RILJ    : [4151]> RIL_REQUEST_SHUTDOWN [SUB1]
05-24 03:48:18.124  2128  2128 D RILJ    : [4152]> RIL_REQUEST_SHUTDOWN [SUB1]
05-24 03:48:18.134  2128  2287 D RILJ    : [4151]< RIL_REQUEST_SHUTDOWN  [SUB1]
05-24 03:48:18.149  2128  2287 D RILJ    : [4152]< RIL_REQUEST_SHUTDOWN  [SUB1]
05-24 03:48:18.212  2128  2128 D RILJ    : [4153]> RIL_REQUEST_SHUTDOWN [SUB0]
05-24 03:48:18.214  2128  2128 D RILJ    : [4154]> RIL_REQUEST_SHUTDOWN [SUB0]
05-24 03:48:18.374  2128  2287 D RILJ    : [4153]< RIL_REQUEST_SHUTDOWN  [SUB0]
05-24 03:48:19.108  2128  2287 D RILJ    : [4154]< RIL_REQUEST_SHUTDOWN  [SUB0]

关闭radio

Android 关机时的radio相关关闭流程_第15张图片

Android 关机时的radio相关关闭流程_第16张图片
在这里插入图片描述

Android 关机时的radio相关关闭流程_第17张图片

Android 关机时的radio相关关闭流程_第18张图片
对应log:

05-24 03:48:17.513   SST   : [0] mDeviceShuttingDown=true, mDesiredPowerState=false, getRadioState=RADIO_ON, mPowerOffDelayNeed=true, mAlarmSwitch=false, mRadioDisabledByCarrier=false
05-24 03:48:17.515   SST   : [1] mDeviceShuttingDown=true, mDesiredPowerState=false, getRadioState=RADIO_ON, mPowerOffDelayNeed=true, mAlarmSwitch=false, mRadioDisabledByCarrier=false

当插单卡,开数据业务,接着调用poweOffRadioSafely()

开数据业务情况下poweOffRadioSafely流程

Android 关机时的radio相关关闭流程_第19张图片
调用流程如下:
ShutDownThread.shutdownRadios()-》phone.shutdownMobileRadios (ITelephone–>PhoneInterfaceManager)->PhoneInterfaceManager.shutdownRadiosUsingID()->Phone.shutdownRadio()->ServiceStateTracker.requestShutDown()->setPowerStateToDesired()->powerOffRadioSafely->DcTracker.clearUpAllConnections() 同事registerForAllDataDisconnected(EVENT_All_DATA_DISCONNECTED)

即使 插单卡,只要有数据业务,两个sub都会调用dcTracker.cleanUpAllConnections()。 无卡的那个sub还会关注EVENT_All_DATA_DISCONNECTED。
在cleanUpAllConnections()中,针对每一个APN调用一次cleanUpConnection。mDisconnectPendingCount 在cleanUpConnection ()中会自加1.
Android 关机时的radio相关关闭流程_第20张图片
cleanUpConnection 中tearDown apn。 mDisconnectPendingCount 自加1. 关闭成功后收到EVENT_DISCONNECT_DONE.
Android 关机时的radio相关关闭流程_第21张图片
无卡sub 的cleanUpAllConnections中,直接调用notifyAllDataDisconnected().
数据业务sub data断开后触发onDisconnectDone,mDisconnectPendingCount 减1至0后,也调用notifyAllDataDisconnected。

数据业务卡是在onDisconnectDone中触发processPendingRadioPowerOffAfterDataOff().进而调用hangupAndPowerOff。
非数据业务卡,或无卡sub,在SST(serviceStateTracker) 处理EVENT_ALL_DATA_DISCONNTECD时调用hangupAndPowerOff
Android 关机时的radio相关关闭流程_第22张图片
无卡sub等待EVENT_All_DATA_DISCONNECTED
Android 关机时的radio相关关闭流程_第23张图片

log:

//不插卡,或无数据业务的卡。等待另一张卡关数据业务
05-24 03:48:17.516  2128  2412 D SST     : [1] Data is active on DDS.  Wait for all data disconnect

//两个sub 都等待30s,都会设置mPendingPowerOffAfterDataOff
05-24 03:48:17.514  2128  2412 D SST     : [0] Wait upto 30s for data to disconnect, then turn off radio.
05-24 03:48:17.516  2128  2412 D SST     : [1] Wait upto 30s for data to disconnect, then turn off radio.

//两个sub,一个无卡mDisconnectPendingCount 为0,一个volte和data两个apn,所以mDisconnectPendingCount = 2
05-24 03:48:17.515  2128  2128 D QtiDCT  : [0]cleanUpConnection: tearing down using gen#1apnContext={mApnType=default mState=CONNECTED mWaitingApns={[[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true}
05-24 03:48:17.515  2128  2128 D QtiDCT  : [0]cleanUpConnection: tearing down using gen#1apnContext={mApnType=ims mState=CONNECTED mWaitingApns={[[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true}
05-24 03:48:17.523  2128  2128 D QtiDCT  : [0]cleanUpConnection: mDisconnectPendingCount = 2
05-24 03:48:17.535  2128  2128 D QtiDCT  : [1]cleanUpConnection: mDisconnectPendingCount = 0

//使能数据业务的sub log,分别关闭数据和volte的apn
//QtiDcTracker.java继承自DcTracker.java,由于多态,调用基本是DcTracker的函数
05-24 03:48:17.568  2128  2128 D QtiDCT  : [0]getValidApnContext (onDisconnectDone) on {mApnType=ims mState=DISCONNECTING mWaitingApns={[[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true} got 1 vs 1
05-24 03:48:17.568  2128  2128 D QtiDCT  : [0]onDisconnectDone: EVENT_DISCONNECT_DONE apnContext={mApnType=ims mState=DISCONNECTING mWaitingApns={[[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] China Mobile (IMS), 2466, 46002, ims, , , , , , -1, ims, IPV4V6, IPV4V6, true, 0, 0, 2, true, 1023, 0, 300, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true}
05-24 03:48:17.583  2128  2128 D QtiDCT  : [0]onDisconnectDone: not retrying
05-24 03:48:17.600  2128  2128 D QtiDCT  : [0]getValidApnContext (onDisconnectDone) on {mApnType=default mState=DISCONNECTING mWaitingApns={[[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true} got 1 vs 1
05-24 03:48:17.600  2128  2128 D QtiDCT  : [0]onDisconnectDone: EVENT_DISCONNECT_DONE apnContext={mApnType=default mState=DISCONNECTING mWaitingApns={[[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0]} mApnSetting={[ApnSettingV5] APN_NAME_CMNET, 2463, 46002, cmnet, , , , , , -1, default | net | supl, IPV4V6, IPV4V6, true, 0, 0, 0, false, 0, 0, 0, 0, , , false, 0, 0} mReason=radioTurnedOff mDataEnabled=true mDependencyMet=true}
05-24 03:48:17.606  2128  2128 D SST     : [0] Process pending request to turn radio off.
05-24 03:48:17.608  2128  2128 D QtiDCT  : [0]onDisconnectDone: radio will be turned off, no retries

//数据业务sub调用hangupAndPowerOff
05-24 03:48:17.606  2128  2128 D SST     : [0] Process pending request to turn radio off.

//非数据业务sub调用hangupAndPowerOff
05-24 03:48:17.610  2128  2128 D SST     : [1] EVENT_ALL_DATA_DISCONNECTED, turn radio off now.

hangupAndPoweroff

最终是向ril发送RIL_REQUEST_RADIO_POWER
Android 关机时的radio相关关闭流程_第24张图片

Android 关机时的radio相关关闭流程_第25张图片
Android 关机时的radio相关关闭流程_第26张图片

在这里插入图片描述
qcril_qmi_nas_request_power
在这里插入图片描述
对应log:

05-24 03:48:17.608  2128  2128 D RILJ    : [4127]> RADIO_POWER on = false [SUB0]
05-24 03:48:17.612  2128  2128 D RILJ    : [4128]> RADIO_POWER on = false [SUB1]
05-24 03:48:17.997  2128  2287 D RILJ    : [4128]< RADIO_POWER  [SUB1]
05-24 03:48:18.003  2128  2287 D RILJ    : [4127]< RADIO_POWER  [SUB0]
05-24 03:48:18.117  2128  2128 D SST     : [1] EVENT_RADIO_POWER_OFF_DONE
05-24 03:48:18.210  2128  2128 D SST     : [0] EVENT_RADIO_POWER_OFF_DONE

成功power radio后的流程:

SST会收到EVENT_RADIO_POWER_OFF_DONE。
Android 关机时的radio相关关闭流程_第27张图片
调用requestShutDown。又会走到ril。
Android 关机时的radio相关关闭流程_第28张图片
在这里插入图片描述
Android 关机时的radio相关关闭流程_第29张图片

里面涉及到一个shutdown的状态机。
在这里插入图片描述
这个状态机如何触发ril内部模块shutdown呢?以内部的关卡状态为例。

Android 关机时的radio相关关闭流程_第30张图片
在这里将UimCardPowerReqMsg命令发出。
Android 关机时的radio相关关闭流程_第31张图片
最终UimModule模块处理。
Android 关机时的radio相关关闭流程_第32张图片

Android 关机时的radio相关关闭流程_第33张图片
最终发送出去,由UimModemEndpointModule处理:
在这里插入图片描述
Android 关机时的radio相关关闭流程_第34张图片
最终通过qmi发送QMI_UIM_POWER_DOWN_REQ命令给modem。真是一个弯弯曲曲的流程。
Android 关机时的radio相关关闭流程_第35张图片

在这里插入图片描述

RIL_REQUEST_SHUTDOWN执行完毕

不管ril内部的复杂流程。当执行完后,会通知上层么?
从代码看,调用是没有提供参数。所以不会通知上层。但是后续radio状态机会发生变化。
Android 关机时的radio相关关闭流程_第36张图片
并且RIL_REQUEST_SHUTDOWN 处理完毕后 ,RIl.java 会处理。也会将Radio状态设置为unavailable。所以发送shutdown后,终端在radio还没有到unavailabe时,ril层就提前转到unavialable了。
Android 关机时的radio相关关闭流程_第37张图片

05-24 03:48:18.120  2128  2128 D RILJ    : [4151]> RIL_REQUEST_SHUTDOWN [SUB1]
05-24 03:48:18.124  2128  2128 D RILJ    : [4152]> RIL_REQUEST_SHUTDOWN [SUB1]
05-24 03:48:18.134  2128  2287 D RILJ    : [4151]< RIL_REQUEST_SHUTDOWN  [SUB1]
05-24 03:48:18.149  2128  2287 D RILJ    : [4152]< RIL_REQUEST_SHUTDOWN  [SUB1]
05-24 03:48:18.212  2128  2128 D RILJ    : [4153]> RIL_REQUEST_SHUTDOWN [SUB0]
05-24 03:48:18.214  2128  2128 D RILJ    : [4154]> RIL_REQUEST_SHUTDOWN [SUB0]
05-24 03:48:18.374  2128  2287 D RILJ    : [4153]< RIL_REQUEST_SHUTDOWN  [SUB0]
// radio state 变为 unavialable是 03:48:19.175,但是由于RIL_REQUEST_SHUTDOWN  03:48:18.374时已经都执行完了。所以ShutdownThread的轮询认为radio turned off。在shutdownRadios中出现如下打印
05-24 03:48:18.422  1354  4213 I ShutdownThread: Radio turned off.
05-24 03:48:18.422  1354  4213 I ShutdownThread: Radio shutdown complete.
05-24 03:48:19.108  2128  2287 D RILJ    : [4154]< RIL_REQUEST_SHUTDOWN  [SUB0]
05-24 03:48:18.001  1208  1269 D RILC    : radioStateChangedInd: radioState 0
05-24 03:48:18.006  1193  1255 D RILC    : radioStateChangedInd: radioState 0
05-24 03:48:19.175  1193  1255 D RILC    : radioStateChangedInd: radioState 1
05-24 03:48:19.182  1208  1269 D RILC    : radioStateChangedInd: radioState 1

最后一步 rebootOrShutdown

Android 关机时的radio相关关闭流程_第38张图片

QCRIL执行RIL_REQUEST_SHUTDOWN 的内部状态机

这个内部状态机曾经发送过变化。之所以关注到这个代码的改动,是因为比较不同机器的ShutdownTiming: ShutdownRadio took to complete的时间打印在终端同样插卡开数据volte的情况下,稳定的存在差异。最后发现主要差异在RIL_REQUEST_SHUTDOWN 执行时间不同。新平台机器的时间要长。 最后对比了日志,发现在状态2至状态3时,新平台有500ms差异,而老平台没有。看了代码才发现,状态名变了,等待的事件变了(从ims service的ims-reg状态,到ims pdp connected状态)。 这个变化是为了确保ims从网络侧de-registered。
Android 关机时的radio相关关闭流程_第39张图片
Android 关机时的radio相关关闭流程_第40张图片

你可能感兴趣的:(android移动网络通讯,移动网络通信,Qcril)