主要用到的源码文件
/frameworks/base/core/java/android/app/ContextImpl.java
提供应用注册广播入口,和ams通信。
/frameworks/base/core/java/android/app/LoadedApk.java
分发广播信息给为应用注册的广播,其内部的aidl实现类InnerReceiver 接收Android系统中广播,注册一个广播会创建一个InnerReceiver对象。
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
初始化3种广播队列,处理注册广播流程缓存注册的广播对象binder等信息,处理发送广播流程
/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
处理广播分发流程,和广播超时策略。mParallelBroadcasts存储无序广播列表
/frameworks/base/services/core/java/com/android/server/am/BroadcastDispatcher.java
和BroadcastQueue互相持有引用,处理广播分发流程,mOrderedBroadcasts存储有序广播列表,mDeferredBroadcasts存储离线广播列表
/frameworks/base/services/core/java/com/android/server/am/BroadcastRecord.java
BroadcastRecord.queue  存储基于发送广播的Intent 获取对应广播队列 BroadcastQueue
BroadcastRecord.receivers 存储 BroadcastFilter列表

/frameworks/base/services/core/java/com/android/server/am/BroadcastFilter.java
BroadcastFilter继承IntentFilter 封装广播注册到IntentFilter中参数
BroadcastFilter.receiverList 存储ReceiverList对象

/frameworks/base/services/core/java/com/android/server/am/ReceiverList.java
ReceiverList extends ArrayList<BroadcastFilter> 列表中存储动态注册广播时的IntentFilter参数
ReceiverList.receiver 存储动态注册广播时创建的 IIntentReceiver aidl binder
一个app中一个BroadcastReceiver对应一个BroadcastFilter及一个ReceiverList

 /frameworks/base/core/java/android/app/LoadedApk.java
LoadedApk.ReceiverDispatcher.mReceiver 为应用注册的BroadcastReceiver。
LoadedApk.ReceiverDispatcher.mIIntentReceiver 为LoadedApk.ReceiverDispatcher.InnerReceiver(继承IIntentReceiver.Stub) 是aidl 服务端实现类对象。
LoadedApk.ReceiverDispatcher.InnerReceiver.mDispatcher 为LoadedApk.ReceiverDispatcher对象。


一、广播初始化

从ams初始化流程可知 SystemServer进程启动时会调启动ActivityManagerService调用其构造函数,
ActivityManagerService.ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) 构造方法初始化如下广播信息:
#1调用mFgBroadcastQueue = new BroadcastQueue(this, mHandler,"foreground", foreConstants, false)初始化前台广播队列mFgBroadcastQueue,
参数foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT,即前台广播超时时间为10秒,
#2调用mBgBroadcastQueue = new BroadcastQueue(this, mHandler,"background", backConstants, true)初始化后台广播队列mBgBroadcastQueue
参数backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT,即后台广播超时时间为60秒,
#3调用mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,"offload", offloadConstants, true)初始化离线广播队列mOffloadBroadcastQueue
参数offloadConstants.TIMEOUT = BROADCAST_BG_TIMEOUT,即离线广播超时时间为60秒,
即使最终BroadcastQueue.mConstants.TIMEOUT 存储了对应消息队列的超时时间。
广播分类总结如下:
1.前台广播队列:ActivityManagerService.mFgBroadcastQueue负责处理需要立即响应的广播事件,如用户交互相关的通知。flags包含Intent.FLAG_RECEIVER_FOREGROUND,
anr超时时间定义 BROADCAST_FG_TIMEOUT = 10*1000
2.后台广播队列:ActivityManagerService.mBgBroadcastQueue处理那些可以延迟但仍然需要处理的广播事件。flags不包含Intent.FLAG_RECEIVER_FOREGROUND和Intent.FLAG_RECEIVER_OFFLOAD,
anr超时时间定义 BROADCAST_BG_TIMEOUT = 60*1000
3.离线广播队列:ActivityManagerService.mOffloadBroadcastQueue处理那些可以延迟到系统空闲时处理的广播事件,以减少对系统当前操作的干扰。flags包含Intent.FLAG_RECEIVER_OFFLOAD


二、注册广播监听

