BroadcastReceiver的注册有两种,静态注册和动态注册,静态注册是由PackageManagerService来完成的,这里只介绍BroadcastReceiver的动态注册。动态注册的实现其实在ContextImpl中,ContextWraper只是个代理类,没有实现真正的功能。那这里我们直接来看ContextImpl中的registerReceiver方法代码如下:
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
这里最终是调用了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) {//1
//在ReceiverDispatcher构造方法中会创建InnerReceiver这个IIntentReceiver binder实现类
//2
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
//3
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//4
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在注释1处首先对LoadedApk类型的mPackageInfo和context进行了非空判断,如果不为空就会执行注释2处的代码,从mPackageInfo获取rd对象,如果为null那么就执行注释3的代码创建一个rd对象。
这个rd对象其实是IIntentReceiver类型的Binder接口对象用于进行跨进程通讯的,它的具体实现在LoadedApk.ReceiverDispatcher.InnerReceiver中代码如下:
static final class ReceiverDispatcher {
final static class InnerReceiver extends 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;
}
...
}
...
}
这个类暂时还用不到,后面发送和接收的流程会用到。我们回到registerReceiverInternal方法注释4处,这里会调用ActivityManagerService的registerReceiverWithFeature方法并把rd和intentfilter传进去。这里低版本的源码在这调用有点区别,大家可以自行了解,接下来我们看一下ActivityManagerService的registerReceiverWithFeature代码,这里我们先看粘性广播处理部分,代码如下:
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
String permission, int userId, int flags) {
...
synchronized(this) {
...
//1
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// Collect stickies of users
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);//2
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);//3
}
}
}
...
}
注释1处通过filter获取对应的所有action的描述信息,然后根据action和userid获取所有粘性广播的intent并在注释2处添加到stickyIntents这个临时list集合中,然后遍历stickyIntents集合把匹配的intent添加到注释3处的allSticky中。
接着查看ActivityManagerService的registerReceiverWithFeature方法的剩余内容:
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
String permission, int userId, int flags) {
...
synchronized (this) {
...
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());//1
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);//2
if (rl.app != null) {
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {//3
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
rl.app.receivers.add(rl);
} else {
...
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
permission, callingUid, userId, instantApp, visibleToInstantApps);//4
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);//5
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);//6
}
...
return sticky;
}
}
注释1处获取ReceiverList列表,如果为空则在注释2处创建一个ReceiverList,ReceiverList继承自ArrayList,用来存储广播接收者。在注释4处创建BroadcastFilter并传入此前创建的ReceiverList,BroadcastFilter用来描述注册的广播接收者,并在注释5通过add方法将自身添加到ReceiverList中。注释6处将BroadcastFilter添加到mReceiverResolver中,这样当AMS接收到广播时就可以从mReceiverResolver中找到对应的广播接收者了。注意:从注释3处可以看出一个进程注册广播的个数是有限制的,这里最多可以注册1000个。
上面的这张图主要展示了,广播的发送与接收流程,整个流程止于BroadcastReceiver的onReceive方法。接下来我们就来分析具体的代码流程,我们在使用发送广播的时候一般是调用sendBroadcast方法,这里我们就从sendBroadcast开始。其实sendBroadcast是Context的抽象方法,具体的实现类是ContextImpl,具体为什么是ContextImpl前面的文章已经讲过了,这里就不在赘述了。我们就直接看一下ContextImpl中的 sendBroadcast的代码:
@Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
warnIfCallingFromSystemProcess();
...
try {
intent.prepareToLeaveProcess(this);
//1
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, receiverPermissions,
AppOpsManager.OP_NONE, options, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
注释1处直接调用了ActivityManagerService的broadcastIntentWithFeature()方法:
public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
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);//1
...
try {
return broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, callingUid, callingPid, userId);//2
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
我们先看一下注释1处的verifyBroadcastLocked方法:
final Intent verifyBroadcastLocked(Intent intent) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {//1
throw new IllegalArgumentException("File descriptors passed in Intent");
}
int flags = intent.getFlags();//2
if (!mProcessesReady) {
if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {//3
// This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.
} else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {//4
Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+ " before boot completion");
throw new IllegalStateException("Cannot broadcast before boot completed");
}
}
...
return intent;
}
这个方法其实就是对Broadcast的验证是否合法,注释1处判断Intent不为null 并且intent包含文件描述符就会抛出参数不合法异常。注释2处获取flag,注释3处判断如果系统正在启动过程中,判断如果flag设置为FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT(启动检查时只接受动态注册的广播)则不做处理,如果不是则在注释4处判断如果flag没有设置为FLAG_RECEIVER_REGISTERED_ONLY(只接受动态注册的广播接收者)则会抛出异常。
接下来我们在回到broadcastIntentWithFeature的注释2处调用了broadcastIntentLocked方法代码如下:
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
@Nullable String callerFeatureId, 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 realCallingUid,
int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
@Nullable int[] broadcastWhitelist) {
...
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
// If we are not serializing this broadcast, then send the
// registered receivers separately so they don't wait for the
// components to be launched.
if (isCallerSystem) {
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, registeredReceivers);
}
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);//1
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked(); //2
}
registeredReceivers = null;
NR = 0;
}
...
return ActivityManager.BROADCAST_SUCCESS;
}
这个方法的代码非常长大概有600多行,这里我们只看关键部分。前面的工作主要做了一下几件事:
(1)、对一些特殊的action做权限的检查。
(2)、对一些系统广播做非系统应用的使用限制
(3)、对所有的静态和动态注册的广播进行收集
(4)、把有的广播接收者按照不同优先级合并到receivers这个集合中
这里我们只关心无序广播的调用流程,因为我们主要搞清楚广播是怎么送达的。接下来就是在注释1处创建BroadcastRecord对象并将registeredReceivers传进去,在注释2处调用BroadcastQueue的scheduleBroadcastsLocked方法。代码如下
public void scheduleBroadcastsLocked() {
...
if (mBroadcastsScheduled) {
return;
}
//1
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
在注释1处通过BroadcastHandler类型的mHandler发送了一个BROADCAST_INTENT_MSG消息,然后在handleMessage中进行了处理。代码如下:
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
TAG_BROADCAST, "Received BROADCAST_INTENT_MSG ["
+ mQueueName + "]");
processNextBroadcast(true);
} break;
...
}
}
}
这里直接调用了BroadcastQueue的processNextBroadcast方法,但是这个方法里面什么也没处理直接调用了BroadcastQueue的processNextBroadcastLocked方法。代码如下:
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
...
if (fromMsg) {
mBroadcastsScheduled = false;//1
}
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {//2
r = mParallelBroadcasts.remove(0);
...
final int N = r.receivers.size();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
//3
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
...
}
这个方法也是很长的大概700行左右,这里我们只看无序广播的逻辑。从上面我们知道fromMsg是true,所以就会在注释1处把mBroadcastsScheduled置为false,表示对于此前发来的BROADCAST_INTENT_MSG类型的消息已经处理了。注释2处的mParallelBroadcasts这个集合就是存储无序广播的集合,然后通过while循环将mParallelBroadcasts列表中一个一个取出并移除然后通过注释3处发给对应的广播接收者。deliverToRegisteredReceiverLocked方法的代码如下:
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
...
try {
if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
"Delivering to " + filter + " : " + r);
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
...
} else {
r.receiverTime = SystemClock.uptimeMillis();
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
//1
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (r.allowBackgroundActivityStarts && !r.ordered) {
postActivityStartTokenRemoval(filter.receiverList.app, r);
}
}
...
} catch (RemoteException e) {
...
}
这里省去了一部分权限检查的逻辑,和关于有序广播的处理逻辑。这里我们只关心注释1处的方法performReceiveLocked 代码如下:
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
//1
if (app != null) {
if (app.thread != null) {
try {
//2
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
} catch (RemoteException ex) {
...
}
} else {
...
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
这里注释1处判断广播接收者所在的进程是否正在运行,如果正在运行然后就会调用注释2处的代码。这里的app.thread指的是ApplicationThread,接下来我们就来看一下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);
//1
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
这里注释1处调用了IIntentReceiver的performReceive,这里的IIntentReceiver是一个binder的接口,具体的实现类是LoadedApk.ReceiverDispatcher.InnerReceiver,代码如下所示:
static final class ReceiverDispatcher {
final static class InnerReceiver extends 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;
}
@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) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
...
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);//1
} else {
...
}
}
}
}
这里在注释1处调用了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);//1
...
if (intent == null || !mActivityThread.post(args.getRunnable())) {//2
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
}
这里在注释1处将intent等广播信息封装到Args对象中,然后再注释2处调用mActivityThread的post方法并传入args的内部的Runnable对象。这里的mActivityThread其实指的就是ActivityThread的内部的Handler对象H。这个消息最终会在Args的run方法中执行。
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);//1
} catch (Exception e) {
...
}
...
};
}
}
在注释1处调用了广播接收者的onReceive方法,到这里广播的注册、发送和接收过程到这里就分析完了。具体细节大家可以自行了解。