一,写在前面
本篇文章会从源码角度分析广播的工作流程,具体来说是分为两部分:广播的注册,发送广播。在阅读本篇文章前,建议先了解Activity,Service相关的工作流程。本篇文章将不再分析工作流程中的重复细节,参考文章:
Android Activity的启动流程源码解析(8.0)
Android Service的启动流程源码分析(8.0)
二,广播的注册,交给ContextImpl
广播的注册分为静态注册,以及动态注册。静态注册是在xml中配置<receiver>节点,在应用程序启动后会解析xml文件,具体的注册流程是交给PackagerManagerService来处理。本篇文章主要分析广播的动态注册,也就是在Java代码中调用registerReceiver方法来注册广播,开发中具体的使用这里不再介绍。 不管是在Activity,还是Service中注册广播,都是调用ContextWrapper$registerReceiver方法。其中,ContextWrapper是Context的一个子类,在抽象类Context中定义了抽象方法registerReceiver,具体实现在子类ContextWrapper中。 查看ContextWrapper$registerReceiver源码:
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
第4行,变量mBase是Context类型,而Context是一个抽象类,其实mBase的具体实现类是ContextImpl。至于具体原因,可以查看文章
Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
查看ContextImpl相关源码:
@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);
}
//继续查看...
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();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
//...code
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
//...code
}
第17行,ContextImpl$registerReceiver有多个重载方法,但最终都会调用ContextImpl$registerReceiverInternal方法。
第24行,mMainThread是一个ActivityThread类型的变量,它的实例化在ContextImpl的构造方法中。mMainThread.getHandler()返回一个H类型的对象,H是ActivityThread的内部类,继承了Handler。值得一提的是,在启动Activity,Service的工作流程中,都会创建一个上下文环境,也就是会创建ContextImpl对象。具体分析,见文章
Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。 第26行,变量mPackageInfo是一个LoadedApk的变量,这里是将BroadcastReceiver对象封装到ReceiverDispatcher中,并最终返回IIntentReceiver类型的对象。有意思的是,ReceiverDispatcher与绑定服务中的ServiceDispatcher比较类似,都是将组件对象进行封装,并返回一个Binder对象,用于实现组件对象在进程间的通信。 由于逻辑与绑定服务流程中的LoadedApk$ServiceDispacher类似,具体分析可参考文章
Android Service的绑定流程源码分析(8.0) 。这里rd返回IIntentReceiver类型的对象,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver,其具体结构:final static class InnerReceiver extends IIntentReceiver.Stub 。 第33行,当mPackageInfo为null时,给rd赋值,做的事情与前面讲到的第26行一样。
第40行,ActivityManager.getService()返回一个IActivityManager的代理对象,调用其registerReceiver方法会向系统服务发送一个请求,基于Binder机制,会调用ActivityManagerService$ActivityManage方法。具体分析,见文章
Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
三,广播的注册,交给ActivityManagerService处理
查看ActivityManagerService$ActivityManage方法源码:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
//...code
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//...code
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);
//...code
}
第8行,caller是一个IApplicationThread类型的变量,是一个Binder对象,具体源码见文章
Android Activity的启动流程源码解析(8.0) ,这里会检查它的对应的Binder对象。 第12行,变量mRegisteredReceivers的定义: HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>()。 key:receiver.asBinder()返回的是IIntentReceiver对象对应的Binder对象。IIntentReceiver前面已经分析过了,它封装了BroadcastReceiver对象,且是一个Binder对象。 value:ReceiverList类型的对象,它是一个存储BroadcastFilter对象的List集合。结构:class ReceiverList extends ArrayList<BroadcastFilter> implements IBinder.DeathRecipient。
第14行,创建ReceiverList对象,注意最后一个参数receiver,说明ReceiverList封装了InnerReceiver对象。 第31行,BroadcastFilter结构:class BroadcastFilter extends IntentFilter 。BroadcastFilter对象中封装了ReceiverList对象,IntentFilter对象。 第37行,mReceiverResolver是一个IntentResolver类型的变量,该类里面维护了集合,并调用addFilter方法将bf存储起来。 也就是说,注册广播的就是将InnerReceiver对象,IntentFilter对象封装在类BroadcastFilter中,并最终将BroadcastFilter对象存储在变量mReceiverResolver中。值得一提的是,在发送广播的流程中,会取出变量mReceiverResolver中存储的广播接受者相关的数据。动态注册广播的分析,到此就结束了~
四,发送广播,交给ContextImpl处理
与动态注册广播一样,发送广播实际上调用的ContextWrapper$sendBroadcast方法; 查看ContextWrapper$sendBroadcast方法源码:
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
第3行,变量mBase实现类是ContextImpl,与动态注册广播一样的。 查看ContextImpl$sendBroadcast方法源码:
public void sendBroadcast(Intent intent) {
//...
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
//...
}
ActivityManager.getService()返回一个IActivityManager接口的代理对象,向系统服务AMS发起一个请求,会调用ActivityManagerService$broadcastIntent方法。具体细节不再分析,动态注册广播时已经提到。
五,发送广播,交给ActivityManagerService处理
查看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) {
//...
synchronized(this) {
intent = verifyBroadcastLocked(intent);
//...
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, userId);
//...
return res;
}
}
第9行,主要对intent的flag进行检查; 第13行,查看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) {
//...
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
//...
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
//...
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
//...
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
//...
}
第10行,设置flag为FLAG_EXCLUDE_STOPPED_PACKAGES时,广播不会发送给已经停止的应用。本篇文章是基于8.0的源码,其实从Android3.1开始,发送广播会默认添加flag为FLAG_EXCLUDE_STOPPED_PACKAGES,禁止向停止应用发送广播,为了避免调用已经停止的应用。另外,若想将广播发送给已经停止的应用,也可以设置flag为FLAG_INCLUDE_STOPPED_PACKAGES。值得一提的是,应用处于停止状态意思是:应用安装后没有启动,或被手动,其他应用强行停止了。
第14行,前面分析广播注册流程,最后有提到变量mReceiverResolver,它存储了BroadcastFilter对象,也就是存放了广播接受者相关的信息。调用IntentResolver$queryIntent方法用于获取与该intent相匹配的广播接受者,返回的是一个List集合,因此变量registeredReceivers是一个List类型变量。
第21行,将变量registeredReceivers封装在BroadcastRecord对象中。 第26行,变量queue是一个BroadcastQueue类型的对象,BroadcastQueue queue = broadcastQueueForIntent(intent)。 查看BroadcastQueue$enqueueParallelBroadcastLocked方法源码:
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
enqueueBroadcastHelper(r);
}
第2行,变量mParallelBroadcasts是一个ArrayList类型的对象,用于存放BroadcastRecord对象。ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>()。后面,会取出mParallelBroadcasts集合中的数据,完成广播的接受。
继续回到ActivityManagerService$broadcastIntentLocked的第27行,调用了queue.scheduleBroadcastsLocked(),这个是重点入口。
六,广播的接收
查看BroadcastQueue相关方法源码:
public void scheduleBroadcastsLocked() {
//...code
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
//...code
}
//继续查看...
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: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
//...code
}
}
}
//继续查看...
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
//...=
if (fromMsg) {
mBroadcastsScheduled = false;
}
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
//...
final int N = r.receivers.size();
//...
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
//...
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
//...
}
//...
}
}
第4行,发送一个what为BROADCAST_INTENT_MSG的消息; 第19行,处理what为BROADCAST_INTENT_MSG的消息; 第22行,继续调用processNextBroadcast方法;
第44行,变量mParallelBroadcasts前面已经讲过,是一个ArrayList集合,存储了BroadcastRecord对象,而BroadcastRecord对象封装了广播接受者相关的信息; 第45行,取出index为0的BroadcastRecord对象,并将该对象删除; 第51行,r.receivers返回一个List集合,里面存放了BroadcastFilter对象。注册广播流程中已经分析过BroadcastFilter对象,它封装了广播接受者相关的信息。 第55行,对r.receivers对应的集合进行遍历,完成所有匹配的BroadcastReceiver对广播的接受。然后会调用deliverToRegisteredReceiverLocked方法,这个是一个重要入口。
查看BroadcastQueue$deliverToRegisteredReceiverLocked方法源码:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
//...code
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
//...code
}
//继续查看...
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) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
//...
}
//...
}
//...
}
第21,22行,对app,app.thread进行判空检查; 第26行,app.thread返回IApplicationThread接口的代理对象,最终会调用ApplicationThread$scheduleRegisteredReceiver方法。关于ApplicationThread的描述,这里不能理解的,请参考文章
Android Activity的启动流程源码解析(8.0) ,这里不再重复阐述。
查看ActivityThread$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);
}
第5行,变量receiver是一个IIntentReceiver类型的对象,在注册广播的流程中提到过IIntentReceiver,它的具体实现类是LoadedApk$ReceiverDispatcher$InnerReceiver。其实InnerReceiver是一个Binder接口,封装BroadcastReceiver对象后,使组件对象可以在进程间传递。 查看LoadedApk$ReceiverDispatcher$InnerReceiver$performReceive方法源码:
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//...
final LoadedApk.ReceiverDispatcher rd;
//...
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
//...
}
第10行,调用LoadedApk$ReceiverDispatcher$performReceive方法;
查看LoadedApk$ReceiverDispatcher$performReceive方法源码:
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//...
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
//...
if (intent == null || !mActivityThread.post(args.getRunnable())) {
//...
}
}
第10行,变量mActivityThread是ActivityThread$H类型的对象,它继承了Handler,接受广播的操作是在Handler所在的线程中执行,也就是在ActivityThread主线程中执行。 args.getRunnable()返回一个Runnable接口; 查看LoadedApk$ReceiverDispatcher$Args源码如下:
final class Args extends BroadcastReceiver.PendingResult {
//...
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
//...
receiver.onReceive(mContext, intent);
//...
};
}
}
第10行,回调BroadcastReceiver$onReceive方法,于是前面注册的广播接受者,就接收到发送的广播了~
七,最后
本篇文章,从动态注册广播,发送广播,接收广播来分析BroadcastReceiver的工作机制。 阅读本篇文章前,建议先阅读如下文章:
Android Activity的启动流程源码解析(8.0)
Android Service的启动流程源码分析(8.0)