目录
- 广播发送与派发整体流程简介
- sendBroadcast时序图
- 源码解析
- 总结
1. 广播发送与派发整体流程简介
从上一节广播的注册,可以知道广播机制是典型的观察者模式,那么通知所有receiver的时机具体是什么时候呢,答案就是在发送广播的时候,广播一发送,此时就应该通知所有已经注册的观察者,也就是已经注册的receiver。整个广播的派发的流程其实就是逐个通知观察者的过程。而这整体的流程主要都在BroadcastQueue中经过调度之后派发给各个注册的receiver,最终回调到APP进程中已注册的receiver的onReceive方法。
注:本文基于Android 8.1。
2. sendBroadcast时序图

- 上面的流程中,主要涉及到的进程有发送APP的进程,systemserver进程,以及接收广播的进程
- 图中11~18的过程是动态注册的广播的派发(包括有序和无序)
- 图中19~24的过程是静态注册的派发,静态注册的广播默认都以有序广播形式派发
- BroadcastHandler调度线程是用的ActivityManager线程
3. 源码解析
3.1 ContextImpl.sendBroadcast
客户端通过context发送广播,都会调用到ContextImpl.sendBroadcast去实现广播的发送,而且不管是发送有序广播还是无序广播,最终发起binder call的方法都是一致的。
sendBroadcast
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
sendOrderedBroadcast
void sendOrderedBroadcast(Intent intent,
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras, Bundle options) {
warnIfCallingFromSystemProcess();
IIntentReceiver rd = null;
// 相比于发送无序广播,有序广播最重要区别就在
// 有序广播可以有一个resultRceiver,也就是可以指定这个广播的最后一个接收者
// 有序广播是逐个派发的,因此通过最后一个接收者可以知道广播派发完毕了,做一些收尾工作
if (resultReceiver != null) {
if (mPackageInfo != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler,
mMainThread.getInstrumentation(), false);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
}
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermissions, appOp,
options, true, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
上面resultReceiver跟receiver的注册有些类似,这也正是有序广播相对与无序广播多出来的部分,多了最后的InnerReceiver,保证本次发送的所有广播执行结束之后,调用这个广播。
3.2 ActivityManagerService.broadcastIntent
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions,
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, bOptions, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
参数解析:
caller:发送方的applicationThread对象
intent:本次发送的广播所带的intent
resolvedType:根绝intent schema判断类型
resultTo:最终接受的receiver
resultCode:有序广播在一个receiver处理之后可以设置值,这样下一个receiver就可以拿到这个数据
resultData:作用同上面的code,是string类型的数据
resultExtras:作用同上面的code,是Bundle类型数据
requiredPermissions:接收这个广播需要的权限
appOp:接受这个广播需要的AppopsManager权限
bOptions:设置在这个广播发送的时候将某个package放入到deviceIdle白名单中,有时长限制
serialized:是否为有序广播
sticky:是否为sticky广播
userId:这个广播将要发送到的user
3.3 ActivityManagerService.broadcastIntentLocked
final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
// Intent支持跨进程传输,保证互不干扰,此处创建新的Intent对象
intent = new Intent(intent);
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
if (callerInstantApp) {
// 如果caller是instant app,则不能使用FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS
// 即instant app不能发送给instant app可见的广播
intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
// 默认情况下,广播不会发送给处于stop状态下的package
// 应用在安装后从来没有启动过,或者已经被用户强制停止了,那么这个应用就处于停止状态
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 如果开机还没有完成,且没有带升级状态可接受的flag,那么添加FLAG_RECEIVER_REGISTERED_ONLY
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
...
// user校验
// 参数中的bOptions会改变deviceidle的临时白名单
// 因此需要查看caller是否有改变deviceidle名单的权限
BroadcastOptions brOptions = null;
if (bOptions != null) {
brOptions = new BroadcastOptions(bOptions);
if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
if (checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
}
}
// 确保protectBroadcast广播只能由某些特定的发送者发送
// 主要是root/system/phone/bluetooth/nfc这些uid
// 以及persist应用可以发送
final String action = intent.getAction();
final boolean isProtectedBroadcast;
try {
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
return ActivityManager.BROADCAST_SUCCESS;
}
final boolean isCallerSystem;
switch (UserHandle.getAppId(callingUid)) {
case ROOT_UID:
case SYSTEM_UID:
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
isCallerSystem = true;
break;
default:
isCallerSystem = (callerApp != null) && callerApp.persistent;
break;
}
if (!isCallerSystem) {
// protectBroadcast只能由系统发送
if (isProtectedBroadcast) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from pid="
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
// 对于这些比较特殊的广播,不允许caller为null
if (callerPackage == null) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " from unknown caller.";
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else if (intent.getComponent() != null) {
// 如果component不为空,则必须要求所设置的component的package和caller一致
if (!intent.getComponent().getPackageName().equals(
callerPackage)) {
String msg = "Permission Denial: not allowed to send broadcast "
+ action + " to "
+ intent.getComponent().getPackageName() + " from "
+ callerPackage;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
} else {
// 如果component为空则只能发送给自己
intent.setPackage(callerPackage);
}
}
}
if (action != null) {
if (getBackgroundLaunchBroadcasts().contains(action)) {
// 判断允许在后台应用可以接受的广播的action列表中有没有这个action
// 如果有,即允许这个广播被后台应用接收,则添加flag
// 默认的action都是不带这个flag的,所以默认不允许后台应用接收广播
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
}
// 此处对某些的action进行特殊处理
switch (action) {
...
// 主要是针对package相关的广播做了特殊处理,这里不再罗列,有兴趣可以自己翻看源码
}
}
// 处理sticky广播
if (sticky) {
// sticky广播需要在manifest中声明BROADCAST_STICKY权限
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
callingPid, callingUid)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid="
+ callingPid + ", uid=" + callingUid
+ " requires " + android.Manifest.permission.BROADCAST_STICKY;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
// Sticky广播不能有权限要求
if (requiredPermissions != null && requiredPermissions.length > 0) {
Slog.w(TAG, "Can't broadcast sticky intent " + intent
+ " and enforce permissions " + Arrays.toString(requiredPermissions));
return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
// Sticky广播必须有component
if (intent.getComponent() != null) {
throw new SecurityException(
"Sticky broadcasts can't target a specific component");
}
if (userId != UserHandle.USER_ALL) {
// 校验对于当前的这个对单个user的广播 和现有的针对所有user的广播不冲突
// 也就是说一个sticky广播不能同时针对单个user又针对user_all
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(
UserHandle.USER_ALL);
if (stickies != null) {
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list != null) {
int N = list.size();
int i;
for (i=0; i<N; i++) {
if (intent.filterEquals(list.get(i))) {
throw new IllegalArgumentException(
"Sticky broadcast " + intent + " for user "
+ userId + " conflicts with existing global broadcast");
}
}
}
}
}
// 将sticky广播放入mStickyBroadcasts
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
if (stickies == null) {
stickies = new ArrayMap<>();
mStickyBroadcasts.put(userId, stickies);
}
ArrayList<Intent> list = stickies.get(intent.getAction());
if (list == null) {
list = new ArrayList<>();
stickies.put(intent.getAction(), list);
}
final int stickiesCount = list.size();
int i;
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
// 如果能找到对应的sticky广播,则进行替换
// 因为sticky广播是在注册者一注册就把最近的u一个发出去了
// 所以对于同一个sticky广播需要记录下,如果有重复,则替换
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
// 没有找到则添加
list.add(new Intent(intent));
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {
// Caller wants broadcast to go to all started users.
users = mUserController.getStartedUserArrayLocked();
} else {
// Caller wants broadcast to go to one specific user.
users = new int[] {userId};
}
// 开始查找注册了这个广播的receiver
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
// 查找静态注册的receiver,resolvedType在此查询时处生效
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
// 对于shell发送的user_all的广播
for (int i = 0; i < users.length; i++) {
if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
// 默认情况下,只针对当前user注册的广播生效
// 查找动态注册的广播
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
}
}
// 如果带有FLAG_RECEIVER_REPLACE_PENDING
// 表示如果这个广播还没有派发,则替换掉之前的广播
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 处理并行广播
if (!ordered && NR > 0) {
if (isCallerSystem) {
// 对于系统发送的广播进行校验
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, registeredReceivers);
}
// 创建BroadcastRecord并入队
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// 不需要替换的情况下,入队并派发
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// Merge into one list.
int ir = 0;
if (receivers != null) {
// 对特殊的广播,检查条件,不满足条件的从receiver的列表中移除
String skipPackages[] = null;
// ACTION_PACKAGE_ADDED广播
if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
Uri data = intent.getData();
if (data != null) {
String pkgName = data.getSchemeSpecificPart();
if (pkgName != null) {
skipPackages = new String[] { pkgName };
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
}
if (skipPackages != null && (skipPackages.length > 0)) {
for (String skipPackage : skipPackages) {
if (skipPackage != null) {
int NT = receivers.size();
for (int it=0; it<NT; it++) {
ResolveInfo curt = (ResolveInfo)receivers.get(it);
if (curt.activityInfo.packageName.equals(skipPackage)) {
receivers.remove(it);
it--;
NT--;
}
}
}
}
}
// 静态注册的广播可以在manifest中指定优先级
// 根据priority进行排序,优先级高的排在前面
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null;
BroadcastFilter curr = null;
// 如果是并行广播,经过前面处理,那此处NR就已经等于0了,等于只对静态注册的排序
// 如果是串行广播,此处经过排序后合并
while (it < NT && ir < NR) {
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
if (curr.getPriority() >= curt.priority) {
receivers.add(it, curr);
ir++;
curr = null;
it++;
NT++;
} else {
it++;
curt = null;
}
}
}
// 合并之后,如果动态注册的receiver中还有,则全部依次添加在后面
while (ir < NR) {
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}
if (isCallerSystem) {
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, receivers);
}
// 开始入队
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
// 根据广播是否带有fg的flag决定是要入前台广播队列还是后台广播队列
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId);
// 如果需要替换之前的广播则进行查找并替换
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
// 如果替换了之前的广播,那么要执行之前广播的resultToReceiver
if (oldRecord.resultTo != null) {
final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
try {
oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
oldRecord.intent,
Activity.RESULT_CANCELED, null, null,
false, false, oldRecord.userId);
} catch (RemoteException e) {
Slog.w(TAG, "Failure ["
+ queue.mQueueName + "] sending broadcast result of "
+ intent, e);
}
}
} else {
// 如果没有替换,则添加到有序队列,并开始调度
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
} else {
// 没有找到receiver,仅仅记录
if (intent.getComponent() == null && intent.getPackage() == null
&& (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
这段代码看起来很长,但是仔细捋一遍其中的大致流程其实也是很容易理解的
- 添加一些默认的flag
- user状态校验
- 如果要改变temp deviceidle名单,进行权限校验
- protectBroadcast的caller校验
- 特殊action广播特殊处理
- sticky广播处理
- 动态注册的并行广播处理入队
- 静态注册广播以及动态注册有序广播根据优先级排序后入队
- 开始调度
- 在AMS初始化的时候默认创建了两个队列,一个是前台广播队列,一个是后台广播队列
- 在每个队列中又有并行广播队列以及串行广播队列
- 有序广播队列的超时:前台广播队列10s,后台广播队列60s
3.4 BroadcastQueue.scheduleBroadcastsLocked
// 广播调度开始
public void scheduleBroadcastsLocked() {
// 如果已经开始了就先return等待
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
3.5 BroadcastHandler.handleMessage
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
此处的handler的线程用的是ActivityManager线程
3.6 BroadcastQueue.processNextBroadcast
这个是广播调度派发的核心方法
// 开始派发
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
mService.updateCpuStats();
if (fromMsg) {
mBroadcastsScheduled = false;
}
// 首先派发并行广播
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
// 可以看到,并行广播的派发非常简单,直接一个for循环
// deliverToRegisteredReceiverLocked中的处理还是比较简单的
// 主要是进行了一系列权限的校验,之后调度到app进程
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
// 添加到广播历史记录
addBroadcastToHistoryLocked(r);
}
// 这个是一个记录,如果在派发广播时需要启动进程的话,会用这个先记录下来
// 等到进程启动之后再处理
if (mPendingBroadcast != null) {
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
// 如果进程不存在,retrun,继续等待
// 在进程启动之后的attachApplication中会进行处理此广播
// 后面的章节中会有Android进程管理部分,也会讲述此部分的处理
if (!isDead) {
return;
} else {
Slog.w(TAG, "pending app ["
+ mQueueName + "]" + mPendingBroadcast.curApp
+ " died before responding to broadcast");
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
do {
// 如果有序广播队列中已经没有需要派发的广播了
// 说明所有广播已经派发完毕
if (mOrderedBroadcasts.size() == 0) {
mService.scheduleAppGcsLocked();
if (looped) {
mService.updateOomAdjLocked();
}
return;
}
// 从有序广播队列中取出第一个
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;
// 此处是判断这个广播的超时
// 一个有序广播,所有的receiver的派发时间加起来
// 不能大于2 * mTimeoutPeriod * numReceivers
// mTimeoutPeriod是本广播队列的超时,前台广播队列10s,后台广播队列60s
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
if (mService.mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
Slog.w(TAG, "Hung broadcast ["
+ mQueueName + "] discarded after timeout failure:"
+ " now=" + now
+ " dispatchTime=" + r.dispatchTime
+ " startTime=" + r.receiverTime
+ " intent=" + r.intent
+ " numReceivers=" + numReceivers
+ " nextReceiver=" + r.nextReceiver
+ " state=" + r.state);
broadcastTimeoutLocked(false);
// 如果已经超时,那标志forceReceive
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
if (r.state != BroadcastRecord.IDLE) {
return;
}
// 这个广播没有更多的receiver了,或者被打断了
// 或者被上面因为超时强制停止了
// 此时需要直接执行resultReceiver(发送有序广播时指定的最后一个receiver)
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
if (r.resultTo != null) {
try {
performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false, false, r.userId);
r.resultTo = null;
} catch (RemoteException e) {
r.resultTo = null;
Slog.w(TAG, "Failure ["
+ mQueueName + "] sending broadcast result of "
+ r.intent, e);
}
}
// 已经在执行最后一个receiver了,取消超时的计时
cancelBroadcastTimeoutLocked();
// 记录到history
addBroadcastToHistoryLocked(r);
if (r.intent.getComponent() == null && r.intent.getPackage() == null
&& (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
}
// 从有序广播队列中移除
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while (r == null);
// 经过了上面的do-while循环,取出来的就是马上要派发的广播了
// 一个广播会有多个receiver,这个是用来记录当前派发的数量的
int recIdx = r.nextReceiver++;
r.receiverTime = SystemClock.uptimeMillis();
// 这个广播第一次派发,记录时间
if (recIdx == 0) {
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
}
// 记录超时,超时后会触发ANR
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
setBroadcastTimeoutLocked(timeoutTime);
}
final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);
// 说明这个receiver是一个动态注册的receiver
// 进行派发,binder call到app进程
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
if (r.receiver == null || !r.ordered) {
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
// 需要设置deviceidle白名单就在此处设置
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(filter.owningUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
}
return;
}
// 代码走到这里就说明这个receiver是静态注册的
ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
boolean skip = false;
...
//这中间是一些权限的校验,此处不再罗列
String targetProcess = info.activityInfo.processName;
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
// 这里也是权限的校验,但是这里比较重要,因为Android新版本的限制越来越多在此处判断
// getAppStartModeLocked中会根据idle白名单,tmp名单,targetSdkVersion,appops权限等一些列校验
// 后面会有专门章节介绍这块新增的权限校验,随着Android版本变化,此处的校验也越来越严格
if (!skip) {
final int allowed = mService.getAppStartModeLocked(
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
Slog.w(TAG, "Background execution disabled: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
skip = true;
// // 在Android O上对后台app不允许接收广播的管控
} else if (((r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0)
|| (r.intent.getComponent() == null
&& r.intent.getPackage() == null
&& ((r.intent.getFlags()
& Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0)
&& !isSignaturePerm(r.requiredPermissions))) {
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
component.getPackageName());
Slog.w(TAG, "Background execution not allowed: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
skip = true;
}
}
}
if (skip) {
// 经过前面的校验,如果skip,则进行调度下一个
r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
return;
}
r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;
if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
// 因为广播在派发,设置package不能被stop
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.curComponent.getPackageName() + ": " + e);
}
// 此处判断这个receiver的进程是否存在,如果存在,那么在processCurBroadcastLocked派发
if (app != null && app.thread != null && !app.killed) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
+ r.curComponent, e);
} catch (RuntimeException e) {
Slog.wtf(TAG, "Failed sending broadcast to "
+ r.curComponent + " with " + r.intent, e);
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
r.state = BroadcastRecord.IDLE;
return;
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// 如果进程不在,启动新的进程
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// 记录需要处理的广播,在进程启动之后,进程attach到system server的时候处理
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
}
这里是广播调度与派发的和讯流程,中间省略了一部分代码,但还是很长,总结一下流程如下:
- 派发并行广播
- 处理广播整体超时
- 处理resultReceiver
- 派发动态注册的串行广播(有序广播)
- 处理静态注册的串行广播(有序广播)
- 权限校验
- 进程在的情况下processCurBroadcastLocked
- 进程不在则启动进程,记录要处理的广播mPendingBroadcast
3.7 BroadcastQueue.deliverToRegisteredReceiverLocked
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
...
//权限校验,不做过多罗列
if (mService.mPermissionReviewRequired) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
filter.owningUserId)) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
}
r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
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) {
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceivers.add(r);
mService.updateOomAdjLocked(r.curApp, true);
}
}
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
if (ordered) {
skipReceiverLocked(r);
}
} else {
// 执行receiver的派发
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
}
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
if (ordered) {
r.receiver = null;
r.curFilter = null;
filter.receiverList.curBroadcast = null;
if (filter.receiverList.app != null) {
filter.receiverList.app.curReceivers.remove(r);
}
}
}
}
这个方法中主要做了权限校验,然后派发
3.8 BroadcastQueue.performReceiveLocked
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) {
try {
// 终于看到了binder call
// 此处经过binder call到了receiver所在进程
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} catch (RemoteException ex) {
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 {
throw new RemoteException("app.thread must not be null");
}
} else {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
这个方法终于进行了binder call,到了app进程。
3.9 BroadcastQueue.processCurBroadcastLocked
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
// app进程必须存在才可以派发
if (app.thread == null) {
throw new RemoteException();
}
if (app.inFullBackup) {
skipReceiverLocked(r);
return;
}
// 要派发之前,调整这个进程的优先级
// 所以app在receiver执行的过程中优先级是很高的
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceivers.add(r);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
// binder call到app进程
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.repProcState);
started = true;
} finally {
if (!started) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceivers.remove(r);
}
}
}
上面这个方法是针对静态注册的广播,调度到其进程执行receiver。
3.10 ApplicationThread.scheduleRegisteredReceiver
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);
}
终于到了app的进程
从前面的处理流程可以知道,动态注册的receiver无论是并行还是串行最终调度都会到这里。
在注册的时候可以指定receiver的处理handler,如果没有指定才会用主线程。
这里就用到了之前注册时携带的binder对象innerReceiver.
3.11 InnerReceiver.performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
// innerReceiver是ReceiverDispatcher的内部类
// innerReceiver保存了对dispatcher的弱饮用,在创建的时候就记录了receiverDisoatcher,此处取出
rd = mDispatcher.get();
}
if (rd != null) {
// receiverDisoatcher.performReceive
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
IActivityManager mgr = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteExceptin e) {
throw e.rethrowFromSystemServer();
}
}
}
3.12 ReceiverDispatcher.performReceive
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
...
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
args.sendFinished(mgr);
}
}
这个方法的重点在于mActivityThread.post(args.getRunnable())
不要被mActivityThread的名字迷惑,其实这是一个Handler,正是在广播动态注册的时候设置的那个handler
通过这个post,切换了线程,开始执行receiver。
3.13 Args.run
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
mCurIntent = null;
mDispatched = true;
mPreviousRunStacktrace = new Throwable("Previous stacktrace");
if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
// receiver为空直接发送finish
sendFinished(mgr);
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
// 终于看到了熟悉的onReceive回调了
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
// 只有有序广播才会执行此步骤
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
};
}
到这里,终于看到了BroadcastReceiver的回调。
不过这只是动态注册的receiver,而且在动态注册的receiver执行完毕之后,如果是有序广播则还需要发送finish。
在处理有序广播的时候,前一个receiver处理完之后,可以留下一些信息,后面一个receiver在处理的时候可以根据这些信息做进一步的操作,而这些信息的传递正是通过getPendingResult
3.14 Args.finish
public final void finish() {
if (mType == TYPE_COMPONENT) {
final IActivityManager mgr = ActivityManager.getService();
// 这个queuedwork前面讲sharedpreference的时候有重点提到
// 这里就是在等待sp的写入完成
if (QueuedWork.hasPendingWork()) {
QueuedWork.queue(new Runnable() {
@Override public void run() {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast after work to component " + mToken);
sendFinished(mgr);
}
}, false);
} else {
sendFinished(mgr);
}
} else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to " + mToken);
final IActivityManager mgr = ActivityManager.getService();
sendFinished(mgr);
}
通过这里我们可以知道,在有序广播的执行流程中,还会去等待sp的写入文件完成,如果sp数据过大造成此处等待时间过长,是有可能造成广播anr的
3.15 ActivityThread.scheduleReceiver
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
H.handleMessage(Message msg){
...
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
这里是Android app的基本机制了,几乎大多数从systemserver来的binder call都是通过applicationthread过来,然后经过切换线程到主线程中执行,此处正是这样。
3.15 ActivityThread.handleReceiver
private void handleReceiver(ReceiverData data) {
unscheduleGcIdler();
String component = data.intent.getComponent().getClassName();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
IActivityManager mgr = ActivityManager.getService();
Application app;
BroadcastReceiver receiver;
ContextImpl context;
try {
app = packageInfo.makeApplication(false, mInstrumentation);
context = (ContextImpl) app.getBaseContext();
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
java.lang.ClassLoader cl = context.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
data.sendFinished(mgr);
throw new RuntimeException(
"Unable to instantiate receiver " + component
+ ": " + e.toString(), e);
}
try {
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
// 执行receiver的onReceive方法
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
if (!mInstrumentation.onException(receiver, e)) {
throw new RuntimeException(
"Unable to start receiver " + component
+ ": " + e.toString(), e);
}
} finally {
sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
data.finish();
}
}
这里就是静态注册的receiver在app这边的处理了,
从代码流程上看差距并不大,为什么静态注册要跟动态注册有区别呢?
重点在于动态注册的时候可以指定处理receiver的handler,而静态注册无法指定,因此只能用主线程处理
3.16 BroadcastReceiver.sendFinished
public void sendFinished(IActivityManager am) {
synchronized (this) {
if (mFinished) {
throw new IllegalStateException("Broadcast already finished");
}
mFinished = true;
try {
if (mResultExtras != null) {
mResultExtras.setAllowFds(false);
}
if (mOrderedHint) {
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast, mFlags);
} else {
am.finishReceiver(mToken, 0, null, null, false, mFlags);
}
} catch (RemoteException ex) {
}
}
这里就比较简单了,一些简单的状态判断之后,发送消息到AMS,我这个receiver已经执行完毕了
3.17 BroadcastReceiver.sendFinished
public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {
if (resultExtras != null && resultExtras.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Bundle");
}
final long origId = Binder.clearCallingIdentity();
try {
boolean doNext = false;
BroadcastRecord r;
synchronized(this) {
// 匹配相应的广播队列之后取出广播
BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
? mFgBroadcastQueue : mBgBroadcastQueue;
r = queue.getMatchingOrderedReceiver(who);
if (r != null) {
// finishReceiverLocked中置一些状态
doNext = r.queue.finishReceiverLocked(r, resultCode,
resultData, resultExtras, resultAbort, true);
}
}
// 进行下一轮的调度
if (doNext) {
r.queue.processNextBroadcast(false);
}
trimApplications();
} finally {
Binder.restoreCallingIdentity(origId);
}
因为有序广播是逐个执行,所以前一个执行完之后,通过finish告诉AMS,我执行完了,可以进行下一轮的调度了,这样对于一个有序广播,可能会有多个接收者,就这样挨个执行下去。
广播的ANR也是针对有序广播才有的,为了避免前面有一个receiver执行的时间太久而耽误后面的receiver,所以广播超时机制也是很有必要的。
总结
整体上讲,广播从发送流程到派发搭配各个客户端的流程相对还是比较复杂的,重点在于其中多了很多特殊的校验和判断,但其实如果从大纲上来看主要流程如下:
- 发送广播
- 处理sticky广播(重点是替换以及存储)
- 如果是并行广播,收集receiver后,入队
- 如果是串行广播,收集静态注册的receiver,和动态注册的receiver一起根据优先级排序后,入队
- 开始派发
- 如果是并行广播,直接for循环逐个派发出去,且是异步binder call,可以认为基本所有receiver会同时收到
- 如果是串行广播,先派发动态注册的receiver
- 静态注册广播需要先看进程是否存在,存在则派发,不存在则启动进程
- 广播派发到客户端后,动态注册的receiver通过inndeRreceiver找到ReceiverDispatcher后找到相应handler执行
- 静态注册广播派发到客户端后主线程执行
- 如果是有序广播,则派发后还需要告诉ams,执行完毕,让ams开始这个广播下一个receiver的派发