应用调用context.registerReceiver
ContextWrapper.registerReceiver 调用  mBase.registerReceiver(receiver, filter),mBase其实就是一个ContextImpl类型的对象
ContextImpl.registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 调用registerReceiverInternal(receiver, ...)这里的scheduler参数为null
ContextImpl.registerReceiverInternal(BroadcastReceiver receiver,...) 该方法主要 执行如下2步:
#1  设置scheduler为主线程Handler。具体是调用scheduler = mMainThread.getHandler(),
#2 将IIntentReceiver.Stub 实现binder接口对象,通过aidl接口传递到ams。
具体是调用intent = ActivityManager.getService().registerReceiverWithFeature(mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd, filter, broadcastPermission, userId, flags)其中rd为LoadedApk.ReceiverDispatcher.mIIntentReceiver对象(一个receiver只会创建一个rd),mIIntentReceiver对象是ReceiverDispatcher构造方法中通过new InnerReceiver(继承IIntentReceiver.Stub)创建的,
ReceiverDispatcher构造方法同时封装了receiver和scheduler,将BroadcastReceiver参数receiver赋值给LoadedApk.ReceiverDispatcher.mReceiver。
而InnerReceiver.mDispatcher为LoadedApk.ReceiverDispatcher对象,即InnerReceiver.mDispatcher.mReceiver为BroadcastReceiver参数。

ActivityManagerService.registerReceiverWithFeature(..IIntentReceiver receiver, .) 注册广播信息到ams,主要 执行如下3步:
如果receiver是第一次注册( 即 mRegisteredReceivers不包含receiver) 
#1创建ReceiverList其中ReceiverList.receiver 存储动态注册广播时创建的 IIntentReceiver aidl binder,
rl = new ReceiverList(this, callerApp, callingPid, callingUid,userId, receiver).
然后调用rl.app.receivers.add(rl) 将new ReceiverList创建的rl添加到rl的进程记录块里面的receivers中。
即一个app中一个BroadcastReceiver对应一个ReceiverList,
#2调用mRegisteredReceivers.put(receiver.asBinder(), rl) 将receiver 的Binder和rl 添加到ActivityManagerService.mRegisteredReceivers变量
#3 调用rl.add(bf) 参数bf为new BroadcastFilter(filter, rl,...)创建的 封装IntentFilter参数 的对象,
同时BroadcastFilter.receiverList 也存储了 ReceiverList对象
调用mReceiverResolver.addFilter(bf) 将IntentFilter.mActions 名称列表和BroadcastFilter对象添加到mReceiverResolver.mActionToFilter map中。
#4 获取当前广播action 对应缓存的粘滞广播Intent列表,发送粘滞广播。
同普通发送无序广播,发送广播到广播监听者,具体步骤是:
遍历粘滞广播Intent列表:
基于Intent 获取对应广播队列 BroadcastQueue queue,r = new BroadcastRecord
同三、调用queue.enqueueParallelBroadcastLocked(r) 发送粘滞广播。
例如应用注册广播调用:
IntentFilter.addAction('action1')
IntentFilter.addAction('action2')
则mReceiverResolver.mActionToFilter map存储
action1,BroadcastFilter1  第一个registerReceiver
action2,BroadcastFilter1  第一个registerReceiver
action1,BroadcastFilter2  第二个registerReceiver

ps:BroadcastFilter中包含包名称,IntentFilter等信息。广播注册时一个 IntentFilter 可以绑定多个 action,例如 filter.addAction多次。
因为ActivityManagerService.mReceiverResolver(new IntentResolver对象) 是ActivityManagerService的全局变量,
所以mReceiverResolver.mActionToFilter 存储是系统所有注册的 action 和BroadcastFilter列表信息。

注册广播监听总结:

总结:应用注册一个广播时 会创建一个LoadedApk.ReceiverDispatcher对象和一个LoadedApk.ReceiverDispatcher.InnerReceiver(继承IIntentReceiver.Stub) binder服务端对象mIIntentReceiver ,mIIntentReceiver会存储到ams中ActivityManagerService.mReceiverResolver(new IntentResolver对象).mActionToFilter map中BroadcastFilter.receiver 中。。
InnerReceiver binder服务端 用来接收广播并转发给应用。

三、发送及接收广播


