针对插单卡,开数据业务情况下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相关关闭流程相关推荐

  1. Android -- Wifi热点的打开与关闭流程简介

    Android -- Wifi热点的打开与关闭流程简介 在Android手机中,热点也是一个较为常用的功能.对于framework开发者来说,要开发.维护SoftAp,了解framework中热点开关 ...

  2. Android WiFi 打开关闭流程

    本文简单介绍下WiFi打开与关闭流程,参考源码Android P. 一.WiFi 开机自动打开流程 系统服务启动的时候会启动WifiService,在SystemService.PHASE_SYSTE ...

  3. 高通Android智能平台环境搭建_编译流程分析

    高通Android智能平台环境搭建_编译流程分析 高通平台环境搭建,编译,系统引导流程分析 TOC \o \h \z \u 1. 高通平台android开发总结. 7 1.1 搭建高通平台环境开发环境 ...

  4. Android Telephony通话状态更新消息上报流程

    Telephony通话消息上报流程 通话相关代码名称统一约定以及运行进程: 通话相关代码名称统一约定及运行进程汇总 路径 统称 进程 packages/app/Dialer Dialer com.an ...

  5. Android蓝牙开发—经典蓝牙详细开发流程

    文章目录 开发流程 权限 核心API BlueToothAdapter getDefaultAdapter():获取BluetoothAdapter对象 判断设备是否支持蓝牙 判断蓝牙是否开启 get ...

  6. 【Android 10 源码】MediaRecorder 录像流程:MediaRecorder 配置

    MediaRecorder 录像配置主要涉及输出文件路径.音频来源.视频来源.输出格式.音频编码格式.视频编码格式.比特率.帧率和视频尺寸等. 我们假设视频输入源来自 Camera,Camera2 A ...

  7. android 7.0APN信息加载设置流程

    博文原址 :https://blog.csdn.net/gaugamela/article/details/53199141 终端中有一个apns-config.xml文件,负责定义各个运营商规定的默 ...

  8. Android系统的心脏-Zygote进程启动流程分析

    简介: Android中,Zygote是整个Android系统的核心进程,是Android系统的心脏.所有的Android应用程序,包括Android框架层所在的进程system_server,都是由 ...

  9. 【Android 10 源码】MediaRecorder 录像流程:MediaRecorder 初始化

    MediaRecorder 用于录制音频和视频,录制控制基于一个简单的状态机.下面是典型的使用 camera2 API 录制,需要使用到的 MediaRecorder API. MediaRecord ...

最新文章

  1. Silverlight学习笔记之文字特效之ImageBrush
  2. mysql数据控制语言_mysql数据控制语言DCL(Data Control Language)-数据库
  3. java 函数名调用_粉丝提问|c语言:如何定义一个和库函数名一样的函数,并在函数中调用该库函数...
  4. c语言 题目 猜算式,蓝桥杯竞赛题目(猜算式)
  5. 昂靠的由来[本博作者爆料]
  6. java web 请求跟踪_IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie技术
  7. C++反汇编第一讲,认识构造函数,析构函数,以及成员函数
  8. python3 十六进制字符串进行分割并累加
  9. vb.net使用DirectX入门知识
  10. tdd:spock工作原理_TDD与 数学形式主义:敌还是友?
  11. 用acdsee制作html,ACDSee 制作网络像册
  12. 联通光猫IPV6配置
  13. 在Excel中批量生成复选框,也支持批量打勾批量删除,#excel插件
  14. !! A股历史平均市盈率走势图
  15. 16. Segmentation
  16. Zxing扫描条形码后得到结果前面多了一个0的问题
  17. android 重启 logo,MSM8909+Android5.1.1开机logo对应的splash.img生成
  18. python-OpenCv调用IP摄像头APP
  19. 全球都在研发的虚拟气候设备,是治愈“失眠”的最优解吗?
  20. c语言编译产生随机数为什么,C语言 怎样产生随机数

热门文章

  1. 北京邮电大学计算机考研英语,我的考研心得——北京邮电大学计算机专业
  2. 【JVAV】—继承、多态、抽象类
  3. 华为手机的开发者模式真难用,为什么要把系统搞得这么烂?
  4. 魅族手机投屏电脑如何操作
  5. 用SDK包开发K66FX18学习笔记(2)
  6. 3种方式构造HTTP请求详解(HTTP4)
  7. [win7 百度网盘] 登录安全验证显示空白页
  8. python注释是什么意思_python中注释的意思是什么
  9. 阿里java社招_社招|阿里巴巴Java工程师社招凉经
  10. UML预约挂号系统建模(团队作业)