barrier repair barrier( 四 )


逻辑调整前: 先移除将要强制调度的并设置了异步属性的消息,再强制调度该消息,以保证该消息不受 barrier 消息之前的消息 block,进而提高响应能力 。
if(hasMsg){......handler.removeCallbacks(message.getCallback());//先移除handler.dispatchMessage(cloneMsg);//再强制调度该消息......}逻辑调整后: 先强制调度该消息,然后再将该消息从队列中移除 。
......handler.dispatchMessage(newMessage);//先强制调度handler.removeCallbacks(message.getCallback());//从队列中移除消息......}但是时序调整后存在一定隐患,即在强制调用 DoFrame 消息期间,业务可能会再次触发 UI 刷新逻辑,产生 barrier 消息并发出 vsync 请求,如果系统及时响应 vsync,并产生 DoFrame 消息,那么调用 removeCallbacks 接口会一次性清除消息队列中所有的 DoFrame 消息,即:移除了消息队列之前的 DoFrame 消息和下次待调度的 DoFrame 消息,但是与下次 DoFrame 消息同步的 barrier 消息并没有被移除 。
那么为什么会移除多个消息呢?这就要从handler.removeCallbacks 的实现说起了 。

barrier repair barrier

文章插图
进一步查看 messageQueue.removeMessages 接口实现,发现该接口会遍历消息队列中符合当前 runnable 以及 object 的消息,但是上面传递的 Object 对象是 null,因此就相当于移除了当前 Handler 对象下面所有相同 runnable 对象的消息!
barrier repair barrier

文章插图
因为强制刷新和时序调整的问题,导致了消息队列中同时存在 2 个 UI doFrame 消息,并在强制执行之后被同时移除,从而导致一个无人认领的 barrier 消息一直停留在消息队列 !
其它场景:此外,除了上面遇到的场景会导致这类问题之外,还有一种场景也可能会导致这类问题,即:UI 异步刷新,尽管 Android 系统禁止异步刷新,并利用 checkThread 机制对 UI 刷新进行线程检查,但是百密一疏,如果开启硬件加速,在 AndroidO 及之后的版本会间接调用 onDescendantInvalidated 触发 UI 刷新,该逻辑躲过了系统 checkThread 检查,将会造成线程并发隐患 。如下图,如果并发执行则会导致前一个线程的 mTraversalBarrier 被覆盖,从而导致 vsync 消息与 barrier 出现同步问题 。
barrier repair barrier

文章插图
查看 Android Q 源码,看到 onDescendantInvalidated 内部加上了 checkThread,但被注释掉了!解释如下:修复摄像头后重新启用或者通过 targetSdk 检查?好吧,或许是忘记这个 TODO 了 。

barrier repair barrier

文章插图
总结:至此,我们完成了该类问题的分析和最终定位,综合来看该类问题因 Trace 场景(NativePollOnce)和问题本身的高度隐蔽性,给排查和定位带来了极大挑战,如果单纯依靠系统提供的日志,是很难发现 MessageQueue.next()内部发生了异常 。这里我们通过 Raster 监控工具,还原了问题现场,并提供了重要线索 。现在总结来看,该类问题其实具有很明显的特征,表现在以下几个方面:
问题场景 ANR Trace 集中聚合在 NativePollOnce,此过程 Wall duration 持续很长,并且屏蔽了后续所有正常消息调度,看起来像主线被冻结一样 。通过 Raster 监控工具可以清晰的看到,消息队列中如果第一个待消息 target 为 null,即为 barrier 消息,可以通过后续消息 block 时长评估影响程度 。出现该类问题时,因为正常消息无法被调度,如 Service,Receiver 消息,将会导致应用连续发生 ANR,直到用户主动 Kill 该进程 。后续接下来的文章中,我们将会介绍系统服务与客户端 binder 通信过程中,因为时序颠倒引起的 ANR 问题,因为是系统机制出现了 bug,理论上所有应用都会受到影响,问题表现同样很隐蔽,那么这类问题到底是什么样的表现呢?敬请期待 。
优化实践更多参考: ANR 优化实践系列 - 设计原理及影响因素
ANR 优化实践系列 - 监控工具与分析思路
ANR 优化实践系列分享 - 实例剖析集锦
Android 平台架构团队我们是字节跳动 Android 平台架构团队,以服务为主,面向 GIP,同时服务公司其他产品,在产品性能稳定性等用户体验,研发流程,架构方向上持续优化和探索,满足产品快速迭代的同时,追求极致的用户体验 。
如果你对技术充满热情,想要迎接更大的挑战和舞台,欢迎加入我们,北京,深圳均有岗位,感兴趣发送邮箱:tech@bytedance.com,邮件标题:姓名 - GIP - Android 平台架构 。
【barrier repair barrier】