本分对广播发送的流程进行分析,主要包括应用端发送广播到广播入队的过程,涉及从发送者进程到 SystemServer 进程的通信。
应用端发送广播
Context 中提供了 sendBroadcast 和 sendOrderedBroadcast 来发送无序和有序广播,最终都是通过 Binder调用了 ActivityManagerService#broadcastIntentLocked
,从发送广播应用进程走到了 SystemServer 进程:
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
| final int broadcastIntentLocked(...) { intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid) != PackageManager.PERMISSION_GRANTED) {...} if (requiredPermissions != null && requiredPermissions.length > 0) {...} if (intent.getComponent() != null) {...} if (userId != UserHandle.USER_ALL) {...} ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); ... } List receivers = null; List<BroadcastFilter> registeredReceivers = null; if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents(...); } int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { ... final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(...); if (!replaced) { queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } registeredReceivers = null; NR = 0; } if ((receivers != null && receivers.size() > 0) || resultTo != null) { BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(...); queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } return ActivityManager.BROADCAST_SUCCESS; }
|
保存黏性广播
当参数 sticky 为 true 时表示发送黏性广播,可以通过 Context#sendStickyBroadcast
发送,需要注册 Manifest.permission.BROADCAST_STICKY
权限,由于具有安全性问题,已经被标记为弃用,因此不推荐使用这种方式。在 ActivityManagerService 中 mStickyBroadcasts 用来保存所有用户当前活跃的黏性广播:
1 2
| final SparseArray<ArrayMap<String, ArrayList<Intent>>> mStickyBroadcasts = new SparseArray<ArrayMap<String, ArrayList<Intent>>>();
|
获取广播队列
无论是处理有序广播还是无序广播,首先都要获取到对应的广播队列:
1 2 3 4 5
| BroadcastQueue broadcastQueueForIntent(Intent intent) { ... final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0; return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue; }
|
这里会根据是否有设置 FLAG_RECEIVER_FOREGROUND
属性来返回前台广播队列 mFgBroadcastQueue 或是后台广播队列 mBgBroadcastQueue,它们都是 BroadcastQueue 类型,在 AMS 的构造函数中初始化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| BroadcastQueue mFgBroadcastQueue; BroadcastQueue mBgBroadcastQueue;
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) { mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_FOREGROUND, false ); mHandlerThread.start(); mHandler = new MainHandler(mHandlerThread.getLooper()); final BroadcastConstants foreConstants = new BroadcastConstants( Settings.Global.BROADCAST_FG_CONSTANTS); foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT; final BroadcastConstants backConstants = new BroadcastConstants( Settings.Global.BROADCAST_BG_CONSTANTS); backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT; mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", foreConstants,false); mBgBroadcastQueue = new BroadcastQueue(this, mHandler, "background", backConstants,true); }
|
可以看到前台广播和后台广播在超时上的区别,分别为 10s 和 60s,在构造 BroadcastQueue 时这里传入的是 AMS 中名为 ActivityManager 的 HandlerThread ,因此 BroadcastQueue 中处理消息都是在这个线程中:
1 2 3 4 5 6 7 8 9 10
| BroadcastQueue(ActivityManagerService service, Handler handler, String name, BroadcastConstants constants, boolean allowDelayBehindServices) { mService = service; mHandler = new BroadcastHandler(handler.getLooper()); mQueueName = name; mDelayBehindServices = allowDelayBehindServices;
mConstants = constants; mDispatcher = new BroadcastDispatcher(this, mConstants, mHandler, mService); }
|
这里还需要注意下的是 mDelayBehindServices,在后台广播中为 true,这个变量主要用于控制是否在应用存在多个后台服务时延迟对广播的继续派发,后面会说到。
广播入队
无序广播通过调用 BroadcastQueue#enqueueParallelBroadcastLocked
来将广播对象 BroadcastRecord 插入到队列中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
public void enqueueParallelBroadcastLocked(BroadcastRecord r) { mParallelBroadcasts.add(r); enqueueBroadcastHelper(r); }
private void enqueueBroadcastHelper(BroadcastRecord r) { r.enqueueClockTime = System.currentTimeMillis(); if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) { Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING), System.identityHashCode(r)); } }
private String createBroadcastTraceTitle(BroadcastRecord record, int state) { return String.format("Broadcast %s from %s (%s) %s",...); }
|
无序广播队列中通过 ArrayList 来保存广播对象,有序广播是通过 BroadcastDispatcher 来完成广播的分发,广播对象也是保存在 ArrayList 中:
1 2 3 4 5 6 7 8 9 10
| public void enqueueOrderedBroadcastLocked(BroadcastRecord r) { mDispatcher.enqueueOrderedBroadcastLocked(r); enqueueBroadcastHelper(r); }
private final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>(); void enqueueOrderedBroadcastLocked(BroadcastRecord r) { mOrderedBroadcasts.add(r); }
|