应用端发送广播
应用调用context.sendBroadcast(intent) 发送无序、非粘滞广播。其他情形如调用sendOrderedBroadcast发送有序广播,sendStickyBroadcast发送粘滞广播。
ContextWrapper.sendBroadcast(Intent intent)  调用mBase.sendBroadcast(intent) ,mBase其实就是一个ContextImpl类型的对象
ContextImpl.sendBroadcast(Intent intent)  调用ActivityManager.getService().broadcastIntentWithFeature(..intent, resolvedType.  false, false, getUserId()) 通过aidl 调用ams接口发送广播,
这里参数 serialized为false即为无序广播,sticky为false即为非粘滞广播。
其中ActivityManager.getService() 方法通过IActivityManager.Stub.asInterface(b)返回  IActivityManager.Stub.Proxy(实现IActivityManager接口) 对象 ,
其中参数 b为ServiceManager中注册的名称为"activity"的服务。resolvedType查看Intent里是否有MIME或者Uri这里为null,
ActivityManagerService.broadcastIntentWithFeature(..intent,. boolean serialized, boolean sticky, int userId ) 调用 broadcastIntentLocked(..intent,. serialized,) 
这里的参数 serialized 对应参数ordered, 值为false 即默认是无序广播,sticky为false即使默认是非粘滞广播。
ActivityManagerService.broadcastIntentLocked(.. Intent intent,. boolean ordered,) 这里做了如下处理
#Instant应用禁止发送广播给Instant应用接收者,即快应用之间禁止通过广播交互。
#系统未启动完成(非升级过程),禁止通过广播启动新的进程。
#广播发给特定用户,用户或者父用户没有运行,则不发送广播。
#广播发送时,设置options数据,需要根据options情况,检查白名单、受限目标、后台启动Activity等权限进行检查。
#如果是有序广播调用 queue.enqueueOrderedBroadcastLocked(r) 将 当前广播 添加到 有序广播列表mOrderedBroadcasts
如果ordered是false 发送无序广播
BroadcastRecord对象r初始化流程:获取注册当前intent action 的BroadcastFilter列表并 添加到 registeredReceivers 列表然后封装到BroadcastRecord对象 r,
其中registeredReceivers赋值给了 BroadcastRecord.receivers,registeredReceivers获取具体步骤是调用mReceiverResolver.queryIntent(intent...) 获取动态广播注册时mReceiverResolver.addFilter(bf) 创建的BroadcastFilter对象
IntentResolver.queryIntent(Intent intent, ...)  调用mActionToFilter.get(intent.getAction()) 获取 BroadcastFilter 列表,即BroadcastRecord.receivers 存储动态注册当前action的BroadcastFilter 列表,BroadcastFilter.receiver存储应用注册广播监听时创建的binder服务端对象mIIntentReceiver .


基于广播分类intent的flags获取对应的广播队列(BroadcastQueue) 对象queue ,具体是是调用broadcastQueueForIntent(intent) 
然后发送无序广播到广播监听者,具体步骤是;
调用queue.enqueueParallelBroadcastLocked(r)
BroadcastQueue.enqueueParallelBroadcastLocked(BroadcastRecord r) 该方法将 BroadcastRecord添加到广播队列的并行集合mParallelBroadcasts列表中,接收者之间可以同时处理该广播
然后调用queue.scheduleBroadcastsLocked()
BroadcastQueue.scheduleBroadcastsLocked() 调用mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this))
BroadcastQueue.BroadcastHandler.handleMessage case BROADCAST_INTENT_MSG 调用processNextBroadcast(true)
BroadcastQueue.processNextBroadcast(boolean fromMsg)  调用processNextBroadcastLocked(fromMsg, false)
处理下一个广播
BroadcastQueue.processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) 主要执行如下几步


1 处理无序广播

1.1 发送无序广播
遍历mParallelBroadcasts无序广播列表(理论size为1) BroadcastRecord对象 r,
遍历r.receivers (receivers为 registeredReceivers) 即遍历 注册该广播action的 BroadcastFilter列表中的 BroadcastFilter对象 target ,
 调用 deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i) 参数ordered 传值为false,即
BroadcastQueue.deliverToRegisteredReceiverLocked(BroadcastRecord r,BroadcastFilter filter, boolean ordered, int index) 
先进行权限检查,更新本次发送给单个广播接收者的开始时间r.receiverTime = SystemClock.uptimeMillis(),
然后调用 performReceiveLocked (filter.receiverList.app, filter.receiverList.receiver,.r.ordered..)  参数filter.receiverList.receiver为注册广播信息到ams的IIntentReceiver.Binder,
通过这个binder可以跨进程调用客户端注册监听的广播.
BroadcastQueue.performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,.boolean ordered,..)  主要分为两步
#1如果receiver所在的进程已经启动app(app.thread != null)  异步方式调用 app.thread.scheduleRegisteredReceiver(receiver,...)  
ActivityThread.scheduleRegisteredReceiver(IIntentReceiver receiver,...)  先调用updateProcessState(processState, false)更新进程状态 ,
然后调用receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser)
这里receiver为 ams的IIntentReceiver.Binder,即通过aidl调用到ams中的服务端实现类 InnerReceiver.performReceive方法中.
#2如果receiver所在的进程未启动app(app为null) 调用receiver.performReceive(intent, resultCode, data, extras, ordered,sticky, sendingUser)
同#1 也通过aidl调用到ams中的服务端实现类 InnerReceiver.performReceive方法中.

