摘要
1.发送广播(App喊话)
App喊话:你的App调用ContextImpl.sendBroadcast(),就像对着全校喊:“注意!有消息!”。
交给校长(AMS):消息通过Binder(类似对讲机)传给系统服务ActivityManagerService(AMS),校长负责管理全校广播。
2. 广播排队(校长整理消息)
分类处理:AMS检查广播类型(普通/有序)和权限,把广播塞进队列(BroadcastQueue)。
冷启动 vs 热启动:
冷启动:如果接收App没运行,校长先叫醒它(通过Zygote fork新进程,类似开学点名)。
热启动:如果App已经在后台,直接发消息。
3. 派送广播(班长传话)
找班长(ActivityThread):系统找到目标App的“班长”(主线程),让它通知具体的“同学”(BroadcastReceiver)。
主线程处理:班长通过ReceiverDispatcher把广播包装成Runnable,扔到主线程的“作业本”(消息队列)里,避免卡顿。
4. 接收广播(同学听讲)
执行onReceive():主线程执行BroadcastReceiver.onReceive(),就像同学听到广播后做作业。但作业不能拖堂(超过10秒会ANR)。
收尾:处理完通知校长(AMS),如果是有序广播还会告诉下一个同学
广播发送的架构图
阶段 |
步骤描述 |
关键方法/组件 |
冷/热启动区别 |
1. 广播发送 |
应用调用sendBroadcast()发起广播 |
ContextImpl.sendBroadcast()→AMS.broadcastIntentWithFeature() |
无区别 |
2. AMS处理广播 |
AMS验证广播合法性并分发给队列 |
AMS.broadcastIntentLocked()→BroadcastQueue.enqueueBroadcastLocked() |
无区别 |
3. 队列调度 |
广播队列根据接收进程状态选择冷启动或热启动路径 |
BroadcastQueueModernImpl.updateRunningListLocked() |
冷启动:进程不存在 → 触发进程创建 热启动:进程存在 → 直接分发 |
4. 进程启动(冷启动) |
通过Zygote fork新进程,并等待应用初始化完成 |
ProcessList.startProcessLocked()→ZygoteProcess.start() |
仅冷启动触发 |
5. 接收器绑定(冷启动) |
进程启动后,AMS重新将广播绑定到新进程的接收器 |
BroadcastQueueModernImpl.onApplicationAttachedLocked() |
仅冷启动触发 |
6. 广播分发(热启动) |
直接通过Binder调用将广播分发给已注册的接收器 |
ActivityThread.scheduleRegisteredReceiver() |
仅热启动触发 |
7. 主线程切换 |
接收器通过主线程Handler执行onReceive() |
LoadedApk.ReceiverDispatcher.Args.getRunnable() |
无区别(均需切换主线程) |
8. 结果回调 |
若为有序广播,接收器处理完成后通知AMS继续传递或终止广播 |
ActivityManagerService.finishReceiver() |
无区别 |
广播发送到接收的堆栈和时序图
ContextImpl. sendBroadcast(Intent intent)->ActivityManagerService.broadcastIntentWithFeature()
→ActivityManagerService.broadcastIntentWithFeature()->ActivityManagerService.broadcastIntentLocked()
→→ActivityManagerService.broadcastIntentLocked()->ActivityManagerService.broadcastIntentLockedTraced()
→→→ActivityManagerService.broadcastIntentLockedTraced()->BroadcastQueue.enqueueBroadcastLocked()
→→→→BroadcastQueue.enqueueBroadcastLocked()->BroadcastQueueModernImpl.enqueueBroadcastLocked()
→→→→→BroadcastQueueModernImpl.enqueueBroadcastLocked()->BroadcastQueueModernImpl.updateRunningListLocked()
→→→→→→BroadcastQueueModernImpl.scheduleReceiverColdLocked()->BroadcastQueueModernImpl.scheduleReceiverColdLocked() 冷启动后发广播
→→→→→→→BroadcastQueueModernImpl.scheduleReceiverColdLocked()->ActivityManagerService.startProcessLocked()
→→→→→→→→ActivityManagerService.startProcessLocked()->ProcessList.startProcessLocked()
→→→→→→→→→ProcessList.startProcessLocked()->ZygoteProcess.start()// 最终通过Zygote fork进程
→→→→→→→→→→ZygoteProcess.start()->BroadcastQueueModernImpl.onApplicationAttachedLocked()->BroadcastQueueModernImpl.updateRunningListLocked() 后面的流程和热启动发送广播一样了
→→→→→BroadcastQueueModernImpl.updateRunningListLocked()->BroadcastQueueModernImpl.scheduleReceiverWarmLocked() 直接热启动发广播
→→→→→→BroadcastQueueModernImpl.scheduleReceiverWarmLocked()->BroadcastQueueModernImpl.dispatchReceivers()
→→→→→→→BroadcastQueueModernImpl.dispatchReceivers()->ActivityThread.scheduleRegisteredReceiver
→→→→→→→→ActivityThread.scheduleRegisteredReceiver->LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive()
→→→→→→→→→LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive()->LoadedApk.ReceiverDispatcher.Args.getRunnable()
→→→→→→→→→→LoadedApk.ReceiverDispatcher.Args.getRunnable()->BroadcastReceiver.onReceive(mContext, intent):App就收到广播了哈
源码走读
一、调用ContextImpl.sendBroadcast发送广播
@Override
public void sendBroadcast(Intent intent) {
// 1. 系统进程调用警告:防止系统进程误用普通API,Android框架的内部保护机制,防止系统进程错误使用普通API导致权限逃逸
warnIfCallingFromSystemProcess();
// 2. 解析Intent的MIME类型(如content:// URI对应的类型)
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
// 3. 准备跨进程传输:清理Intent中可能包含的进程内对象(如Parcelable),会清理Intent中不可序列化的对象,确保其能通过Binder传输。这是Android IPC的核心安全措施
intent.prepareToLeaveProcess(this);
// 4. 通过Binder调用AMS(ActivityManagerService)的广播发送接口
ActivityManager.getService().broadcastIntentWithFeature(
mMainThread.getApplicationThread(), // 调用方线程标识
getAttributionTag(), // 调用方归属标签(用于权限追踪)
intent, // 要发送的广播Intent
resolvedType, // 已解析的MIME类型
null, // 接收权限要求(null表示无限制)
Activity.RESULT_OK, // 默认结果码
null, // 结果数据(BroadcastResult)
null, // 结果扩展数据
null, // 排除的组件列表
null /*excludedPermissions=*/, // 排除的权限列表
null, // 广播选项(如延迟发送)
AppOpsManager.OP_NONE, // 关联的AppOps操作
null, // 目标用户ID(null表示当前用户)
false, // 是否后台广播
false, // 是否粘性广播
getUserId()); // 发送方用户ID
} catch (RemoteException e) {
// 5. 处理系统服务通信异常(AMS运行在system_server进程)
throw e.rethrowFromSystemServer();
}
}
二、调用AMS的broadcastIntentWithFeature方法:
核心逻辑:调用broadcastIntentLocked完成广播分发
@Override
public final int broadcastIntentWithFeature(
IApplicationThread caller, // 调用方应用线程(Binder代理对象)
String callingFeatureId, // 调用方特性标识(如Instant App ID)
Intent intent, // 待发送的广播Intent
String resolvedType, // Intent的MIME类型(已解析)
IIntentReceiver resultTo, // 结果接收器(有序广播时使用)
int resultCode, // 结果码
String resultData, // 结果数据
Bundle resultExtras, // 结果附加数据
String[] requiredPermissions, // 接收方需具备的权限
String[] excludedPermissions, // 排除的权限
String[] excludedPackages, // 排除的包名
int appOp, // 关联的AppOps操作
Bundle bOptions, // 广播选项(如延迟、白名单等)
boolean serialized, // 是否串行发送
boolean sticky, // 是否粘性广播
int userId) { // 目标用户ID
// 1. 隔离进程检查:禁止isolated进程发送广播
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
// 2. 校验Intent合法性(如action非空、组件权限等)
intent = verifyBroadcastLocked(intent);
// 3. 获取调用方进程信息
final ProcessRecord callerApp = getRecordForAppLOSP(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
// 4. 结果接收方默认为调用方进程(有序广播场景)
final ProcessRecord resultToApp = callerApp;
// 5. 检查广播选项权限(如后台启动白名单等)
enforceBroadcastOptionPermissionsInternal(bOptions, callingUid);
// 6. 清除调用方身份标识(切换为系统身份执行后续操作)
final long origId = Binder.clearCallingIdentity();
/// MTK扩展逻辑:DuraSpeed机制可能抑制广播发送
String suppressAction = mAmsExt.onReadyToStartComponent(
callerApp != null ? callerApp.info.packageName : null,
callingUid, "broadcast", null);
if ((suppressAction != null) && suppressAction.equals("skipped")) {
Binder.restoreCallingIdentity(origId);
Slog.d(TAG, "broadcastIntentWithFeature, suppress to broadcastIntent!");
return ActivityManager.BROADCAST_SUCCESS; // 直接返回成功(被抑制)
}
try {
// 7. 核心逻辑:调用broadcastIntentLocked完成广播分发
return broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
callingFeatureId,
intent, resolvedType, resultToApp, resultTo, resultCode,
resultData, resultExtras, requiredPermissions,
excludedPermissions, excludedPackages, appOp, bOptions,
serialized, sticky, callingPid, callingUid, callingUid,
callingPid, userId,
BackgroundStartPrivileges.NONE, null, null);
} finally {
// 8. 恢复调用方身份
Binder.restoreCallingIdentity(origId);
}
}
}
继续分析 broadcastIntentLocked 函数,该函数是广播分发的核心逻辑
三、调用AMS的broadcastIntentLocked方法:
1、找出符合条件的静态接收器和动态接收器
2、若是无序广播,将动态接收器打包成一条广播记录,先进入无序广播队列,并行分发广播
3、按优先级将静态和动态接收器合并到一个接收器队列
4、将3中得到的接收器队列打包成一条广播记录,进入有序广播队列,串行分发广播
/**
* 广播发送核心逻辑,处理权限校验、接收者匹配、队列分发等
*
* @param callerApp 调用方进程记录(ProcessRecord)
* @param callerPackage 调用方包名(用于权限校验)
* @param intent 广播Intent(包含Action和附加数据)
* @param resolvedType Intent的MIME类型(通过ContentResolver解析)
* @param resultToApp 结果接收方进程(有序广播时使用)
* @param brOptions 广播选项(延迟、白名单等,BroadcastOptions类型)
* @param ordered 是否有序广播(true则按优先级顺序分发)
* @param sticky 是否粘性广播(true则存入mStickyBroadcasts)
* @param callingUid 调用方UID(用于跨进程身份校验)
* @param userId 目标用户ID(USER_ALL表示所有用户)
* @param backgroundStartPrivileges 后台启动权限控制(Android 15+限制)
* @return 广播状态码(如BROADCAST_SUCCESS)
*/
final int broadcastIntentLockedTraced(...) {
// 1. SDK沙箱进程检查(限制敏感广播发送)
if (Process.isSdkSandboxUid(realCallingUid)) { ... }
// 2. 系统启动状态处理:未完成启动时限制广播范围
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); // 仅动态接收器
}
// 3. 特殊广播处理(包管理、时间变更等)
switch (intent.getAction()) {
case Intent.ACTION_PACKAGE_REMOVED:
forceStopPackageLocked(...); // 强制停止卸载的包
case Intent.ACTION_TIME_CHANGED:
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); // 异步更新时区
}
// 4. 粘性广播存储
if (sticky) {
synchronized (mStickyBroadcasts) {
mStickyBroadcasts.put(userId, new Intent(intent)); // 按用户存储
}
}
// 5. 接收者匹配:静态注册+动态注册
List receivers = collectReceiverComponents(...); // 静态注册查询
List<BroadcastFilter> registeredReceivers = mReceiverResolver.queryIntent(...); // 动态注册过滤
// 6. 创建广播记录并加入队列
BroadcastRecord r = new BroadcastRecord(...);
mBroadcastQueue.enqueueBroadcastLocked(r); // 根据ordered选择并行或有序队列
}
阶段 |
关键操作 |
涉及核心类/方法 |
1. 发送入口 |
Context.sendBroadcast()→ContextImpl.broadcastIntent() |
ContextWrapper→ContextImpl |
2. 跨进程通信 |
通过Binder调用AMS的broadcastIntentWithFeature() |
ActivityManagerService |
3. 权限与校验 |
- 检查调用方UID权限 - 验证Intent合法性(如非空Action) |
verifyBroadcastLocked() enforceBroadcastOptionPermissions() |
4. 接收者匹配 |
- 静态注册:PackageManagerService查询 - 动态注册:mReceiverResolver |
collectReceiverComponents() IntentResolver |
5. 队列分发 |
- 创建BroadcastRecord - 加入BroadcastQueue(前台/后台/离线队列) |
BroadcastQueue.enqueueBroadcastLocked() 接口定义 BroadcastQueueModernImpl.enqueueBroadcastLocked() 实现类 |
下一步:分析 enqueueBroadcastLocked() 的具体实现
四、调用BroadcastQueueModernImpl的enqueueBroadcastLocked方法
1、根据进程名和Uid找出或创建接收器进程记录(BroadcastProcessQueue)。
2、将接收器添加到接收器进程记录内的mPending、mPendingUrgent和mPendingOffload三个接收器队列中的一个
3、将接收器进程记录添加到进程队列(mRunnableHead),越早排队优先级越高
4、enqueueUpdateRunningList分发广播
/**
* 将广播记录(BroadcastRecord)加入现代广播队列的核心逻辑
*
* @param r 广播记录,包含Intent、接收者列表、发送方信息等
*
* 关键流程:
* 1. 对每个接收者,按进程分类管理(BroadcastProcessQueue)
* 2. 根据策略决定接收者是否跳过(如静态接收者限制)
* 3. 将接收者加入进程队列的优先级子队列(mPending/mPendingUrgent/mPendingOffload)
* 4. 触发异步分发(enqueueUpdateRunningList)
*/
public void enqueueBroadcastLocked(@NonNull BroadcastRecord r) {
// 调试日志:记录广播的发送方和接收者数量
StringBuilder allReceivers = new StringBuilder();
if (DEBUG_BROADCAST) {
allReceivers.append(":").append(r.receivers);
}
logv("Enqueuing " + r + " from uid " + r.callingUid + " pid " + r.callingPid
+ " for " + r.receivers.size() + " receivers" + allReceivers);
final int cookie = traceBegin("enqueueBroadcast");
// 应用单例广播策略(如系统广播的权限控制)
r.applySingletonPolicy(mService);
// 应用投递组策略(如后台广播的延迟处理)
applyDeliveryGroupPolicy(r);
// 记录入队时间(影响分发优先级,时间越早优先级越高)
r.enqueueTime = SystemClock.uptimeMillis();
r.enqueueRealTime = SystemClock.elapsedRealtime();
r.enqueueClockTime = System.currentTimeMillis();
mHistory.onBroadcastEnqueuedLocked(r); // 历史记录跟踪
// 初始化被替换广播的缓存(用于FLAG_RECEIVER_REPLACE_PENDING逻辑)
ArraySet<BroadcastRecord> replacedBroadcasts = mReplacedBroadcastsCache.getAndSet(null);
if (replacedBroadcasts == null) {
replacedBroadcasts = new ArraySet<>();
}
boolean enqueuedBroadcast = false;
// 遍历所有接收者
for (int i = 0; i < r.receivers.size(); i++) {
final Object receiver = r.receivers.get(i);
// 1. 获取或创建接收者所属进程的队列(BroadcastProcessQueue)
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), // 进程名
getReceiverUid(receiver) // UID
);
// 2. 检查接收者是否应跳过(如静态接收者只能接收显式广播)
final String skipReason = mSkipPolicy.shouldSkipMessage(r, receiver);
if (skipReason != null) {
setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
"skipped by policy at enqueue: " + skipReason);
continue; // 跳过无效接收者
}
enqueuedBroadcast = true;
// 3. 将接收者加入进程队列的子队列(按优先级选择mPending/mPendingUrgent/mPendingOffload)
final BroadcastRecord replacedBroadcast = queue.enqueueOrReplaceBroadcast(
r, i, mBroadcastConsumerDeferApply);
if (replacedBroadcast != null) {
replacedBroadcasts.add(replacedBroadcast); // 记录被替换的旧广播
}
// 4. 更新可运行队列(mRunnableHead),越早加入优先级越高
updateRunnableList(queue);
// 5. 触发异步分发(通过Handler调度)
enqueueUpdateRunningList();
}
// 清理被替换的广播(FLAG_RECEIVER_REPLACE_PENDING生效时)
skipAndCancelReplacedBroadcasts(replacedBroadcasts);
replacedBroadcasts.clear();
mReplacedBroadcastsCache.compareAndSet(null, replacedBroadcasts);
// 若广播无有效接收者,立即返回结果
if (r.receivers.isEmpty() || !enqueuedBroadcast) {
scheduleResultTo(r);
notifyFinishBroadcast(r);
}
traceEnd(cookie);
}
下一步:重点看下 触发异步分发 enqueueUpdateRunningList通过Handler调度到updateRunningListLocked函数
五、调用BroadcastQueueModernImpl的updateRunningListLocked方法
遍历mRunnableHead队列,接收器进程已启动则使用scheduleReceiverWarmLocked分发广播,否则使用scheduleReceiverColdLocked分发广播
/**
* 更新"运行中"的进程队列列表,将符合条件的"可运行"队列提升为"运行中"状态
*
* 核心逻辑:
* 1. 遍历 mRunnableHead 队列,根据进程状态(冷启动/热启动)选择分发策略
* 2. 热进程直接通过 scheduleReceiverWarmLocked 分发广播
* 3. 冷进程通过 scheduleReceiverColdLocked 启动进程并分发
*
* 限制条件:
* - 最大并行运行队列数:MAX_RUNNING_PROCESS_QUEUES
* - 同一时间仅允许一个冷启动进程(mRunningColdStart)
*/
@GuardedBy("mService")
private void updateRunningListLocked() {
// 计算可用运行槽位(考虑紧急广播的额外配额)
final int usedExtra = Math.min(getRunningUrgentCount(),
mConstants.EXTRA_RUNNING_URGENT_PROCESS_QUEUES);
int avail = mRunning.length - getRunningSize() - usedExtra;
if (avail == 0) return; // 无可用槽位时直接返回
final int cookie = traceBegin("updateRunningList");
final long now = SystemClock.uptimeMillis();
// 检查是否有等待状态的队列(若有则忽略时间限制)
final boolean waitingFor = !mWaitingFor.isEmpty();
// 移除未处理的更新请求(避免重复调度)
mLocalHandler.removeMessages(MSG_UPDATE_RUNNING_LIST);
boolean updateOomAdj = false;
BroadcastProcessQueue queue = mRunnableHead;
while (queue != null && avail > 0) {
BroadcastProcessQueue nextQueue = queue.runnableAtNext;
final long runnableAt = queue.getRunnableAt();
// 跳过非可运行状态的队列(如广播被跳过或失败)
if (!queue.isRunnable()) {
queue = nextQueue;
continue;
}
// 若已达普通广播并行上限,仅处理紧急广播队列
if (getRunningSize() >= mConstants.MAX_RUNNING_PROCESS_QUEUES) {
if (!queue.isPendingUrgent()) {
queue = nextQueue;
continue;
}
}
// 若队列未到可运行时间且无等待队列,延迟处理
if (runnableAt > now && !waitingFor) {
mLocalHandler.sendEmptyMessageAtTime(MSG_UPDATE_RUNNING_LIST, runnableAt);
break;
}
// 清除队列的延迟状态(准备分发广播)
queue.clearDeferredStates(mBroadcastConsumerDeferClear);
// 更新进程温/冷状态
updateWarmProcess(queue);
final boolean processWarm = queue.isProcessWarm();
if (processWarm) {
// 热进程:临时解冻OOM调整并检查进程存活状态
mService.mOomAdjuster.unfreezeTemporarily(queue.app,
CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);
if (!queue.isProcessWarm()) { // 解冻后进程可能被杀死
queue = nextQueue;
enqueueUpdateRunningList();
continue;
}
} else {
// 冷进程:同一时间仅允许一个冷启动
if (mRunningColdStart == null) {
mRunningColdStart = queue;
} else if (isPendingColdStartValid()) {
queue = nextQueue;
continue;
} else {
clearInvalidPendingColdStart();
mRunningColdStart = queue;
}
}
if (DEBUG_BROADCAST) logv("Promoting " + queue
+ " from runnable to running; process is " + queue.app);
// 将队列提升为运行状态
promoteToRunningLocked(queue);
boolean completed;
/* 关键分发逻辑 */
if (processWarm) {
// 热进程分发:直接通过Binder调用进程的Receiver
updateOomAdj |= queue.runningOomAdjusted;
try {
completed = scheduleReceiverWarmLocked(queue); // 同步分发广播
} catch (BroadcastRetryException e) {
finishOrReEnqueueActiveBroadcast(queue);
completed = true;
}
} else {
// 冷进程分发:先启动进程再分发
completed = scheduleReceiverColdLocked(queue); // 异步启动进程
}
// 若广播分发完成,将队列降级为非运行状态
if (completed) {
demoteFromRunningLocked(queue);
}
avail--; // 占用一个可用槽位
queue = nextQueue;
}
// 更新OOM调整状态(优化进程优先级)
if (updateOomAdj) {
mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);
}
// 清理无效的冷启动状态
checkPendingColdStartValidityLocked();
checkAndRemoveWaitingFor();
traceEnd(cookie);
}
下一步:分别看下冷和热启动的流程
进程状态处理
热进程:通过 scheduleReceiverWarmLocked 直接分发广播(Binder调用已存在的进程)
冷进程:通过 scheduleReceiverColdLocked 启动新进程(仅允许一个冷启动 mRunningColdStart)
六、广播发送中涉及的冷和热启动的流程处理
先看冷启动,因为冷启动后的流程和热启动广播是一样的哈
6.1 冷启动通过 scheduleReceiverColdLocked 启动新进程
/**
* 当目标进程未启动(冷状态)时调度广播分发的核心逻辑
*
* @param queue 目标进程的广播队列(BroadcastProcessQueue)
* @return true 表示广播分发已完成且队列可降级;false 表示需等待进程启动后继续处理
*
* 关键流程:
* 1. 验证队列状态并标记冷启动标志
* 2. 检查接收者有效性(静态/动态注册、进程状态等)
* 3. 通过AMS启动目标进程
* 4. 记录进程启动信息用于后续热启动分发
*/
@CheckResult
@GuardedBy("mService")
private boolean scheduleReceiverColdLocked(@NonNull BroadcastProcessQueue queue) {
// 1. 验证队列状态(必须处于活跃状态)
checkState(queue.isActive(), "isActive");
queue.setActiveViaColdStart(true); // 标记当前广播通过冷启动分发
// 2. 获取当前待分发的广播和接收者信息
final BroadcastRecord r = queue.getActive();
final int index = queue.getActiveIndex();
final Object receiver = r.receivers.get(index);
// 3. 动态注册接收者(BroadcastFilter)不支持冷启动,直接跳过
if (receiver instanceof BroadcastFilter) {
mRunningColdStart = null;
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED,
"BroadcastFilter for cold app");
return true;
}
// 4. 检查接收者是否应跳过(如权限不足、进程已停止等)
final String skipReason = shouldSkipReceiver(queue, r, index);
if (skipReason != null) {
mRunningColdStart = null;
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);
return true;
}
// 5. 准备进程启动参数
final ApplicationInfo info = ((ResolveInfo) receiver).activityInfo.applicationInfo;
final ComponentName component = ((ResolveInfo) receiver).activityInfo.getComponentName();
// 6. 处理应用停止状态(FLAG_STOPPED)和首次启动标志
if ((info.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
queue.setActiveWasStopped(true); // 标记应用曾被用户强制停止
}
final int intentFlags = r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND;
final boolean firstLaunch = !mService.wasPackageEverLaunched(info.packageName, r.userId);
queue.setActiveFirstLaunch(firstLaunch); // 记录是否为首次启动
// 7. 构建进程启动记录(HostingRecord)和性能策略
final HostingRecord hostingRecord = new HostingRecord(
HostingRecord.HOSTING_TYPE_BROADCAST,
component,
r.intent.getAction(),
r.getHostingRecordTriggerType()
);
final boolean isActivityCapable = (r.options != null
&& r.options.getTemporaryAppAllowlistDuration() > 0);
final int zygotePolicyFlags = isActivityCapable ?
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE : ZYGOTE_POLICY_FLAG_EMPTY;
final boolean allowWhileBooting = (r.intent.getFlags()
& Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0; // 允许在系统启动阶段运行
// 8. 通过AMS启动目标进程
long startTimeNs = SystemClock.uptimeNanos();
if (DEBUG_BROADCAST) logv("Scheduling " + r + " to cold " + queue);
queue.app = mService.startProcessLocked(
queue.processName,
info,
true, // 允许冷启动
intentFlags,
hostingRecord,
zygotePolicyFlags,
allowWhileBooting,
false // 非持久化进程
);
// 9. 进程启动失败处理
if (queue.app == null) {
mRunningColdStart = null;
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
"startProcessLocked failed");
return true;
}
// 10. 记录进程启动信息(用于性能监控)
mService.mProcessList.getAppStartInfoTracker().handleProcessBroadcastStart(
startTimeNs,
queue.app,
r.getReceiverIntent(receiver),
r.alarm /* isAlarm */
);
return false; // 返回false表示需等待进程启动完成后再触发热启动分发
}
冷启动成功后,AMS会通过 attachApplicationLocked 回调重新触发 processNextBroadcast,最终由 scheduleReceiverWarmLocked 完成实际分发,故我们继续看热启动的分发广播流程
6.2 热启动通过 scheduleReceiverWarmLocked 直接分发广播
遍历接收器进程记录内的三个接收器队列,分发广播。
/**
* 向已启动(热)进程分发当前活跃广播的核心逻辑
*
* @param queue 目标进程的广播队列(BroadcastProcessQueue)
* @return true 表示广播分发完成且队列可降级;false 表示需等待异步回调
* @throws BroadcastRetryException 若需重试分发则抛出异常
*
* 关键流程:
* 1. 检查队列状态,确保当前有活跃广播待处理(queue.isActive())
* 2. 记录广播分发的关键时间戳(dispatchTime/dispatchRealTime)
* 3. 检查接收者是否需跳过(权限/进程状态等)
* 4. 调用 dispatchReceivers 执行实际分发(跨进程Binder调用)
* 5. 处理分发结果:若阻塞则返回false,否则继续处理下一个广播
*/
@CheckResult
@GuardedBy("mService")
private boolean scheduleReceiverWarmLocked(@NonNull BroadcastProcessQueue queue)
throws BroadcastRetryException {
checkState(queue.isActive(), "isActive"); // 断言队列处于活跃状态
final int cookie = traceBegin("scheduleReceiverWarmLocked");
while (queue.isActive()) { // 循环处理队列中的活跃广播
final BroadcastRecord r = queue.getActive();
final int index = queue.getActiveIndex();
// 首次分发时记录时间戳(用于ANR计算)
if (r.terminalCount == 0) {
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchRealTime = SystemClock.elapsedRealtime();
r.dispatchClockTime = System.currentTimeMillis();
}
// 检查接收者是否需跳过(如静态接收者限制、进程死亡等)
final String skipReason = shouldSkipReceiver(queue, r, index);
if (skipReason == null) {
// 执行实际分发(跨进程调用 onReceive)
final boolean isBlockingDispatch = dispatchReceivers(queue, r, index);
if (isBlockingDispatch) { // 若需等待异步回调(如有序广播)
traceEnd(cookie);
return false;
}
} else {
// 标记跳过状态并清理资源
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);
}
// 检查队列是否需终止(如进程死亡或广播被取消)
if (shouldRetire(queue)) {
break;
}
// 处理下一个待分发的广播
queue.makeActiveNextPending();
}
traceEnd(cookie);
return true; // 当前批次分发完成
}
下一步:重点关注dispatchReceivers跨进程回调 onReceive的逻辑
七、广播发送-dispatchReceivers函数
有序广播需要等待上一个接受器执行完才能执行下一个接受器。所以系统要求每个有序广播接收器需要在特定的时间内执行完(前台广播10S,后台广播60S),否则就会报ANR
/**
* 分发广播到指定接收者,并启动ANR计时(针对有序广播的核心逻辑)
*
* @param queue 目标进程的广播队列(BroadcastProcessQueue)
* @param r 当前广播记录(BroadcastRecord)
* @param index 接收者在r.receivers列表中的索引
* @return true 表示有序广播需阻塞等待finishReceiver()回调;false 表示无序广播或假设已送达
* @throws BroadcastRetryException 静态接收者分发失败时抛出以重试
*
* 关键流程:
* 1. 启动ANR超时监控(仅有序广播且非豁免场景)
* 2. 处理后台启动权限和进程冷冻豁免
* 3. 通过Binder跨进程调用触发接收者的onReceive()
* 4. 若为有序广播,返回true以阻塞等待finishReceiver()
*/
@GuardedBy("mService")
@CheckResult
private boolean dispatchReceivers(@NonNull BroadcastProcessQueue queue,
@NonNull BroadcastRecord r, int index) throws BroadcastRetryException {
final ProcessRecord app = queue.app;
final Object receiver = r.receivers.get(index);
// --- ANR超时控制 ---
// 仅在系统启动完成、非豁免广播且未假设送达时启动ANR计时
final boolean assumeDelivered = r.isAssumedDelivered(index);
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
queue.setTimeoutScheduled(true);
// 前台广播10秒超时,后台广播60秒超时 [2,5](@ref)
final int softTimeoutMillis = (int) (r.isForeground() ? mFgConstants.TIMEOUT
: mBgConstants.TIMEOUT);
startDeliveryTimeoutLocked(queue, softTimeoutMillis); // 启动ANR计时器
} else {
queue.setTimeoutScheduled(false);
}
// --- 后台启动权限管理 ---
if (r.mBackgroundStartPrivileges.allowsAny()) {
app.addOrUpdateBackgroundStartPrivileges(r, r.mBackgroundStartPrivileges);
final long timeout = r.isForeground() ? mFgConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT
: mBgConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT;
// 延迟消息检查后台启动权限超时
mLocalHandler.sendMessageDelayed(
Message.obtain(mLocalHandler, MSG_BG_ACTIVITY_START_TIMEOUT, args), timeout);
}
// --- 进程冷冻豁免处理 ---
if (r.options != null && r.options.getTemporaryAppAllowlistDuration() > 0) {
if (r.options.getTemporaryAppAllowlistType()
== PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_APP_FREEZING_DELAYED) {
// 临时解冻进程以接收广播
mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER,
r.options.getTemporaryAppAllowlistDuration());
} else {
mService.tempAllowlistUidLocked(queue.uid,
r.options.getTemporaryAppAllowlistDuration(),
r.options.getTemporaryAppAllowlistReasonCode(), r.toShortString(),
r.options.getTemporaryAppAllowlistType(), r.callingUid);
}
}
// --- 分发广播到接收者 ---
final Intent receiverIntent = r.getReceiverIntent(receiver);
final IApplicationThread thread = app.getOnewayThread();
if (thread != null) {
try {
// 动态注册接收者(BroadcastFilter)
if (receiver instanceof BroadcastFilter) {
notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
thread.scheduleRegisteredReceiver(
((BroadcastFilter) receiver).receiverList.receiver,
receiverIntent, r.resultCode, r.resultData, r.resultExtras,
r.ordered, r.initialSticky, assumeDelivered, r.userId,
app.mState.getReportedProcState(),
r.shareIdentity ? r.callingUid : Process.INVALID_UID,
r.shareIdentity ? r.callerPackage : null);
if (assumeDelivered) {
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_DELIVERED,
"assuming delivered");
return false; // 无序广播无需等待
}
}
// 静态注册接收者(ResolveInfo)
else {
notifyScheduleReceiver(app, r, (ResolveInfo) receiver);
thread.scheduleReceiver(receiverIntent, ((ResolveInfo) receiver).activityInfo,
null, r.resultCode, r.resultData, r.resultExtras, r.ordered,
assumeDelivered, r.userId,
app.mState.getReportedProcState(),
r.shareIdentity ? r.callingUid : Process.INVALID_UID,
r.shareIdentity ? r.callerPackage : null);
}
return r.ordered; // 有序广播返回true,需阻塞等待finishReceiver()
} catch (RemoteException e) {
// 静态接收者分发失败时抛出异常以重试 [2](@ref)
if (receiver instanceof ResolveInfo) {
cancelDeliveryTimeoutLocked(queue);
throw new BroadcastRetryException(e);
}
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
return false;
}
} else {
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_FAILURE,
"missing IApplicationThread");
return false;
}
}
下一步:看ApplicationThread.scheduleReceiver
备注:有序广播必须等待前一个接收者的 finishReceiver() 回调后,才能分发到下一个接收者(通过 r.ordered 返回 true 实现)
八、广播发送-ApplicationThread.scheduleRegisteredReceiver函数
调度动态注册的广播接收器(跨进程调用入口)
/**
* 调度动态注册的广播接收器(跨进程调用入口)
*
* 核心作用:
* 1. 确保动态注册的广播接收器按正确顺序分发(Binder单线程模型下保证有序性)
* 2. 通过类型检查将调用路由到具体的 `InnerReceiver` 实现类
* 3. 处理发送方身份信息(UID/Package)的传递校验
*
* @param receiver 动态注册的接收器Binder代理(通常为InnerReceiver实例)
* @param intent 广播Intent
* @param assumeDelivered 是否假设广播已送达(避免ANR检查)
* @param sendingUid 发送方UID(用于身份校验)
* @param sendingPackage 发送方包名(用于身份校验)
*/
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, boolean assumeDelivered, int sendingUser, int processState,
int sendingUid, String sendingPackage) throws RemoteException {
// 更新进程状态(优化调度优先级)
updateProcessState(processState, false);
// --- 关键分发逻辑 ---
if (receiver instanceof LoadedApk.ReceiverDispatcher.InnerReceiver) {
// 标准路径:通过InnerReceiver触发接收逻辑
((LoadedApk.ReceiverDispatcher.InnerReceiver) receiver).performReceive(intent,
resultCode, dataStr, extras, ordered, sticky, assumeDelivered, sendingUser,
sendingUid, sendingPackage); // [下一步分析点]
} else {
// 非标准路径:自定义IIntentReceiver的兼容性处理
if (!assumeDelivered) {
Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver
+ " and " + intent + " without mechanism to finish delivery");
}
// 校验发送方身份信息传递完整性
if (sendingUid != Process.INVALID_UID || sendingPackage != null) {
Log.wtf(TAG, "scheduleRegisteredReceiver() called for " + receiver + " and " + intent
+ " from " + sendingPackage + " (UID: " + sendingUid
+ ") without mechanism to propagate the sender's identity");
}
// 降级处理:直接调用performReceive(无身份校验)
receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky,
sendingUser);
}
}
下一步:通过InnerReceiver触发接收逻辑,InnerReceiver.performReceive() → ReceiverDispatcher.performReceive() → 通过主线程Handler执行 Args.run() → 最终调用 BroadcastReceiver.onReceive()
九、广播发送-LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive()函数
继续套娃哈
/**
* 处理广播接收的核心方法(Binder服务端实现)
*
* 核心职责:
* 1. 校验Intent有效性并获取关联的ReceiverDispatcher
* 2. 将广播分发给注册的BroadcastReceiver(通过rd.performReceive)
* 3. 处理接收者已注销时的异常情况(通过AMS.finishReceiver回调)
*
* @param assumeDelivered 是否假设广播已送达(跳过ANR检查)
* @param sendingUid 发送方UID(用于权限校验)
* @param sendingPackage 发送方包名(用于权限校验)
*/
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
int sendingUser, int sendingUid, String sendingPackage) {
// 1. 获取ReceiverDispatcher弱引用(可能因进程回收或注销变为null)
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get(); // 从WeakReference获取ReceiverDispatcher
}
// 2. 调试日志记录广播接收详情
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
}
// 3. 分两种情况处理广播
if (rd != null) {
// 正常路径:通过ReceiverDispatcher分发广播
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, assumeDelivered, sendingUser,
sendingUid, sendingPackage); // [关键调用点]
} else if (!assumeDelivered) {
// 异常路径:接收者已注销但仍需通知AMS完成广播序列
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false); // 禁用文件描述符传递(安全措施)
}
// 强制通知AMS完成广播序列(避免阻塞后续广播)
mgr.finishReceiver(mApplicationThread.asBinder(), resultCode, data,
extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* 处理广播分发的核心方法(通过主线程Handler调度)
*
* 核心职责:
* 1. 封装广播参数为Args对象(包含Intent、结果码、附加数据等)
* 2. 通过主线程Handler异步执行广播处理(避免阻塞Binder线程)
* 3. 处理分发失败或Intent为空的异常情况(强制通知AMS完成流程)
*
* @param assumeDelivered 是否假设广播已送达(跳过ANR检查)
* @param sendingUid 发送方UID(用于权限校验)
* @param sendingPackage 发送方包名(用于身份校验)
*/
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, boolean assumeDelivered,
int sendingUser, int sendingUid, String sendingPackage) {
// 1. 封装广播参数到Args对象(包含后续执行的Runnable逻辑)
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, assumeDelivered, sendingUser, sendingUid, sendingPackage);
// 2. 校验Intent有效性并记录调试日志
if (intent == null) {
Log.wtf(TAG, "Null intent received"); // 异常情况:Intent为空
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver); // 记录广播入队信息[3](@ref)
}
}
// 3. 通过主线程Handler调度广播处理(关键异步化设计)
if (intent == null || !mActivityThread.post(args.getRunnable())) {
// 异常处理:Intent为空或主线程调度失败
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
// 强制通知AMS完成广播流程(避免有序广播阻塞)[2,5](@ref)
args.sendFinished(mgr);
}
}
下一步重点关注:LoadedApk.ReceiverDispatcher.Args.getRunnable()
十、广播发送-LoadedApk.ReceiverDispatcher.Args.getRunnable()函数
这个函数完成后,APP就
/**
* 生成广播分发的Runnable任务(最终触发BroadcastReceiver.onReceive()的核心逻辑)
*
* 核心职责:
* 1. 封装广播分发逻辑为Lambda表达式(通过主线程Handler执行)
* 2. 处理Intent和Receiver的异常情况(空值检查、重复分发等)
* 3. 调用BroadcastReceiver.onReceive()并处理异常
* 4. 通过sendFinished()通知AMS广播处理完成(避免ANR)
*
* 调用链:
* AMS -> InnerReceiver.performReceive() -> ReceiverDispatcher.getRunnable() -> onReceive()
*/
public final Runnable getRunnable() {
return () -> {
// 1. 获取广播接收器和Intent(通过成员变量传递)
final BroadcastReceiver receiver = mReceiver;
final Intent intent = mCurIntent;
// 2. 调试日志记录广播分发信息
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Dispatching broadcast " + intent.getAction()
+ " seq=" + seq + " to " + receiver);
}
// 3. 异常检查:Intent为空或接收器已失效
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
+ (mRunCalled ? ", run() has already been called" : ""));
}
mCurIntent = null; // 清除Intent引用防止重复使用
mDispatched = true; // 标记已分发
mRunCalled = true; // 标记已执行
// 4. 快速失败:接收器/Intent为空或已注销
if (receiver == null || intent == null || mForgotten) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + receiver);
sendFinished(ActivityManager.getService()); // 通知AMS结束流程
return;
}
// 5. 开始性能追踪(用于Systrace工具分析)
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"broadcastReceiveReg: " + intent.getAction());
}
try {
// 6. 准备Intent的ClassLoader(确保反序列化正确)
ClassLoader cl = receiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess(
ActivityThread.isProtectedBroadcast(intent),
mContext.getAttributionSource()
);
// 7. 关键调用:触发BroadcastReceiver.onReceive()
receiver.setPendingResult(this); // 绑定结果回调
receiver.onReceive(mContext, intent); // 实际业务逻辑执行点
} catch (Exception e) {
// 8. 异常处理:记录日志并通知AMS
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + receiver);
sendFinished(ActivityManager.getService());
if (mInstrumentation == null || !mInstrumentation.onException(receiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent + " in " + receiver, e);
}
}
// 9. 检查未完成的广播结果(如有序广播未调用setResult)
if (receiver.getPendingResult() != null) {
finish(); // 强制结束广播流程
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // 结束性能追踪
};
}
Args.run,最终回调receiver.onReceive方法,至此,广播的发送和接收过程分析完毕。