MergeWithNextTransaction 机制解析

核心含义

mMergeWithNextTransaction 是一个事务同步标志,表示当前的 SurfaceControl.Transaction 不要立即提交给
SF,而是合并到 ViewRootImpl 的下一帧渲染事务中,确保 Surface 操作和 View 绘制在同一帧完成。

问题场景:为什么需要同步?

以 AOD 消失 → 亮屏为例:

不同步时(两帧完成): 帧 N: AOD View 消失(View 绘制) → 用户看到:锁屏裸露,没有遮挡 帧 N+1: 压黑 Layer 显示(SF Transaction)→ 用户看到:黑屏盖上 ↑ 闪了一帧锁屏!

同步时(一帧完成): 帧 N: AOD View 消失 + 压黑 Layer 显示 → 用户看到:直接从 AOD 变黑屏 (合并在同一个 SF Transaction 中) 无闪烁

代码流程

@Volatile
  private var mMergeWithNextTransaction: Boolean = false
 
  private fun mergeWithNextTransaction(show: Boolean) {
      keyguardPanelViewInjector.viewRootImpl.let {
          // ① 注册渲染树的帧回调——在 View 绘制完成时触发
          it?.registerRtFrameCallback { frame: Long ->
              mMergeWithNextTransaction = true   // ② 标记:后续操作不要单独 apply
		  if (show) {
              coverBlackScreenFade()         // ③ 准备压黑的 Transaction(不 apply)
              it.mergeWithNextTransaction(    // ④ 合并到 ViewRootImpl 的帧事务
                  mScreenFadeTransaction, frame
              )
          } else {
              hideSurface(true)              // ③ 准备隐藏的 Transaction(不 apply)
              it.mergeWithNextTransaction(
                  mScreenFadeTransaction, frame
              )
          }
 
          mMergeWithNextTransaction = false  // ⑤ 重置标记
      }
  }
}  
  

它如何控制 apply 行为

在 showScreenFadeSurface 和 hideSurface 中,这个 flag 决定事务的提交方式:

  // showScreenFadeSurface (L427-429)
  if (!mMergeWithNextTransaction) {
      mScreenFadeTransaction.applyAsyncUnsafe()  // 普通路径:立即提交
  }
  // else: 不提交,留给 mergeWithNextTransaction 合并提交
 
  // hideSurface (L475-481)
  if (!mMergeWithNextTransaction) {
      if (needApply) {
          transaction?.applyAsyncUnsafe()        // 普通路径:立即提交
      }
  } else {
      Log.d(TAG, "ScreenFade hide ScreenFade layer next transaction")
      // 不提交,等 ViewRootImpl 合并
  }

两种路径对比

ViewRootImpl.mergeWithNextTransaction 是什么

这是 Android Framework 提供的 API:

 // ViewRootImpl.java
  public void mergeWithNextTransaction(Transaction t, long frameNr) {
      // 将外部 Transaction 合并到当前帧号对应的渲染事务中
      // 在 RenderThread 提交帧缓冲时,一并提交给 SurfaceFlinger
  }

它保证了 View 树的绘制结果(如 AOD 消失)和外部 SurfaceControl 操作(如压黑 Layer 显示)在 SF 侧作为一个原子事务执行,不会出现中间状态。

一句话总结

mMergeWithNextTransaction = “别急着提交,等 View 画完一起交给 SF”,本质是用帧级事务合并来消除多个 Surface 操作之间的时序间隙,避免用户看到闪烁。