1. 简介
广播作为Android的四大组件之一,能够实现组件之间的通信。广播过程主要就是注册、发送和接收过程。广播使用了设计模式中的观察者模式:基于消息的发布 / 订阅事件模型,消息的生产者发布事件,而使用者订阅感兴趣的事件。因此,广播能够实现组件间的松耦合,即广播的发送者和接收者事先是可以不用知道对方存在的。接下来,我们来研究一下广播的注册、发送和接收过程的源码。
本文源码基于android 27。
2.广播的注册过程
我们都知道,广播的注册分成两种:静态注册和动态注册。静态注册通过在AndroidManifest.xml
中注册广播接收者,应用安装时PackageManagerService
通过解析AndroidManifest.xml
来完成这个过程,由于涉及到PackageManagerService
,这里暂且不表,后面再去分析PackageManagerService
。我们这里来看下动态注册的过程,要实现动态注册需要调用registerReceiver()
方法,其具体实现位于ContextWrapper
类中。
2.1 ContextWrapper的registerReceiver
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
上面的mBase
实际上是ContextImpl
,Context
类是个抽象类,ContextImpl
类是Context
类的具体实现,而ContextWrapper
类是个装饰者的角色,这里涉及了装饰者模式,对装饰者模式有兴趣的可以看下这篇文章:装饰者模式。
mBase
是在Activity
启动时被赋值的,这里就不祥说了。
我们来看下ContextImpl
类的实现:
2.2 ContextImpl的registerReceiver
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
最终会调用registerReceiverInternal()
。
2.3 ContextImpl的registerReceiverInternal
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
//mPackageInfo的类型为LoadedApk类
//如果mPackageInfo和context都不为空,则从mPackageInfo中获取IIntentReceiver对象
//mPackageInfo.getReceiverDispatcher()最终还是通过LoadedApk.ReceiverDispatcher.getIIntentReceiver()来获取IIntentReceiver对象
//详见下一小节的代码分析
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
//如果mPackageInfo或context为空,则新创建一个ReceiverDispatcher对象并获取IIntentReceiver
//IIntentReceiver的具体实现是在LoadedApk.ReceiverDispatcher.InnerReceiver中
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//ActivityManager.getService()获取到的就是AMS,所以最终会调用到AMS的registerReceiver()方法
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
从上面的代码可以看到,首先会获取到一个名为rd
的IIntentReceiver
对象。如果mPackageInfo
和context
都不为空,则从mPackageInfo.getReceiverDispatcher()
中获取;否则从LoadedApk.ReceiverDispatcher.InnerReceiver()
中获取。
最后会将这个IIntentReceiver
对象传递到AMS
中去注册。
我们先来看看mPackageInfo.getReceiverDispatcher()
,其具体实现是在LoadedApk
类中:
2.4 LoadedApk的getReceiverDispatcher
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
//最终还是通过LoadedApk.ReceiverDispatcher.getIIntentReceiver()来返回IIntentReceiver对象
return rd.getIIntentReceiver();
}
}
我们再来看看过LoadedApk.ReceiverDispatcher
类
2.5 LoadedApk的ReceiverDispatcher类
static final class ReceiverDispatcher {
//InnerReceiver类是ReceiverDispatcher类的静态内部类
final static class InnerReceiver extends IIntentReceiver.Stub {//继承自IIntentReceiver.Stub
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
//...
}
//...
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
//创建InnerReceiver对象
mIIntentReceiver = new InnerReceiver(this, !registered);
//保存BroadcastReceiver对象
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
//获取IIntentReceiver对象,即内部类InnerReceiver
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
}
从上面可以看到,IIntentReceiver
接口的具体实现是ReceiverDispatcher.InnerReceiver
。实际上IIntentReceiver
是一个Binder
接口,可以用来进行跨进程的通信,这里主要是用来进行广播分发。
而广播的分发过程是在AMS
中进行的,AMS
所在的进程与BroadcastReceiver
所在的进程是不同的,同时BroadcastReceiver
作为一个系统组件,其不具备跨进程通信的能力,因此需要IIntentReceiver
作为载体传递到AMS
中去。
然后,我们来看下AMS
中的广播注册过程:
2.6 ActivityManagerService的registerReceiver
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
//省略一大堆代码...
synchronized (this) {
//...
//ReceiverList继承自ArrayList,用来存储广播接收者。
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
//如果ReceiverList为空,就新创建一个
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {//rl.app表示宿主进程,一般就是Activity所在的进程
//将ReceiverList添加到receivers中
//宿主进程里面有一个列表receivers,专门用来保存这个进程注册的广播接收者。
rl.app.receivers.add(rl);
}
//...
//将ReceiverList保存到AMS的mRegisteredReceivers中
//为了方便在收到广播时,快速找到对应的广播接收者
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//...
//创建BroadcastFilter并传入ReceiverList
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
//将BroadcastFilter添加到ReceiverList中,即把ReceiverList和IntentFilter关联起来
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
//将BroadcastFilter添加到mReceiverResolver中
mReceiverResolver.addFilter(bf);
//...
return sticky;
}
}
从上面的分析可以看到,AMS
先把广播接收者封装成一个ReceiverList
对象,然后把ReceiverList
分别添加到rl.app.receivers
和mRegisteredReceivers
中去。最后会创建一个BroadcastFilter
对象并把ReceiverList
和IntentFilter
关联起来,保存到mReceiverResolver
中去,这样当AMS
接收到广播时就可以从mReceiverResolver
中找到对应的广播接收者了。
2.7 时序图
最后来张注册广播的时序图:
2.8 小结
整个注册过程的目的就是将广播接收者receiver
和要接收的广播类型IntentFilter
保存在AMS
中,方便后面收到广播时能够进行相应的处理。
3.广播的发送和接收过程
广播的发送和接收过程我们这里分为三部分来讲解:
- 从发送者到
AMS
- 从
AMS
到ApplicationThread
- 从
ApplicationThread
到接收者
为什么这么分呢,因为这中间涉及到两次跨进程的通信,哈哈~
3.1 从发送者到AMS
首先从广播的发送说起,广播可以发送不同的类型,如普通广播、有序广播等,这里以普通广播为例来分析其发送过程。
发送普通广播需要调用sendBroadcast
方法,其实现同样在ContextWrapper
中:
3.1.1 ContextWrapper的sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
因为Activity
和Service
类都继承了ContextWrapper
类,所以Activity
和Service
都可以注册和发送广播。
跟广播注册一样,ContextWrapper
的sendBroadcast()
方法还是调用到ContextImpl
的sendBroadcast()
方法。
3.1.2 ContextImpl的sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
最后还是交到AMS
中去处理。
3.1.3 时序图
从发送者到AMS
这一步还是很简单的,没做什么复杂的逻辑,我们看下时序图:
3.2 从AMS到ApplicationThread
接下来,我们看下第二部分,首先从ActivityManagerService
的broadcastIntent()
方法开始:
3.2.1 ActivityManagerService的broadcastIntent
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
//验证广播的合法性
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
//调用broadcastIntentLocked
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
AMS
中首先会检验广播的合法性,若合法就继续调用broadcastIntentLocked()
。
3.2.2 ActivityManagerService的broadcastIntentLocked
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
//省略一大堆代码...
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
//获取与这个广播匹配的静态BroadcastReceiver列表
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
//...
} else {
//获取与这个广播匹配的动态BroadcastReceiver列表
//可以查看前面的注册过程分析,动态注册时就是把相关信息(BroadcastFilter对象)保存在mReceiverResolver
//queryIntent函数将这个BroadcastFilter实例取回来
//由于注册一个广播类型的接收者可能有多个,所以这里把所有符合条件的的BroadcastFilter实例放在一个List中
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
}
}
//...
//这里只是无序的动态广播的处理过程
if (!ordered && NR > 0) {
//...
//获得一个广播队列
final BroadcastQueue queue = broadcastQueueForIntent(intent);
//创建一个广播记录BroadcastRecord,
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null);
if (!replaced) {
//广播记录入队
queue.enqueueParallelBroadcastLocked(r);
//广播交给队列去处理
queue.scheduleBroadcastsLocked();
}
//...
}
//这里会对有序广播,静态广播等进行处理,跟无序的动态广播差不多,这里就省略了。
}
可以看到,AMS
先找出能匹配的广播,然后将这些广播放到一个队列中去处理。
我们先来看下queue.enqueueParallelBroadcastLocked(r)
:
3.2.3 BroadcastQueue的enqueueParallelBroadcastLocked
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
enqueueBroadcastHelper(r);
}
实际上就是将广播记录添加到一个ArrayList
中去,后面会从mParallelBroadcasts
这个对象中取出广播记录。
再来看看scheduleBroadcastsLocked()
:
3.2.4 BroadcastQueue的scheduleBroadcastsLocked
public void scheduleBroadcastsLocked() {
//...
if (mBroadcastsScheduled) {
return;
}
//发送一个BROADCAST_INTENT_MSG信息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
这里的mBroadcastsScheduled
表示AMS
当前是不是正在处理其它广播,如果是的话,就先返回不处理了,这样可以保证所有广播是串行处理的。
注意这里处理广播的方式,当AMS
收到一个广播时,AMS
只是把广播放到一个队列中去而已,不会关注这个广播是否及时处理到。所以,广播的发送和处理实际上是异步进行的。
同时可以看到,这里只是用mHandler
发送了个信息而已,我们看看mHandler
是怎么处理信息的。
3.2.5 BroadcastHandler的handleMessage
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
//处理BROADCAST_INTENT_MSG信息
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
}
再去看下processNextBroadcast()
。
3.2.6 BroadcastHandler的processNextBroadcast
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
//...
//无序广播的处理
while (mParallelBroadcasts.size() > 0) {
//前面存到mParallelBroadcasts的BroadcastRecord在这里取出来
r = mParallelBroadcasts.remove(0);
//...
//广播大小
final int N = r.receivers.size();
//遍历所有匹配的广播
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
//调用deliverToRegisteredReceiverLocked()进一步去处理
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
这里会遍历所有匹配的广播,然后调用deliverToRegisteredReceiverLocked()
去处理。
3.2.7 BroadcastHandler的deliverToRegisteredReceiverLocked
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//检查发送者的权限
if (filter.requiredPermission != null) {
//...
}
//检查接收者的权限
if (!skip && r.requiredPermissions != null && r.requiredPermissions.length > 0) {
//...
}
//...
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
if (ordered) {
skipReceiverLocked(r);
}
} else {
//调用performReceiveLocked()进行下一部的处理
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
}
首先会检查发送者和接收者的权限,然后就是调用performReceiveLocked()
。
3.2.8 BroadcastHandler的performReceiveLocked
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
if (app != null) {
if (app.thread != null) {
//
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
//...
}
}
}
这里app.thread
指的就是ApplicationThread
,至此,就到了ApplicationThread
了。
3.2.9 时序图
第二部分的逻辑还是比较多的,我们看下其时序图:
3.2.10 小结
这一步中,AMS
首先根据intent
查找出匹配的广播接收者,然后把这些广播接收者放到一个消息队列中。同时AMS
会在消息循环中处理这些广播,并把广播交到ApplicationThread
中去处理。
3.3 从ApplicationThread到接收者
最后,就是来到ApplicationThread
,我们来看下其scheduleRegisteredReceiver()
实现:
3.3.1 ApplicationThread的scheduleRegisteredReceiver
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
这里的receiver
其类型为IIntentReceiver
,具体实现在LoadedApk.ReceiverDispatcher.InnerReceiver
,前面注册时已经见过这玩意了。我们还是进去看看。
3.3.2 LoadedApk.ReceiverDispatcher.InnerReceiver
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
//...
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
rd = null;
} else {
rd = mDispatcher.get();
}
//...
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}
//...
}
}
这里面只是简单的调用LoadedApk.ReceiverDispatcher
类的performReceive()
。
3.3.3 LoadedApk.ReceiverDispatcher的performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//将广播的intent等信息封装为Args对象
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
//这里的mActivityThread是一个Handler对象,具体指向的就是H
//所以实际就是调用Args的getRunnable()方法并通过H发送到主线程的消息队列中去处理
//因此,ReceiverDispatcher不等这个广播被处理完就返回了
//这里也体现了广播的发送和处理是异步进行的
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
从上面可以看到,广播接收者最终是运行在UI线程中的,所以,onReceive()
方法中不能执行太耗时的操作,否则将引起ANR。
我们再来看看Args
的getRunnable()
的实现。
3.3.4 LoadedApk.ReceiverDispatcher.Args的getRunnable
public final Runnable getRunnable() {
return () -> {
//...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//调用广播的onReceive()方法啦
receiver.onReceive(mContext, intent);
}
//...
}
}
最终,这里会调用广播的onReceive()
方法,至此,广播从发送到接收的过程就完成了。
3.3.5 时序图
来看下相应的时序图:
3.3.6 小结
这一步中,ApplicationThread
交到广播分发器ReceiverDispatcher
中来处理,ReceiverDispatcher
的内部类Args
在主线程消息循环中处理这个广播,最终将这个广播分发到所注册的BroadcastReceiver
实例的onReceive()
函数进行处理。
最后来张总的广播发送、接收过程时序图:
4. 总结
使用广播时,都需要先注册,可以采用静态注册或动态注册来完成。动态注册的本质就是把广播接收者receiver
和要接收的广播类型filter
保存在AMS
中去。发送广播时通过binder
机制把广播发送到AMS
中去,AMS
根据发送过来的条件(IntentFilter
/Permission
等)在已注册的广播接收者中找出相匹配的。然后将这些匹配的广播接收者放到一个消息队列中去,消息循环队列拿到广播后会交给广播分发器ReceiverDispatcher
,广播分发器最终会把广播放到主线程的消息队列中去处理,最后回调BroadcastReceiver
中的onReceive()
方法。
可以看到,在Android的广播机制中,AMS
扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,由此可以知道AMS
是多么的重要,当然并不单单是这一点啦。另外,AMS
并不会等待广播接收器处理这些广播就返回了,因此,广播的发送和处理是异步的。