上午的宁静被一个OTA卡白米问题打破,接下来不断有人反馈不同机型都复现了OTA后卡白米,10.9号OTA升级到10.10号的版本,全机型问题,线刷没有问题,好吧,接下来就根据这些信息开始初步分析log吧!

初步分析

查看问题log,发现Boot phase到了PHASE_SYSTEM_SERVICES_READY

并且走到了PackageManagerService.systemReady

10-10 15:26:47.762  3152  3152 W ContextImpl:
Calling a method in the system process without a qualified user:
android.app.ContextImpl.bindService:1295
miui.provider.ExtraGuard.init:69
com.android.server.pm.PackageManagerServiceInjector.initExtraGuard:429
com.android.server.pm.PackageManagerService.systemReady:15195
com.android.server.SystemServer.startOtherServices:1133 

继续看log发现以下异常信息

10-10 15:27:07.784  3152  3221 E ActivityManager:
Attempt to launch receivers of broadcast intent Intent
{ act=android.net.conn.DATA_ACTIVITY_CHANGE (has extras) } before boot completion

这说明系统启动没有正常完成,ActivityManager的状态还没有就绪,难道system server的启动流程出现了异常?
赶紧打出system server的traces看一下

"main" prio=5 tid=1 Native| group="main" sCount=1 dsCount=0 obj=0x75f14fb8 self=0x558db1ec10| sysTid=3152 nice=-2 cgrp=default sched=0/0 handle=0x7fb6a3afc8| state=S schedstat=( 5043600992 157397768 10523 ) utm=367 stm=137 core=5 HZ=100| stack=0x7fe85de000-0x7fe85e0000 stackSize=8MB| held mutexes=kernel: __switch_to+0x70/0x7ckernel: SyS_epoll_wait+0x2a0/0x32ckernel: SyS_epoll_pwait+0xa4/0x120kernel: cpu_switch_to+0x48/0x4cnative: #00 pc 0000000000069be4  /system/lib64/libc.so (__epoll_pwait+8)native: #01 pc 000000000001cca4  /system/lib64/libc.so (epoll_pwait+32)native: #02 pc 000000000001be88  /system/lib64/libutils.so (_ZN7android6Looper9pollInnerEi+144)native: #03 pc 000000000001c268  /system/lib64/libutils.so (_ZN7android6Looper8pollOnceEiPiS1_PPv+80)native: #04 pc 00000000000d2580  /system/lib64/libandroid_runtime.so (_ZN7android18NativeMessageQueue8pollOnceEP7_JNIEnvP8_jobjecti+48)native: #05 pc 000000000000082c  /data/dalvik-cache/arm64/system@framework@boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+144)at android.os.MessageQueue.nativePollOnce(Native method)at android.os.MessageQueue.next(MessageQueue.java:323)at android.os.Looper.loop(Looper.java:135)at com.android.server.SystemServer.run(SystemServer.java:299)at com.android.server.SystemServer.main(SystemServer.java:181)at java.lang.reflect.Method.invoke!(Native method)at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

看起来主线程没有什么异常,已经进入主消息循环了,也就是说startOtherServices已经走完了,都走完了为啥activitymanager的状态还没有就绪?看代码吧


已知PMS的systemready已经走了,整个startOtherServices也走完了,所以AMS的systemready一定调用了,但是调用了为什么没有ready?

仔细看上面的代码可以看到一些端倪,因为调用AMS的systemready时传入的是一个runnable,runnable里面是启动systemui并通知一堆系统service running,从代码中可以看到这个runnable是在systemready函数的后半部分执行的,而当前出问题的状态是这个runnable并没有执行。

除了这个runnable之外还有一个关键的状态就是AMS的mSystemReady,通过am start发现log中打出来AMS没有ready的信息,产生这种状态的唯一的可能就是在AMS的systemready函数中没有正常执行完毕。

查看代码发现OTA后第一次调用到AMS的systemready之后mDidUpdate为false,mWaitingUpdate也是false,继续往下走到deliverPreBootCompleted,这里又传入了一个runnable,非常关键的一步,如果是OTA后第一次调用deliverPreBootCompleted会返回true给mWaitingUpdate,以为在deliverPreBootCompleted里面会发送ACTION_PRE_BOOT_COMPLETED给所有注册的receiver,并且添加FLAG_RECEIVER_BOOT_UPGRADE,在发送广播的时候就从同步调用变成了异步,返回后继续执行,mWaitingUpdate为true,然后return出去,mSystemReady在这一次没有机会设置为true,那什么时候设置呢?AMS ready的剩余代码什么时候执行呢?带着问题继续看代码

