本文将介绍BroadcastReceiver的工作过程,主要包含两个方面的内容,一个是广播的注册过程,一个是广播的发送和接受过程。
广播的注册过程
首先看下流程图:

广播注册分为静态和动态注册,静态注册是由PMS(PackageManagerService)来实现的,除了广播其他三大组建都是应用安装时由PMS解析并注册的。
这里只分析广播的动态注册,动态注册过程是从ContextWrapper的registerReceiver方法开始的,ContextWrapper并没有实际工作,而是将注册交给了ContextImpl来完成。
1 2 3 
  | public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {     return registerReceiver(receiver, filter, null, null); } 
  | 
 
ContextImpl调用自己的registerReceiverInternal方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 
  | 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) {                     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();             }         }         try {             return ActivityManagerNative.getDefault().registerReceiver(                     mMainThread.getApplicationThread(), mBasePackageName,                     rd, filter, broadcastPermission, userId);         } catch (RemoteException e) {             return null;         }     } 
  | 
 
在上面代码中系统从mPackageInfo中获取IIntentReceiver对象,然后采用跨进成的方式向AMS发送广播注册的请求,之所以采用IIntentReceiver是因为注册是一个进程间通信的过程,IIntentReceiver是一个Binder接口,他的具体实现是LoadedApk.ReceiverDispatcher内部类,该内部类同时保存了BroadcastReceivr和InnerReceiver,这样当接受到广播时,ReceiverDispatcher可以很方便的调用广播的onReceiver方法。
广播的真正实现过程是在AMS中的,AMS的registerReceiver的关键只有下面一部分,最终会把远程的InnerReceiver对象以及IntentFilter对象存储起来。
1 2 3 4 5 6 7 8 9 10 
  | 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);         if (!bf.debugCheck()) {             Slog.w(TAG, "==> For Dynamic broadcast");         } 
  | 
 
这样整个广播的注册过程就完成了。
广播的发送和接受过程
流程图:

当通过send方法来发送广播时,AMS会查找出匹配的广播接受者并将广播发送给他们处理。
广播发送有几种类型:普通广播、有序广播、粘性广播。这里只分析普通广播的实现。
广播的发送开始于ContextImpl的sendBroadcast,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 
  | public void sendBroadcast(Intent intent) {     warnIfCallingFromSystemProcess();     String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());     try {         intent.prepareToLeaveProcess();         ActivityManagerNative.getDefault().broadcastIntent(                 mMainThread.getApplicationThread(), intent, resolvedType, null,                 Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,                 getUserId());     } catch (RemoteException e) {         throw new RuntimeException("Failure from system", e);     } } 
  | 
 
ContextImpl几乎什么都没干,直接向AMS发起一个异步请求发送广播。下面是AMS对广播发送过程的处理。AMS的broadcastIntent的方法源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
  | public final int broadcastIntent(IApplicationThread caller,Intent intent, String resolvedType, IIntentReceiver resultTo,int resultCode, String resultData, Bundle resultExtras,String[] requiredPermissions, int appOp, Bundle options, 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();         int res = broadcastIntentLocked(callerApp,                 callerApp != null ? callerApp.info.packageName : null,                 intent, resolvedType, resultTo, resultCode, resultData, resultExtras,                 requiredPermissions, appOp, null, serialized, sticky,                 callingPid, callingUid, userId);         Binder.restoreCallingIdentity(origId);         return res;     }     } 
  | 
 
broadcastIntent方法又调用了broadcastIntentLocked方法。该方法的开始有这一行代码:
1 2 
  | // By default broadcasts do not go to stopped apps.    intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); 
  | 
 
这表示广播不会发送给已经停止的我应用,从Android3.1开始已经具有这种特性,这是因为在Android3.1中为Intent添加了两个标记,分别是FLAG_EXCLUDE_STOPPED_PACKAGES和FLAG_EXCLUDE_STOPPED_PACKAGES用来控制广播是否对停止应用起作用。
- FLAG INCLUDE STOPPED _ PACKAGES
 
表示包含已经停止的应用,这个时候广播会发送给已经停止的应用
- FLAG EXCLUDE STOPPED _ PACKAGES
 
