ActivityManagerService.java
registerReceiver最后一段是这个
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, null, receivers, null, 0, null, null, false, true, true, -1);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
// 发送广播的时候intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
// 就可以把广播放到mFgBroadcastQueue
// 前后台广播主要是超时时间不一样,见[Broadcast (四)有序广播]
BroadcastQueue broadcastQueueForIntent(Intent intent) {
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
"Broadcast intent " + intent + " on "
+ (isFg ? "foreground" : "background") + " queue");
return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
BroadcastQueue.java
//无序广播队列
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
//有序广播队列
final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
r.enqueueClockTime = System.currentTimeMillis();
}
public void scheduleBroadcastsLocked() {
...
// 有很多地方都是这种形式,服务端收到通知,通过Handler异步处理,
// 不至于让客户端挂起太久,服务端处理完毕再发个通知到客户端
// (这时客户端服务端角色就转换了,也就说app和system进程两边经常都是接到通知后就扔给Handler)
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
}
private final class BroadcastHandler extends Handler {
public BroadcastHandler(Looper looper) {
super(looper, null, true);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
processNextBroadcast(true);
} break;
...
}
}
}
final void processNextBroadcast(boolean fromMsg) {
//全程保持AMS锁,其他线程(app进程binder通信)都需要等待此方法处理完毕
synchronized(mService) {
//step1:处理全部无序广播,遍历动态注册的接收者并通知
//step2:获取第一条有序广播
//step3:获取第一个接收者,校验接收者权限
//step4:设置超时时间,通知接收者
}
}
registerReceiver的时候只用到了step1
如果有静态注册的接收者,有序广播也会有数据
step234每次只会处理一条广播一个接收者,app onReceive处理完毕会通知system进程,会再次调用processNextBroadcast
其他step在后续sendBroadcast文章分析
processNextBroadcast→step1
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
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);
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter,
boolean ordered, int index) {
boolean skip = false;
// 如果发送者设置需要权限,
// 就检验接收者是否具有发送者所需的权限,
// 如果没有权限,skip=true
...
if (skip) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
...
// If this is not being sent as an ordered broadcast, then we
// don't want to touch the fields that keep track of the current
// state of ordered broadcasts.
if (ordered) {
r.receiver = filter.receiverList.receiver.asBinder();
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
r.state = BroadcastRecord.CALL_IN_RECEIVE;
if (filter.receiverList.app != null) {
// Bump hosting application to no longer be in background
// scheduling class. Note that we can't do that if there
// isn't an app... but we can only be in that case for
// things that directly call the IActivityManager API, which
// are already core system stuff so don't matter for this.
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceiver = r;
mService.updateOomAdjLocked(r.curApp);
}
}
try {
...
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
...
} catch (RemoteException e) {
...
}
}
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.
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
// DeadObjectException when the process isn't actually dead.
//} catch (DeadObjectException ex) {
// Failed to call into the process. It's dying so just let it die and move on.
// throw ex;
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
+ " (pid " + app.pid + "). Crashing it.");
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} 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);
}
}
一直到结束,并没有设置超时,所以registerReceiver时sticky广播调用onReceive并不会导致ANR(普通广播即sendBroadcast和sendStickyBroadcast的动态注册接收者也只是经过processNextBroadcast→step1)