Android4.4KK中BOOT_COMPLETED广播问题的分析

简介: 详细内容和具体分析流程也可以下载PDF文档:BOOT_COMPLETED issue analysis report一、问题现象手机开机后,按POWER键无法关闭屏幕,过了很长一段时间(20s左右)才能恢复正常。


详细内容和具体分析流程也可以下载PDF文档:

BOOT_COMPLETED issue analysis report


一、问题现象

手机开机后,按POWER键无法关闭屏幕,过了很长一段时间(20s左右)才能恢复正常。


Platform:MT6581

Android版本:4.4KK

BuildType:user

系统软件版本:SWC1I+ZZ

系统RAM:512M

二、Android4.4的POWER键处理流程

Android中对于输入事件的获取和分发分别由InputManagerService的InputReader以及InputDispatcher两个线程负责,按键属于输入事件的一种。

InputReader首先通过EventHub去获取各种类型的输入事件,当获取到之后会先通知InputDispatcher,并在进入输入事件队列之前先进行系统策略上的一些拦截,对于POWER键这样的特殊按键会进行提前的特殊处理,下图为具体的POWER按键处理流程:




三、问题初步分析

通过问题现象、log以及POWER键的处理过程,发现POWER键的处理流程之所以没有正常进行,是因为PowerManagerService没有及时获取到BOOT_COMPLETED广播,从而导致其相关状态没有被更新,关键代码为goToSleepNoUpdateLocked函数中关于判断当前状态以决定是否继续处理POWER键上下流程的代码,其中有关于mBootCompleted状态的判断,具体代码如下:

mBootCompleted状态开机默认为false,在收到BOOT_COMPLETED广播之后更新为ture,PowerManagerService接收BOOT_COMPLETED并更新mBootCompleted状态的关键代码如下:

既然mBootCompleted没有被及时更新,那么就说明BOOT_COMPLETED广播没有被及时收到,没有收到的话就要看为什么BOOT_COMPLETED广播没有被及时发出。

四、Android4.4上Broadcast(广播)的注册以及发送流程

广播(Broadcast)是一种在组件之间进行消息传递的方式,这些组件可以在相同或者不同的进程中,整个机制是在Binder进程间通信的基础上实现的。

广播机制存在一个注册调度中心,就是AcitivityManagerService。广播接收者订阅消息的形式就是将自己注册到ActivityManagerService中,并且指定要接收的广播类型。当广播发送者发送一个广播时,会首先发送到ActivityManagerService中,然后ActivityManagerService根据这个广播类型找到相应的广播接收者,最后将这个广播发送给它们。

广播接收者的注册方式分为静态注册和动态注册两种。静态注册是通过在配置文件AndroidManifest.xml中声明所感兴趣的广播的类型,以便ActivityManagerService能够找到它们。动态注册时在程序的代码中调用指定的接口将广播接收者注册到ActivityManagerService中。在同等情况下动态注册的广播接收者会优先收到广播。

广播的发送方式分为有序和无序两种。我们在注册广播接收者时可以指定它们的优先级,当ActivityManagerService接收到有序广播时,它就会将这个有序广播发送给符合条件的、优先级较高的广播接收者处理,然后再发送给符合条件、优先较低的广播接收者处理。当ActivityManagerService接收到无序广播时,它就会忽略广播接收者的优先级,先发送给动态注册的广播接收者,然后再将静态注册的广播接收者放入有序广播的处理队列中进行处理,所以对于无序广播动态注册的接收者总是优先接收到广播。

由于本文分析的问题出在广播的发送过程中,所以这里着重介绍广播的发送过程,以下为KK4.4上ActivityManagerService中finishBooting函数发出BOOT_COMPLETED广播的关键代码:

从上图的代码中可以看到红色框住的参数,此参数为true的话即以有序的方式发送广播,false即为无序方式。具体的广播发送过程如下:

1、广播发送者将一个特定类型的广播发送给ActivityManagerService(这里是ActivityManagerService直接发送BOOT_COMPLETED广播)

2、ActivityManagerService接收到一个广播之后,首先找到与此广播对应的广播接收者,然后根据广播的类型区分有序还是无序,有序广播会将所有的广播接收者无论静态还是动态注册都按照优先级进行排序放置到一个列表中,然后加入到有序广播的调度队列中。无序广播会先将动态注册的广播接收者放置到一个列表中,然后加入到无序广播的调度队列并向ActivityManagerService所运行的线程的消息队列发送一个消息,最后会将静态注册的广播接收者放置到另外一个列表中,然后加入到有序广播的调度队列中,所以静态注册的广播接收者总是会按照有序的方式进行处理,然后同样会向ActivityManagerService所运行的线程的消息队列发送一个处理广播的消息。这个时候对于广播发送者来讲,一个广播就发送完成了。

3、当ActivityManagerService所运行的线程的消息队列中的处理广播的消息被处理时,ActivityManagerService就会从广播调度队列中找到需要接收广播的广播接收者,并将对应的广播发送给他们所运行在应用程序进程。在这里需要特别说明的是ActivityManagerService对于无序广播的动态注册的广播接收者没有处理时间以及顺序上的限制,不会主动产生ANR,只是异步的将广播发送给接收者处理就返回。而对于有序广播则会严格限制时间和处理顺序,

