BroadcastReceiver 注册过程
静态注册:程序安装时由 PackageManagerService 即 PMS 解析并完成注册,与 Activity Service ContentProvider 注册相同。
动态注册从 ContextImpl 的 registReceiver 方法开始,调用 registReceiverInternal 方法
应用进程
注册过程需要将 Receiver 传递,注册过程是一个跨进程通信,需要使用跨进程方式向 AMS 提交注册请求,BroadcastReceiver 是一个组件是不可以直接传递的,IIntentReceiver 是一个 Binder,可以使用 IIntentReceiver 来中转
BroadcastReceiver 不可以跨进程传输,registReceiverInternal 方法会从 LoadedApk 中将 BroadcastReceiver 转化为 IIntentReceiver ,IIntentReceiver 的具体实现是 LoadedApk 中的内部类 ReceiverDispatcher 的内部类 InnerReceiver。转化过程同绑定形式的 Service 中 ServiceConnection 的转化,InnerReceiver 为 AIDL 中的 Stub,跨进程后会在系统进程由 Stub 得到 Proxy 代理对象,广播的接收过程中并不会调用 Proxy 对象的方法通过 IPC 调用 Stub 对象的方法,而是会在接收时将 Proxy 再传递到应用进程,应用进程根据 Proxy 找到 Stub,再调用 Stub 的方法完成接收
ReceiverDispatcher 中保存了 BroadCastReceier 和 InnerReceiver,这样当接收到广播时,可以很方便的调用 BroadcastReceiver 的 onReceive 方法,InnerReceiver 中持有了 ReceiverDispatcher 的弱引用,通过 ReceiverDispatcher 能拿到其内部存储的 BroadCastReceier 对象,就可以调用 BroadCastReceier 对象的方法。
系统进程
转换后在 registRecieverInternal 中调用 ActivityManagerNative.getDefault().registerReceiver() 方法,即调用 AMS 的 registerReceiver
registerReceiver 中主要是将 InnerReceiver 及 IntentFilter 保存起来,注册过程结束。
BroadcastReceiver 的发送和接收工作过程
应用进程
ContextImpl 中的 sendBroadCast 方法中直接调用 AMS 的 broadcastIntent 方法
系统进程
broadcastIntent 中 调用 broadcastIntentLocked 方法,这个方法中为 broadcast 添加了 FLAG_EXCLUDE_STOPPED_PACKAGES 标记
- 从 Android 3.1 开始,已经添加了该特性,表示不会将广播发送给已经停止的应用。FLAG_EXCLUDE_STOPPED_PACKAGES 和 FLAG_INCLUDE_STOPPED_PACKAGES 标记位都是 3.1 添加的,第一个表示不会将广播发送给已停止的应用,第二个表示会将广播发送给已停止的应用,两个同时存在,以会发送为准。停止状态包含两种,第一种是安装了但未运行,第二种是应用被强行停止。
broadcastIntent 中,根据 intent 和 intent-filter 查找出匹配的广播接收者并经过一系列条件过滤,最终将满足条件的广播接收者添加到 BroadcastQueue ,接着 BroadcastQueue 就会调用 scheduleBroadcastsLocked 方法将广播发送给相应的接收者
scheduleBroadcastLocked 方法不会直接发送广播,会使用其内部的 Handler 发送一条 Message ,消息内容为 BroadcastQueue 本身,Handler 收到消息后,调用 BroadcastQueue 中的 processNextBroadcast 方法
processNextBroadcast 方法中,无序广播存储在 ArrayList mParalleBroadcast 集合中,while 循环,遍历时总是去除第一个 remove 掉,remove 的返回值为移除的接收者对象,一直到集合长度为 0
循环发送
循环中会调用 deliverToRegisteredReceiverLocked 方法并在该方法内部调用 performReceiveLocked 方法将一个广播发送给接收者
performReceiveLocked 方法中调用 app.thread.scheduleRegisteredReciever() 方法,app.thread 为 IApplicationThread 的实现类 ApplicationThread 的实例。
应用进程
scheduleRegisteredReceiver 方法中会调用 IIntentReciever 的实现类 InnerReceiver 的 performReceiver 方法,并在其内部调用 LoadedApk.ReceiverDispatcher 的 performReceive 方法
performReceive 方法中,会创建一个 Args 对象,Args 实现了Runnable 接口并且是 ReceiverDispatcher 的内部类,并调用主进程的 Handler 也就是 ActivityThread 中的 Handler mH的 post 方法将 args 对象传入,执行 args 的 run 方法。run 方法中调用了 ReceiverDispatcher 中保存的 BroadCastReceiver 的 onReceived 方法,并将发送的广播中的Intent 传递到 onReceive 方法中。并且是在主线程调用的。发送和接收过程也就结束了。
使用 post 的原因,ApplicationThread 是 IApplicationThread 的 Stub 实现类,也是通过 Binder 完成进程间通信的一部分,其执行在 Binder 线程,所以需要通过 ActivityThread 中的 Handler 的 post 方法将执行线程切换到主线程
BroadcastReceiver 注册过程进程转换
应用进程主线程发起注册 --> AMS 系统进程将接收者保存
BroadcastReceiver 发送和接收进程转换
应用进程主线程发起注册 --> AMS 系统进程找到接收者 --> 在 ApplicationThread 中调用 ActivityThread 中的 Handler 处理消息将进程切换到应用进程主线程