深入分析

还记得上面调用deliverPreBootCompleted时传入的runnable吗?当OTA后第一开机的ACTION_PRE_BOOT_COMPLETED广播发送给所有的receiver之后就会调用这个runnable,它里面会将mDidUpdate置为true并再次调用AMS的systemready函数,这次会正常执行完所以的流程,包括设置mSystemReady等状态为true,调用startOtherServices传入的runnable启动systemui和notify systemservice running,启动home等,但是现在这些都没有做。。。好吧,一言不合说不做就不做,Android就是任性!

赶紧看看它为啥没做,deliverPreBootCompleted也调用了,runnable也传过去,那问题就出在deliverPreBootCompleted里面的广播发送了?要想知道,还得看代码和log



好了,代码和log看到这里,基本定位到了大概原因,这个广播是有序发送的,并且是显式指定component的方式,每个发送完了都会把结果给PreBootContinuation并调用performReceive发送下一个,如果都发完了会把之前传入的runnable post 到消息队列里面,显而易见,没有走到post这一步,也就是说上面的广播在发送过程中出问题了,出什么问题了呢?还好这个问题可以必现,赶紧复现追一下代码,发现需要给6个receiver发送广播,出问题时只发送到第二个contactsproviders的时候就断了,log也对应了这一点,并且log中发现了contactsproviders升级数据库版本的信息,同时又仔细看了一下system server的trace,发现有个关于getprovider的线程不是太正常,一直处于waiting状态

contactsproviders执行之后一直没有完成,而AMS这么又有一个binder 线程一直在等待provider,这是不是有某种对应关系?赶紧看一下contactsproviders所在进程的traces,发现真有关系,在ContactsUpgradeReceiver里面执行数据库升级之后去请求一个content provider的时候block住了


真是踏破铁鞋无觅处,得来好不费功夫啊,system server一直在等待你完成通知它,你却在这睡大觉,但是又引来一个问题,这里的调用为什么会一直block?继续看代码,断点追代码,在getContentProviderImpl里发现了蹊跷,为contactsprovider 请求的yellowpage provider去startProcessLocked的时候由于system还没有ready所以start的操作被hold住了,所以导致contactsprovider的query操作被一直block


通过分析代码发现,不允许yellowpageprovider的进程起来是合理的,不合理的是contactsprovider在OTA过第一次开机upgrade的过程中不合理的请求了query yellowpageprovider,从而block整个系统启动,导致卡白米

后续问题

到这里可能有细心的同学会问,为什么之前OTA没问题,今天就有问题了?

原因是contactprovider的数据库版本有升级,在升级的同时触发了T9索引重建,重建的过程中用到了yellowpageprovider,来一下change再配合上面的traces可能会更直观

这个索引重建不是不能做,而是不能在OTA第一次开机过程中调用upgradereceiver的做,可以等正常开机后,BOOT_COMPLETED广播发出去的时候再触发做

可能还有更细心的同学会问,为什么卡住之后再重启一下就好了呢?

这是因为在ContactsUpgradeReceiver中会先判断DB VERSION,第一次因为升级了所以不相等,就走升级流程,升级之前先把最新的DB VERSION put到了preference中,这样第二次的时候因为相等了就不会再走升级流程了,所以就不会卡白米了