4、广播接收者所在的应用程序进程接收到ActivityManagerService发送过来的广播之后,并不是直接调用广播接收者进行处理,而是将接收到的广播封装成一个消息,发送到主线程的消息队列中。当这个消息被处理时,应用程序进程才会将它所描述的广播发送给相应的广播接收者处理。

发送过程中各个组件的调用关系如下图:

以上是对无序广播的动态注册的广播接收者的发送过程,对静态注册的无序广播接收者以及有序广播的动态和静态注册的广播接收者的发送过程则比上面更复杂一点,牵扯到发送超时机制、有序同步反馈机制、启动静态广播接收者所在进程的机制等,大致的原理及过程如下:

1、对无序以及有序广播的静态广播接收者的调用过程需要先判断其所附属的进程是否存在,如果不存在需要先启动其所附属的进程,然后进程启动之后就将广播发送给其所在的应用进程,其所在的进程接收到广播之后则继续分发给具体的接收者,当广播接收者执行完毕之后需要将结果反馈给ActivityManagerService,以便让ActivityManagerService继续将广播分发下一个接收者,如果在分发一个广播给接收者的过程中超时了则会产生ANR。

2、对有序广播的动态注册的广播接收者的分发过程与静态类似,只是少了启动应用进程的过程,同样有分发完成的同步反馈以及超时无响应的ANR机制。

五、进一步的分析问题

通过测试发现Android4.2不存在此问题,因此对比KK4.4以及JB4.2上同样的代码发现在发送BOOT_COMPLETED广播时有一个很关键的地方有区别,就是KK4.4上BOOT_COMPLETED广播由之前的无序发送变为有序发送,即上图中的红色框框圈住的位置,false即为无序发送,ture即为有序发送,首先通过查看android官方原生代码发现不是MTK修改,KK4.4原生即为true,然后查看android的提交历史,找到针对此修改的提交记录如下:

从以上历史记录中可以看到google为了解决calendar的一个问题将BOOT_COMPLETED的广播发送方式由之前的无序改为了有序,同时还进行了延时的发出处理,从而最终影响了整个BOOT_COMPLETED的发送和处理流程,导致BOOT_COMPLETED的处理被安排在无序广播之后,另外由于BOOT_COMPLETED之前还有其他有序广播在待发送队列,只有那些有序广播被顺序处理完才会处理BOOT_COMPLETED,最终在处理有序的BOOT_COMPLETED的时候还会按照优先级进行排序,如果此时静态注册的接收者的优先级大于动态注册的优先级则在发送时还会等待静态注册的接收者的进程起来,然后再继续发送,所以结果就导致系统动态注册的接收者迟迟接收不到BOOT_COMPLETED,影响系统组件的整体功能体验。

六、解决方案

通过以上分析,为了避免在BOOT_COMPLETED广播之前的其他有序广播以及设置了高优先级的静态注册的BOOT_COMPLETED广播的广播接收者占用时间,影响系统组件的接收和功能状态更新,我们给出以下解决方案:

1、将BOOT_COMPLETED广播的发送方式由有序变为无序,这样就是让动态注册的系统组件及时的接收到广播消息,从而能够正常的更新状态,解决因有序而产生的问题。

七、结论

应用解决方案之后系统的行为恢复正常,第三方以及其他应用程序对系统开机的影响被消除,与JB4.2行为基本保持一致,最终达到要求和解决问题的目的。



#analysed by jinshi.song from SWD2 Framework team.

#jinshi.song@jrdcom.com

#201407161600


目录
相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
191 4
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
4月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统无疑是主角。它们各自拥有独特的特点和优势,为开发者提供了不同的开发环境和工具。本文将深入浅出地探讨安卓和iOS开发环境的主要差异,包括开发工具、编程语言、用户界面设计、性能优化以及市场覆盖等方面,旨在帮助初学者更好地理解两大平台的开发特点,并为他们选择合适的开发路径提供参考。通过比较分析,我们将揭示不同环境下的开发实践,以及如何根据项目需求和目标受众来选择最合适的开发平台。
55 2
|
1月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
30 8
|
3月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
91 15
Android 系统缓存扫描与清理方法分析
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
42 1
|
3月前
|
存储 Linux Android开发
Android底层:通熟易懂分析binder:1.binder准备工作
本文详细介绍了Android Binder机制的准备工作,包括打开Binder驱动、内存映射(mmap)、启动Binder主线程等内容。通过分析系统调用和进程与驱动层的通信,解释了Binder如何实现进程间通信。文章还探讨了Binder主线程的启动流程及其在进程通信中的作用,最后总结了Binder准备工作的调用时机和重要性。
Android底层:通熟易懂分析binder:1.binder准备工作
|
4月前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
159 3
|
3月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
4月前
|
安全 Linux Android开发
探索安卓与iOS的安全性差异:技术深度分析
本文深入探讨了安卓(Android)和iOS两个主流操作系统平台在安全性方面的不同之处。通过比较它们在架构设计、系统更新机制、应用程序生态和隐私保护策略等方面的差异,揭示了每个平台独特的安全优势及潜在风险。此外,文章还讨论了用户在使用这些设备时可以采取的一些最佳实践,以增强个人数据的安全。