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
确保此函数只进入一次。
接着调用showShutdwonDialog()判断是否去显示关机动画。
然后触发ShutdownThread.run()
ShutdownThread.run()
发送广播
注意其在调用sendOrderedBraodcastAsUser的参数br,即在发送广播的同时,br会成为此广播的最后一个接受者。br的作用是为了确保所有上层应用都收到关机广播再走下面的流程。
等待广播发送完毕
br最后收到广播,将mActionDone设置为true。 run函数中轮询mActionDone,为true时退出,走下面的流程。
关闭ActivityManager和PackageManager
关闭radio
调用shutdownRadio函数
shutdownRadio函数启动一个thread执行关闭radio的操作。
shutdownRadio
首先判断radio是否需要shutdown,若是则调用phone.shutdownMobileRadios来关闭radio。
然后轮询needMobileRadioShutdown()状态。如果radiooff则走下一步。
关闭radio
接下来针对关闭radio 重点分析一下流程。
判断是否需要关闭radio
从上面截图可以知道,就是判断RIL.java的mState变量值。如果是RADIO_UNAVAILABLE则认为不需要关机,否则需要关机。
mState状态如何转变为UNAVAILABLE
有两个情况会变为UNAVAILBALBE:
radioIndication.java 被通知radioStateChanged时
对应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().
在responseVoid函数中,先通过RIL.java的processResponse做一些处理。
然后通过sendMessageResponse通知AP上层的发送方,命令执行情况。
最后通过processResponseDone来打印收到的response信息。
对应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
对应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流程
调用流程如下:
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.
cleanUpConnection 中tearDown apn。 mDisconnectPendingCount 自加1. 关闭成功后收到EVENT_DISCONNECT_DONE.
无卡sub 的cleanUpAllConnections中,直接调用notifyAllDataDisconnected().
数据业务sub data断开后触发onDisconnectDone,mDisconnectPendingCount 减1至0后,也调用notifyAllDataDisconnected。
数据业务卡是在onDisconnectDone中触发processPendingRadioPowerOffAfterDataOff().进而调用hangupAndPowerOff。
非数据业务卡,或无卡sub,在SST(serviceStateTracker) 处理EVENT_ALL_DATA_DISCONNTECD时调用hangupAndPowerOff
无卡sub等待EVENT_All_DATA_DISCONNECTED
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
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。
调用requestShutDown。又会走到ril。
里面涉及到一个shutdown的状态机。
这个状态机如何触发ril内部模块shutdown呢?以内部的关卡状态为例。
在这里将UimCardPowerReqMsg命令发出。
最终UimModule模块处理。
最终发送出去,由UimModemEndpointModule处理:
最终通过qmi发送QMI_UIM_POWER_DOWN_REQ命令给modem。真是一个弯弯曲曲的流程。
RIL_REQUEST_SHUTDOWN执行完毕
不管ril内部的复杂流程。当执行完后,会通知上层么?
从代码看,调用是没有提供参数。所以不会通知上层。但是后续radio状态机会发生变化。
并且RIL_REQUEST_SHUTDOWN 处理完毕后 ,RIl.java 会处理。也会将Radio状态设置为unavailable。所以发送shutdown后,终端在radio还没有到unavailabe时,ril层就提前转到unavialable了。
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
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相关关闭流程相关推荐
- Android -- Wifi热点的打开与关闭流程简介
Android -- Wifi热点的打开与关闭流程简介 在Android手机中,热点也是一个较为常用的功能.对于framework开发者来说,要开发.维护SoftAp,了解framework中热点开关 ...
- Android WiFi 打开关闭流程
本文简单介绍下WiFi打开与关闭流程,参考源码Android P. 一.WiFi 开机自动打开流程 系统服务启动的时候会启动WifiService,在SystemService.PHASE_SYSTE ...
- 高通Android智能平台环境搭建_编译流程分析
高通Android智能平台环境搭建_编译流程分析 高通平台环境搭建,编译,系统引导流程分析 TOC \o \h \z \u 1. 高通平台android开发总结. 7 1.1 搭建高通平台环境开发环境 ...
- Android Telephony通话状态更新消息上报流程
Telephony通话消息上报流程 通话相关代码名称统一约定以及运行进程: 通话相关代码名称统一约定及运行进程汇总 路径 统称 进程 packages/app/Dialer Dialer com.an ...
- Android蓝牙开发—经典蓝牙详细开发流程
文章目录 开发流程 权限 核心API BlueToothAdapter getDefaultAdapter():获取BluetoothAdapter对象 判断设备是否支持蓝牙 判断蓝牙是否开启 get ...
- 【Android 10 源码】MediaRecorder 录像流程:MediaRecorder 配置
MediaRecorder 录像配置主要涉及输出文件路径.音频来源.视频来源.输出格式.音频编码格式.视频编码格式.比特率.帧率和视频尺寸等. 我们假设视频输入源来自 Camera,Camera2 A ...
- android 7.0APN信息加载设置流程
博文原址 :https://blog.csdn.net/gaugamela/article/details/53199141 终端中有一个apns-config.xml文件,负责定义各个运营商规定的默 ...
- Android系统的心脏-Zygote进程启动流程分析
简介: Android中,Zygote是整个Android系统的核心进程,是Android系统的心脏.所有的Android应用程序,包括Android框架层所在的进程system_server,都是由 ...
- 【Android 10 源码】MediaRecorder 录像流程:MediaRecorder 初始化
MediaRecorder 用于录制音频和视频,录制控制基于一个简单的状态机.下面是典型的使用 camera2 API 录制,需要使用到的 MediaRecorder API. MediaRecord ...
最新文章
- Silverlight学习笔记之文字特效之ImageBrush
- mysql数据控制语言_mysql数据控制语言DCL(Data Control Language)-数据库
- java 函数名调用_粉丝提问|c语言:如何定义一个和库函数名一样的函数,并在函数中调用该库函数...
- c语言 题目 猜算式,蓝桥杯竞赛题目(猜算式)
- 昂靠的由来[本博作者爆料]
- java web 请求跟踪_IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie技术
- C++反汇编第一讲,认识构造函数,析构函数,以及成员函数
- python3 十六进制字符串进行分割并累加
- vb.net使用DirectX入门知识
- tdd:spock工作原理_TDD与 数学形式主义:敌还是友?
- 用acdsee制作html,ACDSee 制作网络像册
- 联通光猫IPV6配置
- 在Excel中批量生成复选框,也支持批量打勾批量删除,#excel插件
- !! A股历史平均市盈率走势图
- 16. Segmentation
- Zxing扫描条形码后得到结果前面多了一个0的问题
- android 重启 logo,MSM8909+Android5.1.1开机logo对应的splash.img生成
- python-OpenCv调用IP摄像头APP
- 全球都在研发的虚拟气候设备,是治愈“失眠”的最优解吗?
- c语言编译产生随机数为什么,C语言 怎样产生随机数