赞
踩
BroadcastReceiver四大组件之一,作为应用内、进程间的一种重要通信机制,能够将消息通过广播的形式传递给它注册的对应广播接收器的对象,那么它们之间信息的传递机制,传递过程是如何的了?接下来就来从广播的注册以及发送两方面讲起,看下它们之间的代码执行过程。
广播的注册调用的是
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
这个方法真正的实现是在ContextWrapper
中,因此我们去它的父类ContextWrapper
中看下它的实现
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter); //转发
}
这里的mBase
是一个Context
,而它是一个抽象类,它的具体实现是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);
}
它接着调用另一个registerReceiver
的重载方法,在它的重载方法中接着转到调用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(); //1
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true); //2
} else {
...
}
}
try {
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags); //3
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
这里的receiver
就是外面注册的广播,mPackageInfo
它是一个LoadedApk
实例,参数scheduler
转发过来就是为的, 所以这里首先会执行到注释1处,它会去获取一个
handler
, 这个Handler
就是ActivityThread
里面维护的Handler
,它里面有处理各种消息事件的code
。接着调用到注释2处,看下getReceiverDispatcher
函数的实现
public final class LoadedApk {
...
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) { //true
map = mReceivers.get(context); //获取ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>>
if (map != null) {
rd = map.get(r); //根据receiver获取ReceiverDispatcher
}
}
if (rd == null) {
//构造一个ReceiverDispatcher, 如果集合中没有rd
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) { //true
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;
return rd.getIIntentReceiver(); 获取ReceiverDispatcher的getIIntentReceiver()方法
}
}
}
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
}
}
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
...
}
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
}
从这段代码可以看出ReceiverDispatcher
里面的InnerReceiver
是一个Binder
对象,在ReceiverDispatcher
的构造函数中创建了一个InnerReceiver
实例,这时候通过getReceiverDispatcher
获取的就是一个Binder
对象,同时在ReceiverDispatcher
中保存了mActivityThread
, mIIntentReceiver
等实例,方便后面广播事件的分发调用。
回到registerReceiverInternal
方法,看注释3处,ActivityManager.getService()获取的就是一个ActivityManagerProxy
代理对象,然后调用registerReceiver
将InnerReceiver
注册给它。
class ActivityManagerProxy implements IActivityManager
{
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver,
IntentFilter filter, String perm) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
//向AMS注册广播接收器的请求
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
}
...
}
这个函数通过Binder
驱动程序就进入到ActivityManagerService
的registerReceiver
中。
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
...
synchronized(this) {
if (caller != null) {
//get ProcessRecord 获取应用程序记录快,每个应用都用一个进程记录快记录
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
...
}
if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
...
}、
//获取uid, pid
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
...
}
//isInstantApp
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
//这里和粘性广播相关 1
Iterator<String> actions = filter.actionsIterator();
...
// 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);
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// Don't provided intents that aren't available to instant apps.
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
// If intent has scheme "content", it will need to acccess
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
//粘性事件添加在allSticky集合中,后面会处理这个集合
allSticky.add(intent);
}
}
}
...
synchronized (this) {
...
//获取ReceiverList 它是一个arrayList集合 2
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 {
...
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
//构建BroadcastFilter对象 3
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
添加到ReceiverList中
rl.add(bf);
...
mReceiverResolver.addFilter(bf);
...
return sticky;
}
}
在这段代码 首先看注释1处 这里会获取匹配的粘性广播allSticky
,当registerReceiver
的时候,如果有匹配的广播,后面就会直接分发去调用注册的广播。接着走到注释2处,获取ReceiverList
实例,接着走到注释3处,构建一个BroadcastFilter
将广播接收器列表ReceiverList
和filter
关联起来,然后保存到AMS
的成员变量mReceiverResolver
中,方便以后可以接受到相应的广播进行处理。 这样就完成了广播的注册过程。
广播注册UML如下
发送过程相对于注册过程还是比较复杂的,这里以发送普通广播sendBroadcast
为例,同样也会调用到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()); //1
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
看注释1处最终也会通过Binder
调用到AMS
的broadcastIntent
方法,而在这个方法中接着会调用到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) {
...
//1
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
BroadcastQueue queue = broadcastQueueForIntent(intent);
queue.enqueueOrderedBroadcastLocked(r);
//2
queue.scheduleBroadcastsLocked();
...
}
}
首先在注释1处查询对应intent
的BroadcastFilter
接收器列表,然后在注视2处将广播信息放到自己的消息队列中。
public void scheduleBroadcastsLocked() {
...
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
在这个方法中通过内部维护的一个mHandler
对象发送了一个message
,对应的处理过程如下
private final class BroadcastHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
...
processNextBroadcast(true);
} break;
...
}
}
}
接着会调用processNextBroadcast
处理广播消息,它的方法很长,它最终会调用deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
来将消息分发给注册者执行,这里是第一阶段广播的事件分发。
接着在它的方法中又会调用performReceiveLocked
方法,然后它的方法里面有这样一句话
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
这里的thread
是一个IApplicationThread
对象,它的具体实现是客户端调用者的ApplicationThread
对象,也就是说这里通过binder
将广播消息传回给调用者进程ApplicationThread
,接着看这个对象里面的scheduleRegisteredReceiver
方法
private class ApplicationThread extends IApplicationThread.Stub {
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); //1
}
}
注释1处的receiver
实例就是前面注册广播的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;
if (intent == null) {
..
} else {
rd = mDispatcher.get(); //WeakReference<LoadedApk.ReceiverDispatcher>
}
...
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);
...
if (intent == null || !mActivityThread.post(args.getRunnable()) /*1*/) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
注释1处会调用mActivityThread.post(args.getRunnable())
而mActivityThread
是ActivityThread
中维护的一个内部Handler
,它的实例化在调用者线程,也就是主线程,并且Args
内部 维护了一个getRunnable()
方法,所以最终会在主线程里面执行这个方法
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
...
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
...
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
方法,这里是第二阶段广播的事件分发。
广播发送UML类图如下
到这里整个广播事件注册,发送流程已经完成了,还是很复杂的,简单来看它就是一个订阅–发布的过程,通过map
存储BroadcastReceiver
,当注册广播时候,通过AMS
存放到map
中, 发送广播的时候,通过IntentFilter
去AMS
中查询对应的BroadcastReceiver
,然后通过两次消息分发,以及ReceiverDispatcher
发送给订阅者调用,从而完成整个过程。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。