1.2.aidl服务端(对应每个注册广播的应用)
LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive(Intent intent,...)
 调用rd = mDispatcher.get() 获取mDispatcher为LoadedApk.ReceiverDispatcher对象.而LoadedApk.ReceiverDispatcher.mReceiver为应用注册的广播 BroadcastReceiver对象.
 调用 rd.performReceive(intent, resultCode, data, extras,ordered, sticky, sendingUser)
LoadedApk.ReceiverDispatcher.performReceive(Intent intent,...) 该方法执行2步
#1 完成当前应用层监听广播类处理
先调用args = new Args(intent,..) 创建封装参数的Args(继承BroadcastReceiver.PendingResult)对象args, 
LoadedApk.ReceiverDispatcher.Args.Args(...) 构造方法调用super(..., mIIntentReceiver.asBinder(), sendingUser, intent.getFlags())
BroadcastReceiver.PendingResult.PendingResult(..., IBinder token, int userId, int flags) 构造方法将参数token赋值给 BroadcastReceiver.PendingResult.mToken,
此处的mToken为LoadedApk.ReceiverDispatcher.InnerReceiver对象的binder  mIIntentReceiver.asBinder()
然后调用mActivityThread.post(args.getRunnable())  在activityThread中执行args中的getRunnable方法。
LoadedApk.ReceiverDispatcher.Args.getRunnable()调用receiver.onReceive(mContext, intent)
执行应用层广播类的BroadcastReceiver.onReceive方法, 这个receiver为LoadedApk.ReceiverDispatcher.mReceiver 即应用注册的广播 BroadcastReceiver对象.
#2 调用mgr = ActivityManager.getService() 获取amd biner IActivityManager 对象mgr,然后调用args.sendFinished(mgr)
BroadcastReceiver.PendingResult.sendFinished(IActivityManager am) 调用am.finishReceiver 通过aidl执行ams的finishReceiver方法通知应用端广播执行完毕,具体调用:
如果是有序广播调用am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,mAbortBroadcast, mFlags)
如果是无序广播调用am.finishReceiver(mToken, 0, null, null, false, mFlags)
ActivityManagerService.finishReceiver(IBinder who,.. int flags) 主要执行3步骤
#1先基于 flags获取对应的BroadcastQueue,具体是:
flags为Intent.FLAG_RECEIVER_OFFLOAD             使用离线广播队列 mOffloadBroadcastQueue。
flags为Intent.FLAG_RECEIVER_FOREGROUND 使用前台广播队列 mFgBroadcastQueue。
flags为其他                                                                                 使用后台广播队列 mBgBroadcastQueue。
#2 基于当前监听广播InnerReceiver获取有序广播BroadcastRecord,调用  r = queue.getMatchingOrderedReceiver(who)
#3如果有当前正在处理的有序广播(r != null)  清理当前BroadcastRecord,调用 doNext = r.queue.finishReceiverLocked(r, resultCode,resultData, resultExtras, resultAbort, true)
如果有doNext为true,执行下一个广播,调用r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true) 重复上述处理下一个广播流程。
BroadcastQueue.finishReceiverLocked(BroadcastRecord r,...)
该方法进行单次广播流程的收尾工作,广播在当前程序执行缓慢(当前时间-单个广播接收者的开始时间r.receiverTime>当前广播队列超时时间),非核心系统app下次处理广播时启动延迟策略
mDispatcher.startDeferring(r.curApp.uid)
BroadcastDispatcher.startDeferring(final int uid) 
调用 d = new Deferrals(uid..) 创建当前uid的Deferrals对象d
将当前uid的Deferrals对象d添加到 缓慢列表mDeferredBroadcasts 中

2 处理有序广播


2.1 发送有序广播
如果是 有序广播,mParallelBroadcasts无序广播列表为空忽略上面的流程.然后调用 r = mDispatcher.getNextBroadcastLocked(now) 从mOrderedBroadcasts获取下一个有序广播,
调用 setBroadcastTimeoutLocked(timeoutTime) 方法开启下一轮的超时检测。
调用 deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx) 流程同1.1.1 最终通过aidl调用到ams中的服务端实现类 InnerReceiver.performReceive方法中.

ps:这里filter 是BroadcastQueue.processNextBroadcastLocked方法调用r.receivers.get(recIdx)  从BroadcastRecord.receivers列表获取下一个注册监听应用的BroadcastFilter, 其中 recIdx = r.nextReceiver++ .

