目录
二、动态广播接收器注册/注销(AMS 记录BroadcastReceiver)
Android 14之后,动态注册广播接收器需要显示标志能否接收应用外部的广播
一、广播分类
1. 普通广播(Unordered Broadcast)
普通广播是最简单的广播类型,一旦广播发出,所有的接收者都会收到这个广播,但接收的顺序是不确定的。
特点
* 无序性:接收者的接收顺序不确定。
* 不可拦截:广播发出后无法被任何接收者取消或拦截。
* 效率较高:因为不需要按顺序处理。
发送普通广播:sendBroadcast(intent);
2. 有序广播(Ordered Broadcast)
有序广播是按照优先级顺序依次传递给各个注册了该广播的接收者。每个接收者都可以选择是否继续传递广播,或者终止广播的传递。
特点
* 有序性:接收者按照优先级顺序接收广播。
* 可拦截:接收者可以选择终止广播,阻止后续的接收者接收到广播。
* 可以修改数据:接收者可以修改广播 Intent 中的数据,并传递给下一个接收者。
发送有序广播:sendOrderedBroadcast
3. 粘性广播(Sticky Broadcast)
粘性广播在发出后会被系统保留,直到被显式地清除。即使在广播发出后,没有接收者注册,稍后注册的接收者仍然可以接收到这个广播。
特点
* 持久性:广播发出后会被系统保留,直到被显式地清除。
* 可以被多次接收:即使没有接收者在广播发出时注册,稍后注册的接收者仍然可以接收到这个广播。
发送粘性广播:ActivityManager.broadcastStickyIntent(intent, AppOpsManager.OP_NONE,
mBatteryChangedOptions, UserHandle.USER_ALL)
粘性广播的注意事项
由于粘性广播在发出后会被系统保留,因此需要谨慎使用,避免潜在的内存泄露问题。此外,从 Android 8.0(API 级别 26)开始,系统对粘性广播的支持有所限制,因此建议尽量避免使用粘性广播,改用其他机制(如 LocalBroadcastManager)来实现类似的功能。
二、动态广播接收器注册/注销(AMS 记录BroadcastReceiver)
动态广播接收器打包成BroadcastFilter,记录在mReceiverResolver列表中
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
#registerReceiver
//mRegisteredReceivers记录BroadcastReceiver
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
mRegisteredReceivers.put(receiver.asBinder(), rl);
//mReceiverResolver记录IntentFilter
roadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
receiverId, permission, callingUid, userId, instantApp, visibleToInstantApps,
exported);
rl.add(bf);
mReceiverResolver.addFilter(getPackageManagerInternal().snapshot(), bf);
#removeReceiverLocked
void removeReceiverLocked(ReceiverList rl) {
mRegisteredReceivers.remove(rl.receiver.asBinder());
for (int i = rl.size() - 1; i >= 0; i--) {
mReceiverResolver.removeFilter(rl.get(i));
}
}
三、发送/接收广播
broadcastIntentLocked
1、找出符合条件的静态接收器和动态接收器
2、若是无序广播,将动态接收器打包成一条广播记录,先进入无序广播队列,并行分发广播
3、按优先级将静态和动态接收器合并到一个接收器队列
4、将3中得到的接收器队列打包成一条广播记录,进入有序广播队列,串行分发广播
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
SparseArray<ArrayMap<String, ArrayList<StickyBroadcast>>> mStickyBroadcasts 粘性广播
#broadcastIntentLocked
//搜索AndroidManifest.xml中注册的Receiver
if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
receivers = collectReceiverComponents(
intent, resolvedType, callingUid, users, broadcastAllowList);
}
//获取代码动态注册的Receiver
registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
resolvedType, false /*defaultOnly*/, userId);
//若是无序广播,则将符合条件的动态注册接收器和广播Intent打包成一条广播记录(BroadcastRecord),并进入并行队列{
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0 && !mEnableModernQueue) { //若是无序广播
final BroadcastQueue queue = broadcastQueueForIntent(intent);
//将符合条件的动态注册接收器和广播Intent打包成一条广播记录(BroadcastRecord)
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
registeredReceivers, resultToApp, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId,
backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
callerAppProcessState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
queue.enqueueBroadcastLocked(r); //广播记录进入并行队列
registeredReceivers = null;
NR = 0;
} //}若是无序广播,则将符合条件的动态注册接收器和广播Intent打包成一条广播记录(BroadcastRecord),并进入并行队列
// Merge into one list. 当是有序广播时,将动态和静态接收器按优先级合并到一个队列{
int ir = 0;
// 比较优先级,先合并完静态接收器{
if (receivers != null) {
int NT = receivers != null ? receivers.size() : 0;
int it = 0;
ResolveInfo curt = null; //当前静态接收器
BroadcastFilter curr = null;//当前动态接收器
while (it < NT && ir < NR) {//只有是有序广播才会执行,因为无序广播此时NR=0
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
// 优先级高的(priority大的)靠前 {
if (curr.getPriority() >= curt.priority) {
// 动态接收器优先级高,先进队列
receivers.add(it, curr);//这里插入到it位置,it之后的元素应该会整体在队列往后移一位
ir++;
curr = null;
it++;
NT++;
} else {
// 静态接收器优先级高,先进队列
it++;
curt = null;
}
// }优先级高的(priority大的)靠前
}
} // }比较优先级,先合并完静态广播
//将剩下的动态接收器合并到队尾
while (ir < NR) {//只有是有序广播才会执行,因为无序广播此时NR=0
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(registeredReceivers.get(ir));
ir++;
}//}将剩下的动态接收器合并到列表
// }Merge into one list. 当是有序广播时,将动态和静态接收器按优先级合并到一个队列
//有序广播进入队有序广播队列
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
filterNonExportedComponents(intent, callingUid, callingPid, receivers,
mPlatformCompat, callerPackage, resolvedType);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, excludedPermissions, excludedPackages, appOp, brOptions,
receivers, resultToApp, resultTo, resultCode, resultData, resultExtras,
ordered, sticky, false, userId,
backgroundStartPrivileges, timeoutExempt, filterExtrasForReceiver,
callerAppProcessState);
//即使是无序广播的静态接收器,在这里也是进入有序队列,并按顺序分发广播
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r);
queue.enqueueBroadcastLocked(r);
} else {
//没有感兴趣的广播接收器
// UNISOC: add log for debug broadcast skipped
Slog.d(TAG, "Skip enqueue broadcast because no receiver with " + intent);
// There was nobody interested in the broadcast, but we still want to record
// that it happened.
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);
}
}
enqueueBroadcastLocked
1、根据进程名和Uid找出或创建接收器进程记录(BroadcastProcessQueue)。
2、将接收器添加到接收器进程记录内的mPending、mPendingUrgent和mPendingOffload三个接收器队列中的一个
3、将接收器进程记录添加到进程队列(mRunnableHead),越早排队优先级越高
4、enqueueUpdateRunningList分发广播
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
#ActivityManagerService构造方中:
if (mEnableModernQueue) { //14之后默认开启
mBroadcastQueues = new BroadcastQueue[1];
mBroadcastQueues[0] = new BroadcastQueueModernImpl(this, mHandler,
foreConstants, backConstants);
}
BroadcastQueue broadcastQueueForFlags(int flags, Object cookie) {
if (mEnableModernQueue) {//14之后默认开启
return mBroadcastQueues[0];
}
}
frameworks/base/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
public void enqueueBroadcastLocked(@NonNull BroadcastRecord r) {
//UNISOC: remove DEBUG_BROADCAST switch for debug
StringBuilder allReceivers = new StringBuilder();
if (DEBUG_BROADCAST) {
allReceivers.append(":");
allReceivers.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);
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),以进程名和Uid为主键。
//2、在这里是根据接收器的进程名和Uid找出或常见接收器进程记录
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), getReceiverUid(receiver));
// If this receiver is going to be skipped, skip it now itself and don't even enqueue
// it.
// 判断接收器是否跳过,如:静态接收器只能接收到显性广播
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;
// 每个接收器进程记录包含三个队列mPending、mPendingUrgent和mPendingOffload,这三个队列都是用来记录接收器信息,只是优先级不一样
// 将接收器添加到广播进程队列内的三个队列中的一个
final BroadcastRecord replacedBroadcast = queue.enqueueOrReplaceBroadcast(
r, i, mBroadcastConsumerDeferApply);
if (replacedBroadcast != null) {
replacedBroadcasts.add(replacedBroadcast);
}
// mRunnableHead是所有接收器进程记录的队列头,将接收器进程记录添加到mRunnableHead队列中
updateRunnableList(queue);
// 在AMS的线程中执行,分发广播。
enqueueUpdateRunningList();
}
// Skip any broadcasts that have been replaced by newer broadcasts with
// FLAG_RECEIVER_REPLACE_PENDING.
// TODO: Optimize and reuse mBroadcastConsumerSkipAndCanceled for the case of
// cancelling all receivers for a broadcast.
skipAndCancelReplacedBroadcasts(replacedBroadcasts);
replacedBroadcasts.clear();
mReplacedBroadcastsCache.compareAndSet(null, replacedBroadcasts);
// If nothing to dispatch, send any pending result immediately
if (r.receivers.isEmpty() || !enqueuedBroadcast) {
scheduleResultTo(r);
notifyFinishBroadcast(r);
}
traceEnd(cookie);
}
updateRunningListLocked
遍历mRunnableHead队列,接收器进程已启动则使用scheduleReceiverWarmLocked分发广播,否则使用scheduleReceiverColdLocked分发广播
private void updateRunningListLocked() {
// Allocated size here implicitly includes the extra reservation for urgent
// dispatches beyond the MAX_RUNNING_QUEUES soft limit for normal
// parallelism. If we're already dispatching some urgent broadcasts,
// count that against the extra first - its role is to permit progress of
// urgent broadcast traffic when the normal reservation is fully occupied
// with less-urgent dispatches, not to generally expand parallelism.
final int usedExtra = Math.min(getRunningUrgentCount(),
mConstants.EXTRA_RUNNING_URGENT_PROCESS_QUEUES);
int avail = mRunning.length - getRunningSize() - usedExtra;
if (avail == 0) {
Slog.d(TAG, "Skip update running list, mRunnableHead=" + mRunnableHead
+ " Max running broadcast queue size is " + mRunning.length
+ " current is " + getRunningSize() + " usedExtra is " + usedExtra);
return;
}
final int cookie = traceBegin("updateRunningList");
final long now = SystemClock.uptimeMillis();
// If someone is waiting for a state, everything is runnable now
final boolean waitingFor = !mWaitingFor.isEmpty();
// We're doing an update now, so remove any future update requests;
// we'll repost below if needed
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();
// When broadcasts are skipped or failed during list traversal, we
// might encounter a queue that is no longer runnable; skip it
if (!queue.isRunnable()) {
queue = nextQueue;
continue;
}
// If we've hit the soft limit for non-urgent dispatch parallelism,
// only consider delivering from queues whose ready broadcast is urgent
if (getRunningSize() >= mConstants.MAX_RUNNING_PROCESS_QUEUES) {
if (!queue.isPendingUrgent()) {
queue = nextQueue;
continue;
}
}
// If queues beyond this point aren't ready to run yet, schedule
// another pass when they'll be runnable
if (runnableAt > now && !waitingFor) {
mLocalHandler.sendEmptyMessageAtTime(MSG_UPDATE_RUNNING_LIST, runnableAt);
break;
}
// We might not have heard about a newly running process yet, so
// consider refreshing if we think we're cold
updateWarmProcess(queue);
final boolean processWarm = queue.isProcessWarm();
if (processWarm) {
mService.mOomAdjuster.unfreezeTemporarily(queue.app,
CachedAppOptimizer.UNFREEZE_REASON_START_RECEIVER);
// The process could be killed as part of unfreezing. So, check again if it
// is still warm.
if (!queue.isProcessWarm()) {
queue = nextQueue;
enqueueUpdateRunningList();
continue;
}
} else {
// We only offer to run one cold-start at a time to preserve
// system resources; below we either claim that single slot or
// skip to look for another warm process
if (mRunningColdStart == null) {
mRunningColdStart = queue;
} else if (isPendingColdStartValid()) {
// Move to considering next runnable queue
queue = nextQueue;
continue;
} else {
// Pending cold start is not valid, so clear it and move on.
clearInvalidPendingColdStart();
mRunningColdStart = queue;
}
}
if (DEBUG_BROADCAST) logv("Promoting " + queue
+ " from runnable to running; process is " + queue.app);
promoteToRunningLocked(queue);
boolean completed;
if (processWarm) {
updateOomAdj |= queue.runningOomAdjusted;
try {
completed = scheduleReceiverWarmLocked(queue);
} catch (BroadcastDeliveryFailedException e) {
reEnqueueActiveBroadcast(queue);
completed = true;
}
} else {
completed = scheduleReceiverColdLocked(queue);
}
// If we are done with delivering the broadcasts to the process, we can demote it
// from the "running" list.
if (completed) {
demoteFromRunningLocked(queue);
}
// TODO: If delivering broadcasts to a process is finished, we don't have to hold
// a slot for it.
avail--;
// Move to considering next runnable queue
queue = nextQueue;
}
// TODO: We need to update oomAdj early as this currently doesn't guarantee that the
// procState is updated correctly when the app is handling a broadcast.
if (updateOomAdj) {
mService.updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_START_RECEIVER);
}
checkPendingColdStartValidity();
checkAndRemoveWaitingFor();
traceEnd(cookie);
}
scheduleReceiverWarmLocked
遍历接收器进程记录内的三个接收器队列,分发广播。
private boolean scheduleReceiverWarmLocked(@NonNull BroadcastProcessQueue queue)
throws BroadcastDeliveryFailedException {
checkState(queue.isActive(), "isActive");
final int cookie = traceBegin("scheduleReceiverWarmLocked");
while (queue.isActive()) {
final BroadcastRecord r = queue.getActive();
final int index = queue.getActiveIndex();
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) {
final boolean isBlockingDispatch = dispatchReceivers(queue, r, index);
if (isBlockingDispatch) {
traceEnd(cookie);
return false;
}
} else {
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_SKIPPED, skipReason);
}
if (shouldRetire(queue)) {
break;
}
// We're on a roll; move onto the next broadcast for this process
queue.makeActiveNextPending();
}
traceEnd(cookie);
return true;
}
四、遇到一些的问题
Android 14之后,动态注册广播接收器需要显示标志能否接收应用外部的广播
//RECEIVER_EXPORTED 表示可以接收应用外部广播,ContextRECEIVER_NOT_EXPORTED 应用内部广播
registerReceiver(mReceiver2, intentFilter, Context.RECEIVER_EXPORTED);
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
#registerReceiver
//动态广播接收器是否有标志RECEIVER_EXPORTED或RECEIVER_NOT_EXPORTED
final boolean explicitExportStateDefined =
(flags & (Context.RECEIVER_EXPORTED | Context.RECEIVER_NOT_EXPORTED)) != 0;
//动态广播接收器是否需要显式标志RECEIVER_EXPORTED或RECEIVER_NOT_EXPORTED
boolean requireExplicitFlagForDynamicReceivers = CompatChanges.isChangeEnabled(
DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid);
//动态广播接收器没有显式标志RECEIVER_EXPORTED或RECEIVER_NOT_EXPORTED时,抛出异常
else if (requireExplicitFlagForDynamicReceivers && !explicitExportStateDefined) {
throw new SecurityException(
callerPackage + ": One of RECEIVER_EXPORTED or "
+ "RECEIVER_NOT_EXPORTED should be specified when a receiver "
+ "isn't being registered exclusively for system broadcasts");
// Assume default behavior-- flag check is not enforced
}
// Dynamic receivers are exported by default for versions prior to T
final boolean exported = (flags & Context.RECEIVER_EXPORTED) != 0;
#broadcastIntentLocked
//过滤RECEIVER_NOT_EXPORTED动态广播接收器
filterNonExportedComponents(intent, callingUid, callingPid, registeredReceivers,
mPlatformCompat, callerPackage, resolvedType);
广播接收器接收广播政策
并不是每个广播接收器都能接收到广播,是在
BroadcastSkipPolicy#shouldSkipMessage有条件判断接收器收否能接受到广播
如静态接收器不能接收到隐式广播,log报:
Background execution not allowed
frameworks/base/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
#enqueueBroadcastLocked
for (int i = 0; i < r.receivers.size(); i++) {
final Object receiver = r.receivers.get(i);
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), getReceiverUid(receiver));
// If this receiver is going to be skipped, skip it now itself and don't even enqueue
// it.
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;
}
}
frameworks/base/services/core/java/com/android/server/am/BroadcastSkipPolicy.java
#shouldSkipMessage
final int allowed = mService.getAppStartModeLOSP(
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false, false);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
// We won't allow this receiver to be launched if the app has been
// completely disabled from launches, or it was not explicitly sent
// to it and the app is in a state that should not receive it
// (depending on how getAppStartModeLOSP has determined that).
if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
return "Background execution disabled: receiving "
+ r.intent + " to "
+ component.flattenToShortString();
} else if (disallowBackgroundStart(r)) {
mService.addBackgroundCheckViolationLocked(r.intent.getAction(),
component.getPackageName());
return "Background execution not allowed: receiving "
+ r.intent + " to "
+ component.flattenToShortString();
}
}
Android 14 有序广播 ANR
有序广播需要等待上一个接受器执行完才能执行下一个接受器。所以系统要求每个有序广播接收器需要在特定的时间内执行完(前台广播10S,后台广播60S),否则就会报ANR
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
static final int BROADCAST_FG_TIMEOUT = (Build.isDebuggable()?40:10) * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
static final int BROADCAST_BG_TIMEOUT = (Build.isDebuggable()?90:60) * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
frameworks/base/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
private boolean dispatchReceivers(@NonNull BroadcastProcessQueue queue,
@NonNull BroadcastRecord r, int index) throws BroadcastDeliveryFailedException {
final ProcessRecord app = queue.app;
final Object receiver = r.receivers.get(index);
// Skip ANR tracking early during boot, when requested, or when we
// immediately assume delivery success
final boolean assumeDelivered = r.isAssumedDelivered(index); //是否是无序动态接收器
if (mService.mProcessesReady && !r.timeoutExempt && !assumeDelivered) {
queue.lastCpuDelayTime = queue.app.getCpuDelayTime();
final int softTimeoutMillis = (int) (r.isForeground() ? mFgConstants.TIMEOUT
: mBgConstants.TIMEOUT);
//当超时后,执行finishReceiverActiveLocked
mLocalHandler.sendMessageDelayed(Message.obtain(mLocalHandler,
MSG_DELIVERY_TIMEOUT_SOFT, softTimeoutMillis, 0, queue), softTimeoutMillis);
}
if (assumeDelivered) {
//无序动态接收器,标志为已分发完广播
finishReceiverActiveLocked(queue, BroadcastRecord.DELIVERY_DELIVERED,
"assuming delivered");
return false;
}
}
private void finishReceiverActiveLocked(@NonNull BroadcastProcessQueue queue,
@DeliveryState int deliveryState, @NonNull String reason) {
//若是广播已经分发,则忽略
if (!queue.isActive()) {
logw("Ignoring finishReceiverActiveLocked; no active broadcast for " + queue);
return;
}
if (deliveryState == BroadcastRecord.DELIVERY_TIMEOUT) {// 超时无响应,后台广播默认60s,前台广播默认10s
r.anrCount++;
if (app != null && !app.isDebugging()) {
final String packageName = getReceiverPackageName(receiver);
final String className = getReceiverClassName(receiver);
mService.appNotResponding(queue.app,
TimeoutRecord.forBroadcastReceiver(r.intent, packageName, className));
}
} else {
mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_SOFT, queue);
mLocalHandler.removeMessages(MSG_DELIVERY_TIMEOUT_HARD, queue);
}
}
在向特定package分发广播前,修改广播数据
private boolean dispatchReceivers(@NonNull BroadcastProcessQueue queue,
@NonNull BroadcastRecord r, int index) throws BroadcastDeliveryFailedException {
final Intent receiverIntent = r.getReceiverIntent(receiver);
if("package"equals(queue.getPackageName()) && "action".equals(receiverIntent.getAction())){
int temperature =receiverIntent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
receiverIntent.putExtra(BatteryManager.EXTRA_TEMPERATURE,temperature < 43 ? temperature:42.9);
}
}
dumpsys activity broadcasts
ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)
📋 Per-process queues: //接收器进程记录
a067f51 5587:com.sprd.engineermode/u0a108 not runnable because INFINITE_DEFER
state:FRZ
e:3 d:3 f:0 fd:0 o:0 a:0 p:3 pd:3 int:0 rt:0 ins:0 m:0 csi:0 adcsi:0 ccu:3 ccn:53
-9s918ms 3be1f0 android.intent.action.BATTERY_CHANGED/u-1
DEFERRED for registered 614d6a1
blocked until 7, currently at 24 of 24
-9s918ms 3be1f0 android.intent.action.BATTERY_CHANGED/u-1
DEFERRED for registered ab9a91a
blocked until 7, currently at 24 of 24
-9s918ms 3be1f0 android.intent.action.BATTERY_CHANGED/u-1
DEFERRED for registered 936b32f
blocked until 7, currently at 24 of 24
926a5c1 22881:com.google.android.apps.tachyon/u0a141 not runnable because INFINITE_DEFER
state:FRZ
runningOomAdjusted:true
e:2 d:2 f:0 fd:0 o:0 a:0 p:1 pd:1 int:0 rt:0 ins:0 m:0 csi:0 adcsi:0 ccu:0 ccn:2
-10s410ms 7597a9 android.intent.action.ACTION_POWER_CONNECTED/u-1
DEFERRED for registered 5695093
-9s918ms 3be1f0 android.intent.action.BATTERY_CHANGED/u-1
DEFERRED for registered 5695093
blocked until 7, currently at 24 of 24
🧍 Runnable:
(none)
🏃 Running:
(none)
(none)
(none)
(none)
(none)
Broadcasts with ignored delivery group policies:
{}
Foreground UIDs:
{10210=true}
Broadcast parameters (key=bcast_fg_constants, observing=true):
bcast_timeout=+40s0ms //debug软件前台广播默认40s超时
bcast_slow_time=+5s0ms
bcast_deferral=+5s0ms
bcast_deferral_decay_factor=0.75
bcast_deferral_floor=0
bcast_allow_bg_activity_start_timeout=+10s0ms
Broadcast parameters (namespace=activity_manager_native_boot):
modern_queue_enabled=true
bcast_max_running_process_queues=4
bcast_max_running_active_broadcasts=16
bcast_max_core_running_blocking_broadcasts=16
bcast_max_core_running_non_blocking_broadcasts=64
bcast_max_pending_broadcasts=256
bcast_delay_normal_millis=+500ms
bcast_delay_cached_millis=+2m0s0ms
bcast_delay_urgent_millis=-2m0s0ms
bcast_delay_foreground_proc_millis=-2m0s0ms
bcast_delay_persistent_proc_millis=-2m0s0ms
bcast_max_history_complete_size=256
bcast_max_history_summary_size=1024
bcast_max_consecutive_urgent_dispatches=3
bcast_max_consecutive_normal_dispatches=10
bcast_core_defer_until_active=true
pending_cold_start_check_interval_millis=30000
Pending broadcasts:
Broadcast #1:
BroadcastRecord{3be1f0 android.intent.action.BATTERY_CHANGED/u-1} to user -1
Intent { act=android.intent.action.BATTERY_CHANGED flg=0x60000010 (has extras) }
extras: Bundle[{technology=Li-ion, icon-small=17303669, max_charging_voltage=5000000, health=2, max_charging_current=500000, status=2, plugged=2, present=true, android.os.extra.CHARGING_STATUS=0, seq=218, charge_counter=105032, level=100, scale=100, temperature=310, voltage=4391, android.os.extra.CYCLE_COUNT=2968, invalid_charger=0, battery_low=false}]
caller=null null pid=1330 uid=1000
options=Bundle[{android:broadcast.deferralPolicy=2, android:broadcast.deliveryGroupPolicy=1}]
enqueueClockTime=2023-12-31 23:00:08.534 dispatchClockTime=2023-12-31 23:00:08.540
dispatchTime=-9s914ms (+6ms since enq) receiverTime=--
resultAbort=false ordered=false sticky=true initialSticky=false originalStickyCallingUid=-1
terminalCount=20
DELIVERED scheduled +7ms terminal 0 (0) #0: BroadcastFilter{d28a248 1000/u0 ReceiverList{7fc4eb 1330 system/1000/u0 local:77103a}}
reason: assuming delivered
DELIVERED scheduled +8ms terminal 0 (0) #1: BroadcastFilter{6c7aa69 1000/u0 ReceiverList{68d44f0 1330 system/1000/u0 local:1ec2933}}
reason: assuming delivered
DELIVERED scheduled +9ms terminal 0 (0) #2: BroadcastFilter{413a5f 1000/u0 ReceiverList{76fe2fe 1330 system/1000/u0 local:e895eb9}}
reason: assuming delivered
DELIVERED scheduled +10ms terminal +1ms (0) #3: BroadcastFilter{d0b673d 1000/u0 ReceiverList{ad16094 1330 system/1000/u0 local:7ae9ce7}}
reason: assuming delivered
DELIVERED scheduled +12ms terminal 0 (0) #4: BroadcastFilter{3d38cc5 1000/u0 ReceiverList{184073c 1330 system/1000/u0 local:a8e952f}}
reason: assuming delivered
DELIVERED scheduled +12ms terminal 0 (0) #5: BroadcastFilter{4ee9af5 1000/u0 ReceiverList{7e6b02c 1330 system/1000/u0 local:5ff8bdf}}
reason: assuming delivered
DELIVERED scheduled +13ms terminal 0 (0) #6: BroadcastFilter{272b94a 1000/u-1 ReceiverList{64baeb5 1330 system/1000/u-1 local:880baec}}
reason: assuming delivered
DELIVERED scheduled +15ms terminal 0 (7) #7: BroadcastFilter{10679e 1000/u0 ReceiverList{73c91d9 1330 system/1000/u0 local:5106420}}
reason: assuming delivered
DELIVERED scheduled +16ms terminal +1ms (7) #8: BroadcastFilter{c35db 1000/u0 ReceiverList{bfbeeea 1330 system/1000/u0 local:e47b6d5}}
reason: assuming delivered
DELIVERED scheduled +18ms terminal 0 (7) #9: BroadcastFilter{7031077 1000/u0 ReceiverList{8c96276 1330 system/1000/u0 local:c93d111}}
reason: assuming delivered
DELIVERED scheduled +19ms terminal 0 (7) #10: BroadcastFilter{6d0e5e9 1000/u0 ReceiverList{3503e70 1330 system/1000/u0 local:36118b3}}
reason: assuming delivered
DELIVERED scheduled +20ms terminal 0 (7) #11: BroadcastFilter{88d7e8a 1000/u0 ReceiverList{d2d40f5 1330 system/1000/u0 local:1002e2c}}
reason: assuming delivered
DELIVERED scheduled +22ms terminal 0 (7) #12: BroadcastFilter{4425832 10168/u0 ReceiverList{e1767a6 1981 com.android.systemui/10168/u0 remote:2ceed01}}
reason: assuming delivered
DELIVERED scheduled +24ms terminal +1ms (7) #13: BroadcastFilter{1d381a2 1001/u0 ReceiverList{6fb816d 1960 com.android.phone/1001/u0 remote:b45c584}}
reason: assuming delivered
DELIVERED scheduled +25ms terminal +1ms (7) #14: BroadcastFilter{34f93b6 1001/u0 ReceiverList{9faff51 1960 com.android.phone/1001/u0 remote:466bc78}}
reason: assuming delivered
DELIVERED scheduled +21ms terminal 0 (7) #15: BroadcastFilter{8f5c89c 1000/u-1 ReceiverList{553000f 1330 system/1000/u-1 local:41b716e}}
reason: assuming delivered
DELIVERED scheduled +23ms terminal 0 (7) #16: BroadcastFilter{6fb0907 10168/u0 ReceiverList{6daa346 1981 com.android.systemui/10168/u0 remote:6315321}}
reason: assuming delivered
DELIVERED scheduled +22ms terminal 0 (7) #17: BroadcastFilter{515841 1000/u0 ReceiverList{d8c2328 1330 system/1000/u0 local:ef3d4b}}
reason: assuming delivered
DELIVERED scheduled +28ms terminal 0 (7) #18: BroadcastFilter{bd2efd 10130/u0 ReceiverList{c126f54 3139 com.google.android.googlequicksearchbox:interactor/10130/u0 remote:7a3aea7}}
reason: assuming delivered
DELIVERED scheduled +24ms terminal 0 (7) #19: BroadcastFilter{60e1d52 10168/u0 ReceiverList{1357ddd 1981 com.android.systemui/10168/u0 remote:bd12db4}}
reason: assuming delivered
DEFERRED (7) #20: BroadcastFilter{614d6a1 10108/u0 ReceiverList{c0f1f08 5587 com.sprd.engineermode/10108/u0 remote:cb33cab}}
reason: mBroadcastConsumerDeferApply
DEFERRED (7) #21: BroadcastFilter{ab9a91a 10108/u0 ReceiverList{5bc3bc5 5587 com.sprd.engineermode/10108/u0 remote:1f6123c}}
reason: mBroadcastConsumerDeferApply
DEFERRED (7) #22: BroadcastFilter{936b32f 10108/u0 ReceiverList{47f7d0e 5587 com.sprd.engineermode/10108/u0 remote:dadd709}}
reason: mBroadcastConsumerDeferApply
DEFERRED (7) #23: BroadcastFilter{5695093 10141/u0 ReceiverList{366182 22881 com.google.android.apps.tachyon/10141/u0 remote:6074cd}}
reason: mBroadcastConsumerDeferApply
log
2024-01-01 00:37:11.637 1330-3251/? V/ActivityManager: Broadcast: Intent { act=com.example.customview.MY_BROADCAST flg=0x10 } ordered=true userid=0 options=null
2024-01-01 00:37:11.638 1330-3251/? V/ActivityManager: Enqueueing broadcast: com.example.customview.MY_BROADCAST replacePending=false
2024-01-01 00:37:11.638 1330-3251/? V/ActivityManager: Enqueueing ordered broadcast BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0}
2024-01-01 00:37:11.638 1330-3251/? V/BroadcastQueue: Enqueuing BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} from uid 10209 pid 11528 for 2 receivers:[BroadcastFilter{6bdd5af 10209/u0 ReceiverList{5fb998e 11528 com.example.customview/10209/u0 remote:a4e9589}}, ResolveInfo{118f150 com.example.customview/.MyReceiver m=0x108000 userHandle=UserHandle{0}}]
2024-01-01 00:37:11.639 1330-3251/? V/ActivityManager_MU: isSingleton(com.example.customview, ApplicationInfo{5054f49 com.example.customview}, com.example.customview.MyReceiver, 0x10000) = false
2024-01-01 00:37:11.639 1330-3251/? D/BroadcastQueue: com.example.customview:Intent { act=com.example.customview.MY_BROADCAST flg=0x10 } deferUntilActive=false RunnableAt=2194826 reason:FOREGROUND enqueueTime=2314826 app.isCached=false ProcessFreezable=false
2024-01-01 00:37:11.640 1330-3251/? D/BroadcastQueue: Delivery state of BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} to ResolveInfo{118f150 com.example.customview/.MyReceiver m=0x108000 userHandle=UserHandle{0}} via null changed from PENDING to SKIPPED because skipped by policy at enqueue: Background execution not allowed: receiving Intent { act=com.example.customview.MY_BROADCAST flg=0x10 } to com.example.customview/.MyReceiver
2024-01-01 00:37:11.640 1330-3251/? W/BroadcastQueue: Delivery state of BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} to ResolveInfo{118f150 com.example.customview/.MyReceiver m=0x108000 userHandle=UserHandle{0}} via null changed from PENDING to SKIPPED because skipped by policy at enqueue: Background execution not allowed: receiving Intent { act=com.example.customview.MY_BROADCAST flg=0x10 } to com.example.customview/.MyReceiver
2024-01-01 00:37:11.642 1330-1374/? V/BroadcastQueue: Scheduling BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} to warm ProcessRecord{66ca199 11528:com.example.customview/u0a209} receiver:com.example.customview.MainActivity$2 waited 3ms
2024-01-01 00:37:11.642 1330-1374/? D/BroadcastQueue: Delivery state of BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} to BroadcastFilter{6bdd5af 10209/u0 ReceiverList{5fb998e 11528 com.example.customview/10209/u0 remote:a4e9589}} via ProcessRecord{66ca199 11528:com.example.customview/u0a209} changed from PENDING to SCHEDULED because scheduleReceiverWarmLocked
2024-01-01 00:37:11.665 11528-11528/com.example.customview D/MyReceiver: 动态接收器 收到广播拉:2,执行前时间:1704040631665
2024-01-01 00:37:11.677 11528-11528/com.example.customview D/MyReceiver: 动态接收器 收到广播拉:2,执行完时间:1704040631677
2024-01-01 00:37:11.678 1330-3251/? D/BroadcastQueue: Delivery state of BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} to BroadcastFilter{6bdd5af 10209/u0 ReceiverList{5fb998e 11528 com.example.customview/10209/u0 remote:a4e9589}} via ProcessRecord{66ca199 11528:com.example.customview/u0a209} changed from SCHEDULED to DELIVERED because remote app
2024-01-01 00:37:11.679 1330-3251/? D/BroadcastQueue: Finished with ordered BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} took 39ms manifest receiver:1 manifest skipped: 1 total receiver:2
2024-01-01 00:37:11.679 1330-3251/? D/BroadcastQueue: Receiver BroadcastFilter{6bdd5af 10209/u0 ReceiverList{5fb998e 11528 com.example.customview/10209/u0 remote:a4e9589}} finished with BroadcastRecord{3a34b13 com.example.customview.MY_BROADCAST/u0} took 36ms