由ContactsProvider的升级引发的OTA首次开机卡白米问题分析相关推荐

  1. SQLSERVER 2012之AlwaysOn -- 一次硬件升级引发的问题

    原文:SQLSERVER 2012之AlwaysOn -- 一次硬件升级引发的问题 这是上周遇到的一个案例:对已有的硬件进行升级而引发的问题,期间还触发了一个比较严重的BUG,可谓多灾多难:不过值得庆 ...

  2. 汽车在线升级系统(OTA)开发浅析

    本文由姜楠,姜姗姗,韩小鹏联合创作 摘要 介绍了汽车在线升级系统(OTA)的应用场景及功能,阐明了升级系统中车端及云端模块开发策略及架构:同时明确了与整车其他 ECU 的交互需求:最后介绍了在线升级系 ...

  3. 58 ESP32 OTA升级(双OTA分区无factory APP)

    1 引言 产品功能实现后,就要对产品的维护进行考虑.产品出来后,卖了N台出去,如果突然发现自己一行代码写错了,怎么办,肯定不能去现场吧N台设备,免费出差旅游也累啊,所以一般需要有远程升级设备的功能,此 ...

  4. android系统开机启动很慢,为什么安卓手机升级系统后,首次启动会比较慢?

    原标题:为什么安卓手机升级系统后,首次启动会比较慢? 点击 很多小伙伴对安卓手机进行系统升级后,可能都会遇到一种情况:手机首次启动的时间好久,首次打开应用的时间也比往常要长. 为什么会出现这种情况? ...

  5. RTOS设备如何快速实现OTA升级--快速接入OTA平台

    目录 一. 创建产品和零件 1.1 登陆平台 1.2 添加产品 1.3 配置产品 1.4 添加升级零件 二. 添加设备 2.1 单个添加 2.2 批量添加 三. 设备注册激活 3.1 发起请求 3.2 ...

  6. ESP32 OTA升级之HTTP OTA

    ESP32 OTA升级之 HTTP OTA 文章目录 ESP32 OTA升级之 HTTP OTA 1. 前言 2. 搭建http本地服务器 2. HTTP OTA 3. 补充学习 1. 前言 在所有电 ...

  7. 启明云端分享|sigmastar SSD201/ssd202核心板升级参考,可实现开机自动从 SD 卡升级固件或开机自动从 SD 卡烧录 MAC 地址

    实现功能 1.开机自动从 SD 卡升级固件: 2.开机自动从 SD 卡烧录 MAC 地址: 一.实现方法 自动升级固件 示例:# vi project/image/configs/i2m/script ...

  8. 计算机启动时蓝屏后自动重起,升级Win10系统之后一开机就蓝屏且电脑不断重启怎么解决?...

    升级Win10系统之后一开机就蓝屏且电脑不断重启怎么解决?这一点其实和用户使用的计算机硬件环境有关系,目前就笔者所知的最容易引起该问题的硬件是显卡,很多显卡驱动都不能很好的兼容Win10系统.所以我们 ...

  9. Windows 11 首次开机OOBE阶段跳过连接网络及登录微软账户,使用本地账号登录的方法

    2022/11/25更新: 以下方法最新版本的Win11 22H1上已失效,最新的方法是在第二步呼出cmd窗口,输入oobe\bypassnro,电脑会重启,再次来到连接网络的页面时选择"我 ...

  10. deepin升级到20.2,开机显示deepin LOGO之后屏幕黑屏解决办法

    deepin升级到20.2,开机显示deepin LOGO之后屏幕黑屏解决办法 黑屏后按快捷键: ctrl+atl +F2进入终端. 在终端执行命令: sudo apt install deepin- ...

最新文章

  1. Comparative assessment of long-read error-correction software applied to RNA-sequencing data
  2. 2021年春季学期-信号与系统-第七次作业参考答案-第一小题
  3. 001_Ajax简介
  4. Url Rewrite 再说Url 重写
  5. java ee架构_与Java EE和Spring的集成架构
  6. 跳转到企业缓存之前要考虑的事项
  7. poj2516Minimum Cost
  8. 【BZOJ2456】mode,卡内存
  9. ★LeetCode(812)——最大三角形面积(JavaScript)
  10. Codeforces Round #439 (Div. 2)
  11. NYOJ -11--奇偶数分离
  12. VARCHART XGantt 甘特图中的数据表介绍
  13. RS485绝对值编码器Arduino数据读取
  14. 计算机软件自启动设置,设置开机启动项,详细教您电脑如何设置开机启动项
  15. Unity 代码帧动画
  16. 公司网盘间的风云变幻PK赛
  17. 树莓派 3B+/4B 连接“手机热点“或“WiFi“ 后无法上网(必解)
  18. 19年6月英语六级阅读单词
  19. Cesium中使用Sampler3D,3D纹理,实现体渲染
  20. 泛型及其使用、Stream的方法(Java小白进阶day17)

热门文章

  1. 简单解说思科命令大全
  2. 【Google浏览器无法登录账号】为安全起见,您无法从此设备登录。请稍后重试,或从其他设备登录
  3. 草蟒python汉化版_草蟒首页、文档和下载 - Python 汉化版 - OSCHINA - 中文开源技术交流社区...
  4. 关于芯片或者功率模块热相关计算
  5. idea将项目导出为jar包
  6. 端口tagged和untagged详解
  7. 在线问题反馈模块实战(十七):实现excel模板在线下载功能
  8. matlab拟合不显示直线,新人求助一下MATLAB直线拟合问题
  9. Java实现飞机大战
  10. java-jsoup爬虫