app端发送广播最终都是调用ContentImpl中的sendBroadcast相关方法实现,最终binder调用AMS的broadcastIntentWithFeature方法实现。
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp) {
// 解析MIME type
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
// 将权限封装成数组
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
// 调用AMS的接口
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false,
false, user.getIdentifier());
} catch (RemoteException e) {
// 抛出异常
throw e.rethrowFromSystemServer();
}
}
有序广播和无序广播主要区别在于可以指定广播的最后一个接收者resultReceiver,通过最后一个receiver可以知道广播派发完了,做一些收尾工作。
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
IIntentReceiver rd = null;
// 通过传入的resultReceiver获取IIntentReceiver 实例
if (resultReceiver != null) {
if (mPackageInfo != null) {
if (scheduler == null) {
// 获取主线程的handler
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();
}
}
// 解析type,封装权限
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
String[] receiverPermissions = receiverPermission == null ? null
: new String[] {receiverPermission};
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
rd, initialCode, initialData, initialExtras, receiverPermissions, appOp,
options, true, false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
入队相关逻辑主要都在AMS的broadcastIntentLocked方法中。
caller: 发送方的application thread对象
callingFeatureId: feature id
intent: 广播所带的intent
resolvedType: MIME type
resultTo: 最终接收的receiver
resultCode: 有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
resultData: 有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
resultExtras:有序广播在一个receiver处理之后可以设置值,下一个receiver可以拿到这个值
serialized:是否为有序广播
sticky:是否为sticky广播
userId:这个广播要发送到的user
public final int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
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);
// 通过caller获取调用端进程
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
// 清除calling uid,避免权限校验失败
final long origId = Binder.clearCallingIdentity();
try {
return broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null, callingFeatureId,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
callingPid, callingUid, callingUid, callingPid, userId);
} finally {
// 恢复calling uid
Binder.restoreCallingIdentity(origId);
}
}
}
以下情况除外
主要是root/system/phone/bluetooth/nfc这些uid 可以发送
allow-implicit-broadcast 列表内的action会添加flag FLAG_RECEIVER_INCLUDE_BACKGROUND,允许这些隐式广播被后台进程接收,后拉起进程。
静态注册的无序广播当作有序广播入队分发,避免一次拉起太多进程。
@GuardedBy("this")
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
@Nullable String callerFeatureId, 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 realCallingUid,
int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
@Nullable int[] broadcastWhitelist) {
intent = new Intent(intent);
//caller 是即时app的处理
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
if (callerInstantApp) {
intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
// 非系统发送的广播,broadcastWhitelist一般为null
if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
+ "Assuming restrictive whitelist.");
broadcastWhitelist = new int[]{};
}
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 系统未启动完成,一般不允许拉起新的进程,所以只允许动态注册的接收该广播
if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
// 非有序广播不能指定分发者IIntentReceiver
if ((resultTo != null) && !ordered) {
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_NON_FULL, "broadcast", callerPackage);
// 当前user不在运行中,终止入队
if (userId != UserHandle.USER_ALL && !mUserController.isUserOrItsParentRunning(userId)) {
if ((callingUid != SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
Slog.w(TAG, "Skipping broadcast of " + intent
+ ": user " + userId + " and its parent (if any) are stopped");
return ActivityManager.BROADCAST_FAILED_USER_STOPPED;
}
}
final String action = intent.getAction();
BroadcastOptions brOptions = null;
// bOptions一般为null,会改变device idle的临时白名单,需要检查caller是否有改变临时白名单的权限
if (bOptions != null) {
brOptions = new BroadcastOptions(bOptions);
if (brOptions.getTemporaryAppWhitelistDuration() > 0) {
if (checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
realCallingPid, realCallingUid, -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);
}
}
if (brOptions.isDontSendToRestrictedApps()
&& !isUidActiveLocked(callingUid)
&& isBackgroundRestrictedNoCheck(callingUid, callerPackage)) {
Slog.i(TAG, "Not sending broadcast " + action + " - app " + callerPackage
+ " has background restrictions");
return ActivityManager.START_CANCELED;
}
if (brOptions.allowsBackgroundActivityStarts()) {
// See if the caller is allowed to do this. Note we are checking against
// the actual real caller (not whoever provided the operation as say a
// PendingIntent), because that who is actually supplied the arguments.
if (checkComponentPermission(
android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
realCallingPid, realCallingUid, -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
+ ", uid=" + callingUid + ")"
+ " requires "
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
Slog.w(TAG, msg);
throw new SecurityException(msg);
} else {
allowBackgroundActivityStarts = true;
}
}
}
// 判断是否是保护广播
final boolean isProtectedBroadcast;
try {
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception", e);
return ActivityManager.BROADCAST_SUCCESS;
}
final boolean isCallerSystem;
// 判断广播是否来自system
switch (UserHandle.getAppId(callingUid)) {
case ROOT_UID:
case SYSTEM_UID:
case PHONE_UID:
case BLUETOOTH_UID:
case NFC_UID:
case SE_UID:
case NETWORK_STACK_UID:
isCallerSystem = true;
break;
default:
// MIUI MOD
// isCallerSystem = (callerApp != null) && callerApp.isPersistent();
isCallerSystem = false;
break;
}
// First line security check before anything else: stop non-system apps from
// sending protected broadcasts.
if (!isCallerSystem) {
// 非系统特殊uid不允许发送保护广播
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) {
// 显示广播要求发送者和接收者的package一致
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);
}
}
}
boolean timeoutExempt = false;
if (action != null) {
// allow-implicit-broadcast 列表内的action会添加flagFLAG_RECEIVER_INCLUDE_BACKGROUND
if (getBackgroundLaunchBroadcasts().contains(action)) {
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
}
// 一些特殊的系统广播处理
}
// 处理sticky广播
if (sticky) {
// 发送stikcy广播的app需要声明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;
}
// stikcy广播不能为显式广播
if (intent.getComponent() != null) {
throw new SecurityException(
"Sticky broadcasts can't target a specific component");
}
// sticky广播不能针对单个user又针对所有user
if (userId != UserHandle.USER_ALL) {
// But first, if this is not a broadcast to all users, then
// make sure it doesn't conflict with an existing broadcast to
// all users.
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))) {
// 替换
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
//没替换则新增
list.add(new Intent(intent));
}
}
int[] users;
if (userId == UserHandle.USER_ALL) {
users = mUserController.getStartedUserArray();
} else {
users = new int[] {userId};
}
// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// 收集静态注册的receivers,resolvedType 在此处生效
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers = collectReceiverComponents(
intent, resolvedType, callingUid, users, broadcastWhitelist);
}
// 隐式广播
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 {
// 查找动态注册的广播
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false /*defaultOnly*/, userId);
}
}
// 表示这个广播还没有派发,则替换掉之前的广播
final boolean replacePending =
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
if (registeredReceivers != null && broadcastWhitelist != null) {
// 不在广播百名单的uid列表且uid > 10000的receiver,从动态注册者中移除
for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);
if (owningAppId >= Process.FIRST_APPLICATION_UID
&& Arrays.binarySearch(broadcastWhitelist, owningAppId) < 0) {
registeredReceivers.remove(i);
}
}
}
// 动态注册的广播
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 处理并行广播
if (!ordered && NR > 0) {
if (isCallerSystem) {
// 对系统发送的广播进行校验
checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
isProtectedBroadcast, registeredReceivers);
}
// 根据intent的flag获取广播队列,负载队列或前台队列或后台队列
final BroadcastQueue queue = broadcastQueueForIntent(intent);
// 创建广播对象
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
// 根据需要替换无序广播
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) {
// 移除一些静态注册的广播接收者
String skipPackages[] = null;
// package相关广播
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 };
}
}
// ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
} 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;
// 有序广播的动态注册receivers和静态注册的receivers
// 无序广播的静态注册receivers
// 下面这个循环就是一个动态,静态receiver排序后插入的过程,最终都在receivers中
while (it < NT && ir < NR) {
// 静态注册获取resolver info
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
// 动态注册获取broadcast filter
if (curr == null) {
curr = registeredReceivers.get(ir);
}
// 动态优先级大于静态优先级,插入到receivers中,继续循环
if (curr.getPriority() >= curt.priority) {
receivers.add(it, curr);
ir++;
curr = null;
it++;
NT++;
} else {
// 将当前动态跟下一个静态相比,就是一个插入排序的过程
it++;
curt = null;
}
}
}
// 合并之后。如果动态注册的receivers还有,全部添加到receivers后面
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) {
// 获取广播队列,前台后后台队列
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 创建广播对象
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
// 如果需要替换之前的广播则查找并替换
final BroadcastRecord oldRecord =
replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
if (oldRecord != null) {
// 如果替换了之前的广播,且是有序广播,则需要执行之前广播的result to receiver
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) {
// This was an implicit broadcast... let's record it for posterity.
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
return ActivityManager.BROADCAST_SUCCESS;
}
广播调度分发逻辑主要在BroadcastQueue中且是异步的,由binder线程转到main线程中执行
// 广播调度开始
public void scheduleBroadcastsLocked() {
// 如果已经开始就返回
if (mBroadcastsScheduled) {
return;
}
// 发送BROADCAST_INTENT_MSG消息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
// main线程
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;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
// 处理广播超时
broadcastTimeoutLocked(true);
}
} break;
}
}
}
广播分发调度的核心方法如下:
一般是派发静态注册的receiver时,app进程不存在,会先去拉起进程,等进程拉起后调用sendPendingBroadcastsLocked去处理pending的广播
这里判断进程是否死亡,未死亡直接返回;
死亡则将
1.若没有需要处理的有序广播,直接返回
2.处理广播的整体超时
有序广播派发中,若当前时间距离派发时间超过 2 * mConstants.TIMEOUT * numReceivers,则标记forceReceive为true,强制结束这个广播
3. 获取到的广播状态不为idle,直接返回
4. 当前广播派发完或终止或2中的forceReceive为true
- 尝试派发有序广播的最后一个接收者
- 取消超时计算
- 添加到广播的历史记录中
- 重新循环
5. 延时广播的处理,重新循环
取到要处理的广播后,通过receiverTime发送超时消息,10s或60s内未取消触发anr
通过deliverToRegisteredReceiverLocked派发动态注册的广播,权限相关校验等也在这个方法中。
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
// 更新cpu统计
mService.updateCpuStats();
// 重置mBroadcastsScheduled
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循环派发到app进程
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
// 添加到广播历史记录
addBroadcastToHistoryLocked(r);
}
// mPendingBroadcast表示派发广播时需要启动进程,会先用这个记录下来,等进程启动后处理
// 静态注册可能需要拉起进程
if (mPendingBroadcast != null) {
boolean isDead;
// 判断mPendingBroadcast广播的当前进程是否死亡
if (mPendingBroadcast.curApp.pid > 0) {
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(
mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.isCrashing();
}
} else {
final ProcessRecord proc = mService.mProcessList.mProcessNames.get(
mPendingBroadcast.curApp.processName, mPendingBroadcast.curApp.uid);
isDead = proc == null || !proc.pendingStart;
}
// 当前进程未死亡,继续等待
if (!isDead) {
return;
} else {
// 否则将广播状态置为idle,receiver索引移到下一位
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
do {
final long now = SystemClock.uptimeMillis();
// 获取当前需要处理的有序广播
r = mDispatcher.getNextBroadcastLocked(now);
// 若无需要处理的有序广播,
if (r == null) {
mDispatcher.scheduleDeferralCheckLocked(false);
mService.scheduleAppGcsLocked();
if (looped) {
mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
}
if (mService.mUserController.mBootCompleted && mLogLatencyMetrics) {
mLogLatencyMetrics = false;
}
return;
}
boolean forceReceive = false;
//获取接收者
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
// timeoutExempt表示当前广播不受接收器超时的限制,如开机广播等
// 系统已经就绪,广播已经分发过
if (mService.mProcessesReady && !r.timeoutExempt && r.dispatchTime > 0) {
// 一个有序广播,所有的receivers派发时间加起来不得大于 2倍的单个派发超时时间(前台10s,后台60s)*receiver的数量
if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mConstants.TIMEOUT * 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); // forcibly finish this broadcast
// 标记forceReceive为true,当前广播状态标记为idle
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
// 如果当前广播状态不是idle,退出这个循环
if (r.state != BroadcastRecord.IDLE) {
return;
}
// 当前广播已经派发完,被终止,或者上面的超时停止了
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
// 有序广播的最终接收者
if (r.resultTo != null) {
boolean sendResult = true;
// 如果当前广播拆分/延迟广播,更新引用计数
if (r.splitToken != 0) {
int newCount = mSplitRefcounts.get(r.splitToken) - 1;
// 移除计数
if (newCount == 0) {
mSplitRefcounts.delete(r.splitToken);
} else {
// 若还有一些拆分的广播,更新引用计数,并延迟回调
sendResult = false;
mSplitRefcounts.put(r.splitToken, newCount);
}
}
// 派发有序广播的最后一个receiver
if (sendResult) {
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);
}
}
}
// 广播派发完了,取消超时计算
cancelBroadcastTimeoutLocked();
// 将当前广播添加到历史记录中
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);
}
// 处理完当前广播,重新循环
mDispatcher.retireBroadcastLocked(r);
r = null;
looped = true;
continue;
}
// Check whether the next receiver is under deferral policy, and handle that
// accordingly. If the current broadcast was already part of deferred-delivery
// tracking, we know that it must now be deliverable as-is without re-deferral.
if (!r.deferred) {
final int receiverUid = r.getReceiverUid(r.receivers.get(r.nextReceiver));
if (mDispatcher.isDeferringLocked(receiverUid)) {
// If this is the only (remaining) receiver in the broadcast, "splitting"
// doesn't make sense -- just defer it as-is and retire it as the
// currently active outgoing broadcast.
BroadcastRecord defer;
if (r.nextReceiver + 1 == numReceivers) {
defer = r;
mDispatcher.retireBroadcastLocked(r);
} else {
// Nontrivial case; split out 'uid's receivers to a new broadcast record
// and defer that, then loop and pick up continuing delivery of the current
// record (now absent those receivers).
// The split operation is guaranteed to match at least at 'nextReceiver'
defer = r.splitRecipientsLocked(receiverUid, r.nextReceiver);
// Track completion refcount as well if relevant
if (r.resultTo != null) {
int token = r.splitToken;
if (token == 0) {
// first split of this record; refcount for 'r' and 'deferred'
r.splitToken = defer.splitToken = nextSplitTokenLocked();
mSplitRefcounts.put(r.splitToken, 2);
} else {
// new split from an already-refcounted situation; increment count
final int curCount = mSplitRefcounts.get(token);
mSplitRefcounts.put(token, curCount + 1);
}
}
}
mDispatcher.addDeferredBroadcast(receiverUid, defer);
r = null;
looped = true;
continue;
}
}
} while (r == null);
//经过上面的循环,取到了一个需要派发的广播
// 广播的receiver索引赋值给recIdx,随后自增1
int recIdx = r.nextReceiver++;
// 赋值receiverTime,计算超时需要
r.receiverTime = SystemClock.uptimeMillis();
// 如果第一次分发,赋值广播的派发时间
if (recIdx == 0) {
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
}
// 发送超时消息,10s或60s后未取消则触发anr
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mConstants.TIMEOUT;
setBroadcastTimeoutLocked(timeoutTime);
}
final BroadcastOptions brOptions = r.options;
// 获取下一个需要派发的receiver
final Object nextReceiver = r.receivers.get(recIdx);
// 如果是动态注册的receiver
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
// 进行分发,binder到app进程执行
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
//广播的receiver为null代表当前分发完成则继续分发下一轮
if (r.receiver == null || !r.ordered) {
//重置广播状态,开始下一轮
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
} else {
if (filter.receiverList != null) {
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
}
// 需要设置device idle百名单在此设置
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;
.......
// 一些特殊情况会跳过分发
if (r.curApp != null && r.curApp.isCrashing()) {
Slog.w(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r
+ " to " + r.curApp + ": process crashing");
skip = true;
}
if (!skip) {
boolean isAvailable = false;
try {
isAvailable = AppGlobals.getPackageManager().isPackageAvailable(
info.activityInfo.packageName,
UserHandle.getUserId(info.activityInfo.applicationInfo.uid));
} catch (Exception e) {
// all such failures mean we skip this receiver
Slog.w(TAG, "Exception getting recipient info for "
+ info.activityInfo.packageName, e);
}
if (!isAvailable) {
skip = true;
}
}
if (!skip) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
info.activityInfo.packageName, UserHandle.getUserId(
info.activityInfo.applicationInfo.uid))) {
skip = true;
}
}
.......
if (!skip) {
final int allowed = mService.getAppStartModeLocked(
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// android O 上对后台app不允许接收广播的管控
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
Slog.w(TAG, "Background execution disabled: receiving "
+ r.intent + " to "
+ component.flattenToShortString());
skip = true;
} 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 && !Intent.ACTION_SHUTDOWN.equals(r.intent.getAction())
&& !mService.mUserController
.isUserRunning(UserHandle.getUserId(info.activityInfo.applicationInfo.uid),
0 /* flags */)) {
skip = true;
Slog.w(TAG,
"Skipping delivery to " + info.activityInfo.packageName + " / "
+ info.activityInfo.applicationInfo.uid + " : user is not running");
}
// 如果跳过,继续下一轮的派发
if (skip) {
r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
r.manifestSkipCount++;
scheduleBroadcastsLocked();
return;
}
r.manifestCount++;
r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
// 设置当前广播的状态
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;
final boolean isActivityCapable =
(brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0);
if (isActivityCapable) {
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}
//广播在派发,设置package不能被stop
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.curComponent.getPackageName() + ": " + e);
}
// 如果当前进程存在,则在processCurBroadcastLocked中派发
if (app != null && app.thread != null && !app.killed) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.longVersionCode, mService.mProcessStats);
maybeAddAllowBackgroundActivityStartsToken(app, r);
processCurBroadcastLocked(r, app, skipOomAdj);
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();
r.state = BroadcastRecord.IDLE;
return;
}
}
// 如果进程不存在,启动新的进程
if ((r.curApp=mService.startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
new HostingRecord("broadcast", r.curComponent),
isActivityCapable ? ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
// app 短时间crash多次会导致进程启动失败
// 结束派发,继续下一轮派发
Slog.w(TAG, "Unable to launch app "
+ info.activityInfo.applicationInfo.packageName + "/"
+ receiverUid + " for broadcast "
+ r.intent + ": process is bad");
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
// 启动新的进程,将当前广播赋值给mPendingBroadcast,等进程启动后继续派发
maybeAddAllowBackgroundActivityStartsToken(r.curApp, r);
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;
}
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
......
// 一些权限的校验
if (!skip && (filter.receiverList.app == null || filter.receiverList.app.killed
|| filter.receiverList.app.isCrashing())) {
Slog.w(TAG, "Skipping deliver [" + mQueueName + "] " + r
+ " to " + filter.receiverList + ": process gone or crashing");
skip = true;
}
.......
// 跳过,将当前动态接收者分发状态标为DELIVERY_SKIPPED
if (skip) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
.......
//设置当前receiver的处理状态,表示已经分发到app进程
r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
// 如果是有序广播,相关属性赋值
if (ordered) {
// 记录当前正在处理的receiver
r.receiver = filter.receiverList.receiver.asBinder();
// 记录当前处理的那个IntentFilter,(因为一个客户端有可能有多个IntentFilter)
r.curFilter = filter;
filter.receiverList.curBroadcast = r;
// 当前广播有正在派发的app
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,
OomAdjuster.OOM_ADJ_REASON_START_RECEIVER);
}
}
try {
// 接收端进程正在被份
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
// 且是有序广播,则结束当前派发,并开始下一轮派发
if (ordered) {
skipReceiverLocked(r);
}
} else {
// 赋值receiverTime,用于计算超时时间,触发anr等
r.receiverTime = SystemClock.uptimeMillis();
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
// 派发到app进程
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
if (r.allowBackgroundActivityStarts && !r.ordered) {
postActivityStartTokenRemoval(filter.receiverList.app, r);
}
}
// 有序广播,表示当前已经派发到app端
if (ordered) {
r.state = BroadcastRecord.CALL_DONE_RECEIVE;
}
} catch (RemoteException e) {
Slog.w(TAG, "Failure sending broadcast " + r.intent, e);
// Clean up ProcessRecord state related to this broadcast attempt
if (filter.receiverList.app != null) {
filter.receiverList.app.removeAllowBackgroundActivityStartsToken(r);
if (ordered) {
filter.receiverList.app.curReceivers.remove(r);
}
}
// And BroadcastRecord state related to ordered delivery, if appropriate
if (ordered) {
r.receiver = null;
r.curFilter = null;
filter.receiverList.curBroadcast = null;
}
}
}
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) {
// 进程存在,binder到app端去执行
try {
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
} 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);
}
}
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app, boolean skipOomAdj) throws RemoteException {
// 进程不存在,抛出异常
if (app.thread == null) {
throw new RemoteException();
}
// app进程在备份,则结束派发,并开始下一轮派发
if (app.inFullBackup) {
skipReceiverLocked(r);
return;
}
// 这个只有在有序广播和静态注册时才赋值
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceivers.add(r);
// 将app的进程提升到PROCESS_STATE_RECEIVER(11),一般执行完后优先级就可能会掉下去
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.mProcessList.updateLruProcessLocked(app, false, null);
if (!skipOomAdj) {
mService.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
}
// Tell the application to launch this receiver.
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
// binder到app端去执行
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackage(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.getReportedProcState());
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);
}
}
}
无序广播的动态注册入队平行广播队列,所以分发也只针对动态注册的方式分发
无序广播的静态注册入队有序广播队列
静态注册的广播默认都以有序广播的形式派发