表示不包含已经停止的应用,这个时候广播不会发送给已经停止的应用。
从3.1开始默认为所有广播添加了FLAG EXCLUDE STOPPED _ PACKAGES标志。
处于停止状态分为两种情形:
- 应用安装后未运行
 
- 应用被手动或其他应用强停。
 
从Android3.1开始处于停止状态的应用同样无法接收到开机广播。
在broadcastIntentLocked内部会根据intentfilter查找匹配的广播接受者,将满足条件的广播添加到BroadcastQueue中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
  | if ((receivers != null && receivers.size() > 0)                 || resultTo != null) {             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);             if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r                     + ": prev had " + queue.mOrderedBroadcasts.size());             if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,                     "Enqueueing broadcast " + r.intent.getAction());             boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);             if (!replaced) {                 queue.enqueueOrderedBroadcastLocked(r);                 queue.scheduleBroadcastsLocked();             }         } 
  | 
 
接着我们来看BroadcastQueue的scheduleBroadcastsLocked方法实现。
1 2 3 4 5 6 7 
  | public void scheduleBroadcastsLocked() {        if (mBroadcastsScheduled) {            return;        }        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));        mBroadcastsScheduled = true;    } 
  | 
 
该方法并没有立即发送广播,而是发送了一个BROADCAST_INTENT_MSG类型的消息。当BroadcastQueue收到消息之后会调用processNextBroadcast方法。该方法对普通广播的处理如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 
  | while (mParallelBroadcasts.size() > 0) {     r = mParallelBroadcasts.remove(0);     r.dispatchTime = SystemClock.uptimeMillis();     r.dispatchClockTime = System.currentTimeMillis();     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);         deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);     }     addBroadcastToHistoryLocked(r);     if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["             + mQueueName + "] " + r); } 
  | 
 
可以看到无序广播存储在mParallelBroadcasts中,系统会遍历该集合并发送给他们的处理者,具体的发送过程是通过deliverToRegisteredReceiverLocked方法来实现,该方法将一个广播发送给一个特定的接受者,它的内部调用了performReceiveLocked方法来完成具体的发送过程,实现如下,由于广播会调起应用程序,因此app.thread不为空app.thread指ApplicationThread。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
  | private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,         Intent intent, int resultCode, String data, Bundle extras,         boolean ordered, boolean sticky, int sendingUser) throws RemoteException {     // Send the intent to the receiver asynchronously using one-way binder calls.     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.             app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,                     data, extras, ordered, sticky, sendingUser, app.repProcState);         } else {             // Application has died. Receiver doesn't exist.             throw new RemoteException("app.thread must not be null");         }     } else {         receiver.performReceive(intent, resultCode, data, extras, ordered,                 sticky, sendingUser);     } } 
  | 
 
该方法会调用ApplicationThread的scheduleRegisteredReceiver,他的实现比较简单,通过InnerReceiver来实现广播的接受。InnerReceiver的performRecerver方法会调用LoadedApk.ReceiverDispatcher的performReceive方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
  |     public void performReceive(Intent intent, int resultCode, String data,             Bundle extras, boolean ordered, boolean sticky, int sendingUser) {         Args args = new Args(intent, resultCode, data, extras, ordered,                 sticky, sendingUser);         if (!mActivityThread.post(args)) {             if (mRegistered && ordered) {                 IActivityManager mgr = ActivityManagerNative.getDefault();                 if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                         "Finishing sync broadcast to " + mReceiver);                 args.sendFinished(mgr);             }         }     } } 
  | 
 
在上面代码中会创建一个Args对象并通过mActivityThread的post方法来执行args中的逻辑,而args实现了Runnable接口。mActivityThread是一个Handler,它其实就是ActivityThread中的mH,mH的类型是ActivityThread的内部类H。在args的run方法中有如下几行代码:
1 2 3 
  | final BroadcastReceiver receiver = mReceiver; receiver.setPendingResult(this); receiver.onReceive(mContext, intent); 
  | 
 
很显然这个时候BroadcastReceiver的onReceiver方法被执行了,也就是说应用已经接收到广播。
到这里这个广播的注册,发送和接受过程已经分析完了,读者应该对广播的整个过程有了一定的理解。
未经许可不得转载,转载请注明zilianliuxue的blog,本人保留所有版权。