概述
我们从三个方面来分析广播的流程
- 广播的注册
- 广播的发送
- 广播的处理
广播的注册
广播的注册分为静态注册和动态注册,我们主要分析动态注册
首先我们从context.registerReceiver()
这个方法开始,看他内部调用了ContextWrapper#registerReceiver
方法
ContextWrapper.java
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
mBase的实现类是ContextImpl
ContextImpl.java
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
//将主线程Handler赋予scheuler
scheduler = mMainThread.getHandler();
}
//注释1
//获取IIntentReceiver对象
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();
}
}
try {
//注释2
//调用AMP.registerReceiver
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
我们先看一下注释1
,他的主要作用是获取IIntentReceiver
对象,其中mPackageInfo
是LoadedApk
类型,我们看一下IIntentReceiver
到底是什么
LoadedApk.java
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;
}
IIntentReceiver
原来是一个Binder接口
,用于广播的跨进程通信,他在LoadedApk.ReceiverDispatcher.InnerReceiver
中实现
ActivityManagerService.java
接下来我们看一下注释2
,ActivityManagerNative.getDefault().registerReceiver
,其中ActivityManagerNative.getDefault()
这个最终会指向ActivityManagerService
,这也是一个Binder用于进程间的通信,我们看一下registerReceiver
这个方法做了什么
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
...
ProcessRecord callerApp = null;
...
synchronized(this) {
if (caller != null) {
//注释1
//查询调用者的进程信息
callerApp = getRecordForAppLocked(caller);
...
//获取IntentFilter中的actions,这个就是平时所加的action
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) {
//从mStickyBroadcasts中查看用户的sticky Inten
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>();
}
//注释3
//把粘性广播添加到列表中
stickyIntents.addAll(intents);
}
}
}
}
}
...
synchronized (this) {
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) {
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
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);
}
...
//创建BroadcastFilter,并添加到接受者队列
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
Slog.w(TAG, "Receiver with filter " + filter
+ " already registered for pid " + rl.pid
+ ", callerPackage is " + callerPackage);
} else {
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
//新建的BroadcastFilter,添加到mReceiverResolver队列中
mReceiverResolver.addFilter(bf);
}
...
return sticky;
}
}
这个方法有点长,其中mRegisteredReceivers
记录着所有已经注册的广播
注册广播小结
- 传递的参数是
BroadcastReceiver
和IntentFilter
- 创建
LoadedApk.ReceiverDispatcher.InnerReceiver
,该对象是一个Binder
- 通过
AMS
把InnerReceiver
对象的代理类,注册到system_server
进程 - 如果广播没有被注册过,则创建广播接受者队列
ReceiverList
,并添加到AMS.mRegisteredReceivers
(已注册广播队列); - 创建
BroadcastFilter
,并添加到AMS.mReceiverResolver
和ReceiverList
发送广播
发送广播是调用sendBroadcast()
,其实真正干货的是ContextImpl类,广播分很多种,有序广播和无序广播,粘性广播,这里我们只分析无序挂广播
ContextImpl.java
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
// 调用AMP.broadcastIntent
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
getUserId());
} catch (RemoteException e) {
...
}
}
还是很熟悉的代码,最终还是会调用到ActivityManagerService#broadcastIntent
方法
ActivityManagerService.java
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();
//注释1
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;
}
}
注释1处,调用了broadcastIntentLocked
方法
private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle options, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
...
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
//根据intent的flag来判断前台队列或者后台队列
BroadcastQueue queue = broadcastQueueForIntent(intent);
//注释1
//创建BroadcastRecord
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
//将BroadcastRecord加入到有序广播队列
queue.enqueueOrderedBroadcastLocked(r);
//注释2
//处理广播
queue.scheduleBroadcastsLocked();
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
这个方法很长,前面省略了很多,前面的工作主要是,把静态注册和动态注册的广播,按照优先级不同存储在不同的列表中,然后把俩个列表合并到recevers
列表中,这样recevers
列表就包含了所有的广播接收者,然后再注释1处创建BroadcastRecord
对象并把recevers
传入,然后再注释2处调用BroadcastQueue
的scheduleBroadcastsLocked
方法处理广播
处理广播
不管哪种广播最终都会调用scheduleBroadcastsLocked
方法来处理广播
BroadcastQueue.java
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
此处的Handler
是BroadcastHandler
,消息在BroadcastHandler
中处理
BroadcastHandler.java
private final class BroadcastHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
processNextBroadcast(true);
} break;
...
}
}
调用了processNextBroadcast方法,该方法对无序广播和有序广播分别进行处理,旨在把广播发送给广播接受者
BroadcastQueue.java
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
//part1: 处理无序广播
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);
//分发广播给已注册的receiver
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
addBroadcastToHistoryLocked(r);//将广播添加历史统计
}
...
}
通过deliverToRegisteredReceiverLocked
方法,把广播分发给对应的广播接收者
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) {
...
//检查发送者是否有BroadcastFilter所需权限
//以及接收者是否有发送者所需的权限等等
//当权限不满足要求,则skip=true。
...
// 处理广播
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
处理广播
private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
//通过binder异步机制,向receiver发送intent
if (app != null) {
if (app.thread != null) {
//调用ApplicationThreadProxy类对应的方法
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} else {
//应用进程死亡,则Recevier并不存在
throw new RemoteException("app.thread must not be null");
}
} else {
//调用者进程为空,则执行该分支
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
这个方法表示,如果广播接受者的进程还存在,则通过Binder发送广播,这里的app.thread
指的是ApplicationThread
,我们看一下scheduleRegisteredReceiver
这个方法
ActivityThread.java
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);
}
他调用了IIntentReceiver
的performReceive
方法,前面说过IIntentReceiver
用于广播的跨进程通信,具体实现在LoadedApk.ReceiverDispatcher.InnerReceive
LoadedApk.java
public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser);
} else {
...
}
}
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//注释1
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);
}
}
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传入了Arg对象,mActivityThread是一个Handler指向内部类H,注释2处的args.getRunnable(),就是要处理的逻辑,我们看下这个getRunnable
public final Runnable getRunnable() {
return () -> {
...
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//注释1
receiver.onReceive(mContext, intent);
再注释1处,调用了onReceive方法,这样注册的广播接受者,就收到了消息
参考:http://gityuan.com/2016/06/04/broadcast-receiver/
Android 进阶解密