2.2.aidl服务端(对应每个注册广播的应用)
流程同1.2
LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive(Intent intent,...)
 调用 rd.performReceive(intent, resultCode, data, extras,ordered, sticky, sendingUser)
LoadedApk.ReceiverDispatcher.performReceive(Intent intent,...) 该方法执行2步
#1 完成当前应用层监听广播类处理
调用args.sendFinished(mgr)
BroadcastReceiver.PendingResult.sendFinished(IActivityManager am) 调用am.finishReceiver 通过aidl执行ams的finishReceiver方法通知应用端广播执行完毕,具体调用:
如果是有序广播调用am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,mAbortBroadcast, mFlags)
ActivityManagerService.finishReceiver(IBinder who,.. int flags) 主要执行3步骤
#1先基于 flags获取对应的BroadcastQueue,具体是:
flags为Intent.FLAG_RECEIVER_OFFLOAD             使用离线广播队列 mOffloadBroadcastQueue。
flags为Intent.FLAG_RECEIVER_FOREGROUND 使用前台广播队列 mFgBroadcastQueue。
flags为其他                                                                                 使用后台广播队列 mBgBroadcastQueue。
#2 基于当前监听广播InnerReceiver获取有序广播BroadcastRecord,调用  r = queue.getMatchingOrderedReceiver(who)
#3如果有当前正在处理的有序广播(r != null)  清理当前BroadcastRecord,调用 doNext = r.queue.finishReceiverLocked(r, resultCode,resultData, resultExtras, resultAbort, true)
如果有doNext为true,执行下一个广播,调用r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true) 重复上述处理下一个广播流程。

3 处理静态广播


3.1 发送静态广播
处理完动态广播后,如果nextReceiver = r.receivers.get(recIdx) 为  ResolveInfo类型 则为静态广播,
先进行权限检查
 调用info = (ResolveInfo)nextReceiver和 r.curReceiver = info.activityInfo初始化 BroadcastRecord r,
 调用 processCurBroadcastLocked(r, app, skipOomAdj)
 BroadcastQueue.processCurBroadcastLocked(BroadcastRecord r..) 调用 app.thread.scheduleReceiver(...) 
 
 3.2 aidl服务端(对应每个注册静态广播的应用)
 ActivityThread.ApplicationThread.scheduleReceiver(Intent intent, ActivityInfo info...) 调用 sendMessage(H.RECEIVER, r)
 ActivityThread.H.handleMessage(Message msg)  case RECEIVER: 调用handleReceiver((ReceiverData)msg.obj);
 ActivityThread.handleReceiver(ReceiverData data) 调用 receiver.onReceive(context.getReceiverRestrictedContext(),data.intent) 执行应用层静态广播类onReceive方法。
 receiver 获取路径:调用 packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo)先从参数获取LoadedApk信息,
 然后调用receiver = packageInfo.getAppFactory().instantiateReceiver(cl, data.info.name, data.intent) 基于应用的intent从LoadedApk中获取BroadcastReceiver信息.

发送接收广播总结:

AMS和广播的关系
#1.应用注册一个广播时 ,将BroadcastReceiver参数receiver赋值给LoadedApk.ReceiverDispatcher.mReceiver(在客户端),同时 会创建
LoadedApk.ReceiverDispatcher.InnerReceiverr(继承IIntentReceiver.Stub) 对象存储到ActivityManagerService.mReceiverResolver(new IntentResolver对象).mActionToFilter map中BroadcastFilter.receiver中。
#2.服务端发送广播时候获取当前action 注册广播创建的 InnerReceiver binder对象列表,遍历列表 调用 InnerReceiver.performReceive 方法,
该方法最终调用mReceiver.onReceive(mContext, intent) 即调用了客户端BroadcastReceiver.onReceive方法。

1.广播发送:
1.1Intent.setFlags 设置广播队列队列类型。
前台、后台(默认类型)、离线三种队列,分别处理不同优先级的广播。在 Android 中,默认发送的广播是后台广播,
Android 中发送前台广播的核心方法是 显式指定接收者或 动态注册接收器。
1.2 sendBroadcast 发送无序、非粘滞广播。sendOrderedBroadcast发送有序广播。
2.广播注册:
每个广播接收器对应一个InnerReceiver,通过AIDL与AMS通信。

3.广播发送与接收:
无序广播并行处理,有序广播按顺序处理,静态广播通过ResolveInfo分发。
广播接收后,通过onReceive方法处理逻辑,并通过finishReceiver通知AMS。

4.性能与资源:
无序广播性能较高,有序广播和静态广播可能涉及更多资源开销。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