最近有些人对android的Broadcast机制颇有兴趣,因此小弟就把自己看到的背后原理跟各位分享.Android的发送广播跟接收机制其实就是一种Publish/subscribepattern, Publish(发布者)只会将不同类型的讯息传送出去,并不会在意subscribe(订阅者),而subscribe(订阅者)只在意想接收的讯息,并不会在意谁是Publish(发布者). 所以Android的broadcast的核心机制大概可分为Broadcast publish, Broadcast subscribe和Broadcast content.就先从注册Broadcast subscribe也就是Broadcast reciever的流程来看吧.
1 RegisterReceiver flow
要注册Android Broadcast receiver有两种形式, 一为动态注册,一为静态注册.静态注册是在AndroidManifest.xml上多一个receiver tag
来指定,在编译android app就指定好了, 而动态注册则会利用Context的一个registerReceiver方法来注册是属于在执行的时候
才会指定特定的receiver.由程序代码来看, Context是一个abstract class所以是一个抽象接口,因此registerReceiver是一个抽象方法.
ContextImpl 是 Context的一个实现类别, 因此registerReceiver的实作就在ContextImpl class里
[ContextImpl.java]
@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()); } |
Android在程序代码的设计有个很有趣的地方,那就是一旦牵扯到核心的流程,都会取个xxxInternal为名子的方法来实作.
在这个registerReceiverInternal方法中只做两件事,先将传入reciever包装产生一个IIntentReceiver, 然后再将IIntentReceiver传送给Activity Manager service 去注册.顾名思义就是在Activity thread上注册一个subscribe(订阅者),用来接收特定讯息.
[ContextImpl.java]
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { IIntentReceiver rd = null; if (receiver != null) { […] rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { […] rd = new LoadedApk.ReceiverDispatcher( receiver, context, scheduler, null, true).getIIntentReceiver(); } } try { final Intent intent = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); […] return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } |
其中mPackageInfo是一个LoadedApk的对象, 因此可以到LoadedApk class里看getReceiverDispatcher方法的实作
[LoadedApk.java]
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 (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); }
[…] return rd.getIIntentReceiver(); } } |
由实作可以知道, 此方法会先产生一个receiver的ReceiverDispatcher然后再产生一个ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>来做管理.最后会执行ReceiverDispatcher的getIIntentReceiver方法.因此上面registerReceiverInternal所产生的IIntentReceiver对象是由ReceiverDispatcher准备的.在这里值得要说的是在Android的设计中,大部分IXXX开头的都是一个
Binder interface, 甚么是Binder interface简单来说就是一道两个Process的通道.Binder 的详细运作不是这次的分享,所以有兴趣的可以自己Google.由getIIntentReceiver方法回传的IItentReciever是一道Receiver Binder interface.
[LoadedApk.java]
static final class ReceiverDispatcher { […] final IIntentReceiver.Stub mIIntentReceiver; […] ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) { […] mIIntentReceiver = new InnerReceiver(this, !registered); […] } […] } |
由上面的程序代码可知,mIIntentReceiver确实是一道Binderinterface, 这一道Binderinterface里面的运作是由InnerReceiverclass来实作的.到此为止是建立了一道Receiver binder interface(InnerReceiver), 接下来就是藉由Activity manager service来注册这一道InnerReceiver.
由registerReceiverInternal方法的程序代码来看, 要注册InnerReciever会执行
ActivityManagerNative.getDefault().registerReceiver |
ActivityManagerNative. getDefault()这是一个Activity manager service的proxy.请看以下分析
[ActivityManagerNative.java]
static public IActivityManager getDefault() { return gDefault.get(); }
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); if (false) { Log.v("ActivityManager", "default service binder = " + b); } IActivityManager am = asInterface(b); if (false) { Log.v("ActivityManager", "default service = " + am); } return am; } }; |
由上面的程序代码可以知道,最后是一个IActivitManger的Activity Manger service Binder interface.这道binder interface通常称为binder proxy.所以大胆推测ActivityManagerNative里面的method都是用来使用Activity manager service的一道媒介.现在就直接来看ActivityManagerNative class的registerReceiver方法
[ActivityManagerNative.java]
public Intent registerReceiver(IApplicationThread caller, String packageName, IIntentReceiver receiver, IntentFilter filter, String perm, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); […] mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0); […] } |
mRemote.transact这一行程序代码就是要做Bindertransaction, 里面的参数就是IPCdata,经由这一道程序代码,Binder driver就会把REGISTER_RECEIVER_TRANSACTION request送给指定的service,这个service会需要看mRemote是指向哪一个 service.
[ActivityManagerNative.java]
static public IActivityManager asInterface(IBinder obj) { if (obj == null) { return null; } IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor); if (in != null) { return in; }
return new ActivityManagerProxy(obj); }
[…]
class ActivityManagerProxy implements IActivityManager { public ActivityManagerProxy(IBinder remote) { mRemote = remote; } […] } […] |
由上面的程序代码可以知道,mRemote是由asInterface这个方法的参数所带进来的, 而asInterface这个方法是在上面要产生ActivityManger service Binder interface就会执行到, 要传入给asInterface方法的参数是由
IBinder b = ServiceManager.getService("activity"); |
这行程序代码产生, 其中的b就是activity manager service的BpBinder.所以mRemote就是activity manager service的BpBinder.因此Binder driver就会把REGISTER_RECEIVER_TRANSACTIONrequest传给Activitymanager service.
在javaframework layer中, 要接收Binder driver传送来的request都会继承一个Binder class, 里面有一个method onTransact就是用来作为接收器.
[ActivityManagerNative.java]
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { […] case REGISTER_RECEIVER_TRANSACTION: // 读取IPC data Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId); // 写入回传状态 […] } return super.onTransact(code, data, reply, flags); } |
最后终于来到了Activitymanager service的registerReceivermethod
[ActivityManagerService.java]
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
[…] mRegisteredReceivers.put(receiver.asBinder(), rl); […] BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); // rl 是一个ReceiverList data. […] mReceiverResolver.addFilter(bf); // mReceiverResolver是一个IntentResolver<BroadcastFilter, BroadcastFilter> data […] } |
由此可知Activitymanager service会用个mRegisteredReceivers将IIntentReceiver放进Receiver list.最后在执行mReceiverResolver的addFilter新增一个BroadcastFilter.之后在发送讯息阶段时,就会利用mReceiverResolver来做传送媒介.
由上面的分析可以做一个总结
1. Broadcast receiver 只是一个简单的抽象类,并没有进程的通讯机制也就是Binder机制.
2. 要从Binderdriver接收讯息会需要借助InnerReceiver这一个receiver binder interface.因此LoadedApk要将BroadcastReceiver和InnerReceiver做个Map来管理.
3. Activity manager service在将InnerReceiver记录在一个Receiver list来做维护,之后再跟IntentFilter包装成一个mReceiverResolver.
4. 整个Registerreceiver的核心都在Activitymanager service完成.
2. Send broadcast message flow
一般要发送广播消息都会用到Context的sendBroadcast, 而Context是一个abstract class, 所以实作需要看Context的实作类别ContextImpl
[ContextImpl.java]
public void sendBroadcast(Intent intent, String receiverPermission) { […] ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, getUserId()); […] } |
[ActivityManagerNative.java]
public int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String[] requiredPermissions, int appOp, Bundle options, boolean serialized, boolean sticky, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); […] mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0); […] }
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { […] case BROADCAST_INTENT_TRANSACTION: // 读取IPC data int res = broadcastIntent(app, intent, resolvedType, resultTo, resultCode, resultData, resultExtras, perms, appOp, options, serialized, sticky, userId); // 写入回传状态 return true; […] } return super.onTransact(code, data, reply, flags); } |
[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) { […] 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; }
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) {
[…] // Figure out who all will receive this broadcast. List receivers = null; List<BroadcastFilter> registeredReceivers = null;
[…] registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId); // mReceiverResolver 是一个在register broadcast 阶段所产生的一个IntentResolver<BroadcastFilter, BroadcastFilter> data. 此方法会回传一个 BroadcastFilter list. […] int NR = registeredReceivers != null ? registeredReceivers.size() : 0; […] final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); […] queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); […] while (ir < NR) { if (receivers == null) { receivers = new ArrayList(); } receivers.add(registeredReceivers.get(ir)); ir++; } […] BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, resolvedType, requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode, resultData, resultExtras, ordered, sticky, false, userId); queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); […] return ActivityManager.BROADCAST_SUCCESS; } |
由上面的执行流程,若指定为发送有次序的广播消息就会先执行BroadcastQueue 的enqueueOrderedBroadcastLocked方法. 若为一般的发送广播消息就会先执行BroadcastQueue 的enqueueParallelBroadcastLocked. 但不管是哪一个方法, 最后都会执行BroadcastQueue 的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; } |
其中mHandler是BroadcastHandler的reference.
[BroadcastQueue.java]
private final class BroadcastHandler extends Handler { […] @Override public void handleMessage(Message msg) { […] case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Slog.v( TAG_BROADCAST, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; […] } […] } |
[BroadcastQueue.java]
final void processNextBroadcast(boolean fromMsg) { […] BroadcastRecord r; […] if (fromMsg) { mBroadcastsScheduled = false; } […] while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); […] 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); } addBroadcastToHistoryLocked(r); } […] } |
其中 mParallelBroadcasts是一串BroadcastRecord的list. r.receivers是一个BroadcastRecord中的包含BroadcastFilter 和ResolveInfo 的list.
[BroadcastQueue.java]
private void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { […] performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); […] } |
[BroadcastQueue.java]
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { […] receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); […] } |
到最后终于要执行Receiverbinder interface IItentReceiver来传送广播消息了.
[LoadedApk.java]
static final class ReceiverDispatcher { final static class InnerReceiver extends IIntentReceiver.Stub { […] @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { […] rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); […] } } […] } |
其中rd是LoadedApk.ReceiverDispatcher一个reference, 此ReceiverDispatcher在register broadcast receiver阶段就已经准备好了.
[LoadedApk.java]
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)) { […] } } |
其中mActivityThread是一个activity thread的handler 的reference.而Args是一个runnable的handler task.所以mActivityThread.post这一行是利用Activity thread的handler来执行Args task.
[LoadedApk.java]
final class Args extends BroadcastReceiver.PendingResult implements Runnable { […] public void run() { final BroadcastReceiver receiver = mReceiver; […] ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent);
} } |
其中mReceiver在建构ReceiverDispatcher时就藉由参数传进来了.
[LoadedApk.java]
ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) { if (activityThread == null) { throw new NullPointerException("Handler must not be null"); }
mIIntentReceiver = new InnerReceiver(this, !registered); mReceiver = receiver; mContext = context; mActivityThread = activityThread; mInstrumentation = instrumentation; mRegistered = registered; mLocation = new IntentReceiverLeaked(null); mLocation.fillInStackTrace(); } |
由此可知这个receiver就是一开始在register receiver阶段就决定好了.
由上面的分析可以做一个总结
1. 从 mReceiverResolver寻找出一串 BroadcastFilterlist. 此BroadcastFilter是在regiester receiver阶段就产生了.
2. 将这一串BroadcastFilterlist包装成BroadcastRecord,在直接传给BroadcastQueue的enqueueParallelBroadcastLocked方法做发送广播消息的准备.
3. 执行BroadcastQueue的scheduleBroadcastsLocked方法开始发送广播消息.
4. 从BroadcastRecord中取得包含BroadcastFilter 和ResolveInfo 的list.
5. 从list中取得辅合条件的BroadcastFilter, BroadcastFilter中在register receiver 阶段就会包含特定的ReceiverList,这个ReceiverList就是IIntentReceiver的一个包装对象.因此可以从这个取得的BroadcastFilter得到相对应的IIntentReceiver也就是Receiver binder interface(InnerReceiver)
6. 执行Receiverbinder interface(InnerReceiver) 的 performReceive方法
7. 执行ReceiverDispatcher的performReceive方法,此方法只是单纯的利用Activity thread的handler来执行ReceiverDispatcher准备好的Args task.
8. 由于在registerreceiver阶段就经由产生ReceiverDispatcher时把BroadcastReceiver指定为ReceiverDispatcher的属性mReceiver, 所以在执行Args task,就直接执行BroadcastReceiver的onReceive的方法.这个onReceive也就是由Application实作的onReceive 方法.