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

上午的宁静被一个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/0x7c
  kernel: SyS_epoll_wait+0x2a0/0x32c
  kernel: SyS_epoll_pwait+0xa4/0x120
  kernel: cpu_switch_to+0x48/0x4c
  native: #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中,这样第二次的时候因为相等了就不会再走升级流程了,所以就不会卡白米了

时间: 2024-09-13 02:31:12

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

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

原文:SQLSERVER 2012之AlwaysOn -- 一次硬件升级引发的问题 这是上周遇到的一个案例:对已有的硬件进行升级而引发的问题,期间还触发了一个比较严重的BUG,可谓多灾多难:不过值得庆幸的是,在一连串连锁问题出现的时候,并没有出现人工操作失误(这往往是在处理故障中风险最高.影响最大的问题)而扩大故障影响范围:   ==========================华丽丽的分割线==========================     先说一下环境:     我做的是跨机房3

金山360老总骂战升级 引发国内首例微博官司

知名电脑安全厂商金山和360之间的"口水战"昨天上午正式升级.因不满360董事长周鸿祎频频在微博中对金山发难,金山公司上午通过律师向海淀法院提起诉讼,索赔1200万元.据悉,这是国内首例因个人微博引发的诉讼案件. 金山公司和360是存在竞争关系的两家电脑安全厂商,两家公司"口水战"源于10天前.金山公司称:大量金山网盾的用户控诉360安全卫士恶意卸载金山网盾.随后,360董事长周鸿祎共发布微博42条,对金山网盾进行了点名批评,用词激烈,揭开两家公司老总互骂的序幕.

不免费就不升级:Win10使用率首次出现下滑

Net Applications最新统计数据显示,Windows10系统排名第二,这个结果显示了过去一个月发生了令人意想不到的事情.尽管大家都预测Windows10系统的市场占有率将持续上升,但在过去一个月它却出人意料地下滑了,这预示着微软创造10亿台电脑使用Windows10操作系统的目标还需要更长的时间才能变为现实.   Win10     份额分布图 现在还无法判断Windows 10系统的市场份额是否会稳定一段时间,但其2016年9月的表现明显低于预期,而且此次下滑发生在微软停止提供免费

5s升级ios7.1.2不能开机怎么办?苹果4s升级ios7.1.2无法开机解决方法

1.我们先到苹果官方下载一个ios7.1.2系统放在电脑中. 2.然后我们把苹果5s手机连接电脑 ,然后在电脑中打开itunes软件(如果自动弹出就不需要我们再打开了) 3.我们在电脑中同时按住按POWER键5秒后不松同时再按HOME10秒进入DFU模式,在ITUNES上按着SHIFT不松选择"恢复",再选择你刚才下的那个固件开始恢复!    另一个方法使用第三方工具恢复 1.百度搜索 下载一个i4(爱思)助手 下载并安装在电脑中, 2.然后同样把苹果5s连接电脑 ,再根据上面的提示退

iPhone4s升级ios7.1.2后开不了机?苹果4s 升级ios7.1.2不能开机解决方法

方法一, 直接从苹果官网下个IOS的7.1.2固件放电脑中,然后我们再 然后连接ITUNES,按POWER键5秒后不松同时再按HOME10秒进入DFU模式,在ITUNES上按着SHIFT不松选择"恢复",再选择你刚才下的那个固件开始恢复! 具体步骤: 1.将你的iPhone关机. 2.同时按住开关机键和Home键. 3.当你看见白色的苹果Logo时,请松开开关机键,并继续保持按住Home键. 4.开启iTunes,等待其提示你进行恢复模式后,即可按住键盘上的Shift键,点击"

绿萝算法升级对网店软文营销的影响分析

运营网站买东西作用并不高,网站更多是起到宣传的作用,除非你运营的具有一定影响力内容的网站,而运营网店则完全不同,网店只要销售的东西够创意,那么想要不赚钱那也很困难,这不刚刚互联网就传来消息,有店主销售灵符就实现了月赚百万的奇迹,由此可见只要在不违法的前提下,在销售内容上多想想创意是不错的生财之道. 但是创意并不是人人都能够想到的,大多数店主销售的产品基本上都会有其竞争者,如果不注重营销,那就很容易被淹没在信息的海洋里,而如今在百度绿萝算法升级的环境里,一些软文的营销方式被彻底改变了,也就是说网店

华为路由器升级异常变砖无法开机的解决方法

  1.准备一台笔记本电脑或者台式机,网线一根,路由器和电源(路由器先不上电) 2.设置电脑的网卡为固定IP,具体如下: 在控制面板-网路和共享中心-更改适配器设置,如下图,在ip地址设置,192.168.0.5 子网掩码为255.255.255.0 然后 点击确定保存 3.电脑有线连接路由器的LAN口(黄色口) 4.路由连接电源上电,同时按下Hi键,长按10s钟左右 5.在电脑或者笔记本的浏览器页面输入http://192.168.0.100这个地址,会出现如下页面: 6.点击"选择文件&qu

Win8升级Win10提示错误代码800703f1问题处理,800703f1原因分析

1.我们在电脑按看好Win+X键 然后在弹出菜单点击"命令提示符(管理员)"意思是以管理员形式运营命令模式; 2.在cmd界面,我们输入 net stop wuauserv,回车; 3.然后定位到系统的 C:\Windows\SoftwareDistribution,将SoftwareDistribution重命名为SoftwareDistributionOld; 4.在命令提示符窗口中接着输入net start wuauserv,回车; 5.之后重新启动计算机即可. 升级Win10提

Office 365和Office 2016升级或安装会出现电脑无响应原因分析

故障现象: 当您希望安装或升级新电脑上预装的Office 365或Office 2016时,电脑可能会出现无响应的现象,这种情况发生在程序的安装过程中. 原因分析: 当4分钟内没有完成安装过程的情况下发生. 解决方案: 如果是一次性购买的Microsoft Office 2016: 电脑只会在第一次尝试完成安装过程时无响应. 解决步骤如下: 1.关闭该进程,退出所有的Office程序: 2.重新打开Office程序安装,比如Microsoft Word 2016 . 这样操作后,安装过程应该会顺