本分对广播分发的流程进行分析,主要包括广播入队后对于广播分发给各个接收者的过程以及接收者处理广播的过程,流程比较长,涉及 SystemServer 进程到接收者进程的通信。
AMS 分发 广播的分发统一都是通过 com.android.server.am.BroadcastQueue#scheduleBroadcastsLocked()
:
1 2 3 4 5 6 7 8 final BroadcastHandler mHandler;public void scheduleBroadcastsLocked () { if (mBroadcastsScheduled) { return ; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this )); mBroadcastsScheduled = true ; }
mHandler 是使用 AMS 中的 HandlerThread 的 Looper,因此这里流程就从 SystemServer 的 Binder 线程切换到了 HandlerThread 中,mHandler 中处理 BROADCAST_INTENT_MSG 会调用到 processNextBroadcast()
:
1 2 3 4 5 final void processNextBroadcast (boolean fromMsg) { synchronized (mService) { processNextBroadcastLocked(fromMsg, false ); } }
processNextBroadcastLocked()
会一直持有 mService 对象锁,因为广播分发的逻辑主要都在这里,因此这部分逻辑比较长,一步一步来看:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 final void processNextBroadcastLocked (boolean fromMsg, boolean skipOomAdj) { BroadcastRecord r; if (fromMsg) { mBroadcastsScheduled = false ; } while (mParallelBroadcasts.size() > 0 ) { r = mParallelBroadcasts.remove(0 ); r.dispatchTime = SystemClock.uptimeMillis(); for (int i=0 ; i<r.receivers.size(); i++) { Object target = r.receivers.get(i); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false , i); } } if (mPendingBroadcast != null ) { ... } do { r = mDispatcher.getNextBroadcastLocked(now); if (r == null ) {...} if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0 ) {...} if (r.state != BroadcastRecord.IDLE) return ; if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { performReceiveLocked(...); cancelBroadcastTimeoutLocked(); mDispatcher.retireBroadcastLocked(r); r = null ; continue ; } ... } while (r == null ); int recIdx = r.nextReceiver++; r.receiverTime = SystemClock.uptimeMillis(); if (recIdx == 0 ) { r.dispatchTime = r.receiverTime; r.dispatchClockTime = System.currentTimeMillis(); } if (!mPendingBroadcastTimeoutMessage) { long timeoutTime = r.receiverTime + mConstants.TIMEOUT; setBroadcastTimeoutLocked(timeoutTime); } final Object nextReceiver = r.receivers.get(recIdx); if (nextReceiver instanceof BroadcastFilter) { BroadcastFilter filter = (BroadcastFilter)nextReceiver; deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx); return ; } ResolveInfo info = (ResolveInfo)nextReceiver; r.manifestCount++; r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED; r.state = BroadcastRecord.APP_RECEIVE; r.curComponent = component; r.curReceiver = info.activityInfo; if (app != null && app.thread != null && !app.killed) { processCurBroadcastLocked(r, app, skipOomAdj); return ; } if ((r.curApp=mService.startProcessLocked(...)) == null ) { finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false ); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return ; } maybeAddAllowBackgroundActivityStartsToken(r.curApp, r); mPendingBroadcast = r; mPendingBroadcastRecvIndex = recIdx; }
这里先是通过 deliverToRegisteredReceiverLocked()
来分发无序广播,接着处理有序广播,优先是动态注册的接收者,也是通过 deliverToRegisteredReceiverLocked()
来分发,而静态注册的接收者则是通过 processCurBroadcastLocked()
分发:
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 29 30 private void deliverToRegisteredReceiverLocked (BroadcastRecord r, BroadcastFilter filter, boolean ordered, int index) { ... if (ordered) { ... r.state = BroadcastRecord.CALL_IN_RECEIVE; } performReceiveLocked(...); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } ... } void performReceiveLocked (ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser)throws RemoteException { if (app != null ) { if (app.thread != null ) { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.getReportedProcState()); } else { throw new RemoteException("app.thread must not be null" ); } } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } }
因为 IIntentReceiver.aidl 和 IApplicationThread.aidl 都是由 oneway 关键字修饰,因此这里调用后就会立即返回,不会等到接收者进程处理完成:
1 2 3 4 5 6 7 8 9 oneway interface IIntentReceiver { @UnsupportedAppUsage void performReceive (in Intent intent, int resultCode, String data, in Bundle extras, boolean ordered, boolean sticky, int sendingUser) ;} oneway interface IApplicationThread { ... }
这里如果获取到了对应进程,则通过 ApplicationThread 来分发主要是为了保证所有的接收者可以按照顺序进行接收,其内部还是调用了IIntentReceiver#performReceive
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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); } ... }
接收者进程处理 至此就是从 SystemServer 进程走到了接收者进程的 Binder 线程中 ,之前看到 IIntentReceiver 在服务端的实现是 android.app.LoadedApk.ReceiverDispatcher.InnerReceiver:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 static final class ReceiverDispatcher { final static class InnerReceiver extends IIntentReceiver .Stub { final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; @Override public void performReceive (Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); if (rd != null ) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { IActivityManager mgr = ActivityManager.getService(); mgr.finishReceiver(this , resultCode, data, extras, false , intent.getFlags()); } } } final class Args extends BroadcastReceiver .PendingResult {..} final IIntentReceiver.Stub mIIntentReceiver; ReceiverDispatcher(BroadcastReceiver receiver, Context context, Handler activityThread, Instrumentation instrumentation, boolean registered) { mIIntentReceiver = new InnerReceiver(this , !registered); } @UnsupportedAppUsage IIntentReceiver getIIntentReceiver () { return mIIntentReceiver; } public void performReceive (Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { final Args args = new Args(...); if (intent == null || !mActivityThread.post(args.getRunnable())) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManager.getService(); args.sendFinished(mgr); } } } }
Args 也是 ReceiverDispatcher 的内部类,其 getRunnable 方法返回一个 Runnanle 对象,主要逻辑如下:
1 2 3 4 5 6 7 8 9 10 11 public final Runnable getRunnable () { return () -> { final IActivityManager mgr = ActivityManager.getService(); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg" ); receiver.onReceive(mContext, intent); if (receiver.getPendingResult() != null ) { finish(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); }; }
这里主要做了两件事:调用接收者的 onReceive 方法并主动通过调用 finish() 来结束处理,可以通过关键字 broadcastReceiveReg 在分析 Systrace 时快速定位到这里。这里也是一个广播 ANR 容易发生的地方,如果当前 handler 中一直有耗时任务在处理,还不等到执行 onReceive 就会报 ANR。
接收者进程完成处理 Args 是继承自 BroadcastReceiver.PendingResult 的,自身并没有覆写 finish 方法:
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 29 30 public final void finish () { if (mType == TYPE_COMPONENT) { final IActivityManager mgr = ActivityManager.getService(); if (QueuedWork.hasPendingWork()) { QueuedWork.queue(new Runnable() { @Override public void run () { sendFinished(mgr); } }, false ); } else { sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { final IActivityManager mgr = ActivityManager.getService(); sendFinished(mgr); } } public void sendFinished (IActivityManager am) { synchronized (this ) { if (mFinished) { throw new IllegalStateException("Broadcast already finished" ); } mFinished = true ; am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast, mFlags); } }
这里对静态注册和动态注册的广播处理有些许不同,但最后都是需要调用到 AMS 这边:
1 2 3 4 5 6 7 8 9 10 11 12 13 public void finishReceiver (IBinder who, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, int flags) { queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0 ? mFgBroadcastQueue : mBgBroadcastQueue; BroadcastRecord r = queue.getMatchingOrderedReceiver(who); if (r != null ) { doNext = r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, true ); } if (doNext) { r.queue.processNextBroadcastLocked( false , true ); } }
finishReceiverLocked 中主要是对状态的一些重置工作:
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 29 30 31 32 33 34 35 36 public boolean finishReceiverLocked (BroadcastRecord r, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) { r.state = BroadcastRecord.IDLE; final ActivityInfo receiver = r.curReceiver; r.receiver = null ; r.curReceiver = null ; r.curApp = null ; mPendingBroadcast = null ; if (resultAbort && (r.intent.getFlags()&Intent.FLAG_RECEIVER_NO_ABORT) == 0 ) { r.resultAbort = resultAbort; } else { r.resultAbort = false ; } if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices && r.queue.mDispatcher.getActiveBroadcastLocked() == r) { ActivityInfo nextReceiver; if (receiver == null || nextReceiver == null || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid || !receiver.processName.equals(nextReceiver.processName)) { if (mService.mServices.hasBackgroundServicesLocked(r.userId)) { Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString()); r.state = BroadcastRecord.WAITING_SERVICES; return false ; } } } r.curComponent = null ; return state == BroadcastRecord.APP_RECEIVE || state == BroadcastRecord.CALL_DONE_RECEIVE; }
这里主要做了以下事情:
重置广播中的一些属性,例如 receiver 等以及 mPendingBroadcast
如果中止广播,则判断是否有设置 FLAG_RECEIVER_NO_ABORT 属性来不允许中止
判断当前后台服务是否已经运行的够多,如果是则延迟处理后台广播的分发
如果此时广播已经调用完成了 BroadcastQueue#processNextBroadcastLocked 或者是 BroadcastQueue#performReceiveLocked,即状态此时为 APP_RECEIVE 或是 CALL_DONE_RECEIVE,则去处理下一个接收者
参考 Android Developer:广播概览