最近在开发安卓14的系统,系统是system和vendor分开的,system是U版本,vendor是S版本,发现通过系统应用发送出来的广播发给应用有500ms的延迟,如下图所示
发送时间是16:03:52.148
接收时间是16:03:52.652 中间有500ms延迟,不可以接受
正常来说如果是无序广播不应该有这么大的时间差才对,研究系统源码发现在AMS将广播加入队列时,高版本对这块做了改动,在发送广播时调用broadcastQueueForIntent获取广播队列,broadcastQueueForIntent使用mEnableModernQueue标志位对前台、后台做了区分,通过mEnableModernQueue这个代码的作用可以看到这个标志位启用了一条新的队列实现
if (mEnableModernQueue) {
mBroadcastQueues = new BroadcastQueue[1];
mBroadcastQueues[0] = new BroadcastQueueModernImpl(this, mHandler,
foreConstants, backConstants);
} else {
mBroadcastQueues = new BroadcastQueue[4];
mBroadcastQueues[BROADCAST_QUEUE_FG] = new BroadcastQueueImpl(this, mHandler,
"foreground", foreConstants, false, ProcessList.SCHED_GROUP_DEFAULT);
mBroadcastQueues[BROADCAST_QUEUE_BG] = new BroadcastQueueImpl(this, mHandler,
"background", backConstants, true, ProcessList.SCHED_GROUP_BACKGROUND);
mBroadcastQueues[BROADCAST_QUEUE_BG_OFFLOAD] = new BroadcastQueueImpl(this, mHandler,
"offload_bg", offloadConstants, true, ProcessList.SCHED_GROUP_BACKGROUND);
mBroadcastQueues[BROADCAST_QUEUE_FG_OFFLOAD] = new BroadcastQueueImpl(this, mHandler,
"offload_fg", foreConstants, true, ProcessList.SCHED_GROUP_BACKGROUND);
}
怀疑是这个导致队列的处理优先级造成的问题
解决方法,将AMS里面的mEnableModernQueue这个标志位置成false,
//mEnableModernQueue = foreConstants.MODERN_QUEUE_ENABLED;
mEnableModernQueue = false;
重新编译后发现延迟问题得到解决。
原因分析,新的广播队列实现对广播进行了分类,紧急、负载、普通分别有一个队列,等待调度的广播分别维护了紧急、普通、负载三个有序集合,优先级为紧急(3) > 普通(10) > 负载,但是当优先级高的集合被处理的广播数量超过一定限制时,优先级低的广播也有机会得到执行。
每个队列都有一个在未来特定时间“可运行”(runnable at 时间戳)的概念,它支持在每个进程的基础上任意暂停或延迟交付。当它下一次符合执行条件时,该值会受到各种策略的影响,例如:
->哪些广播正在等待发送给给定进程。 例如,“紧急”(前台、源于用户交互、闹钟)广播通常会导致较早的runnable at(-120s)时间,或者“延迟”广播通常会导致较晚的runnable at时间。
->进程或 UID 的当前状态。 例如,“cached”(procState > PROCESS_STATE_RECEIVER)进程通常会导致较晚的runnable at(+120s)时间,或者“instrumented”进程通常会导致较早的runnable at(-120s)时间。
通过命令可以查看广播状态
adb shell dumpsys activity broadcasts
可以看到bcast_delay_normal_millis=+500ms 这里确实对普通广播进行了延迟500毫秒,可以跟实际现象对应上
...
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
...
关于新版广播队列可以参考这个文章android U广播详解(一)_android 如何dump广播-CSDN博客