本文将介绍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,本人保留所有版权。