概览

GraphicBuffer 在 BufferQueue - 生产者与消费者 之间流转,如下图所示。

BufferQueue communication process

BufferQueue communication process

在 Android 11 及之前的版本中,应用是生产者,SurfaceFlinger 是消费者,它们是通过 IGraphicBufferProducerIGraphicBufferConsumer 接口通信。当 SurfaceFlinger 使用完 buffer 时调用 BufferQueueConsumer::releaseBuffer() 释放 buffer 并通知生产者。

但 Android 12 引入 BLASTBufferQueue 之后,生产者和消费者都在应用进程,应用产生的 buffer 通过 SurfaceFlinger::setTransactionState() 发送给 SurfaceFlinger。所以相应的 buffer 释放流程也有变化。

该文介绍在 BLASTBufferQueue 机制下 SurfaceFlinger 是如何通知应用进程里生产者 buffer 释放的过程。

时序图

sequenceDiagram
box App
participant bqc as BufferQueueConsumer
participant bbq as BLASTBufferQueue
participant tx as Transaction
participant tcl as TransactionCompletedListener
end
box SurfaceFlinger
participant sf as SurfaceFlinger
participant bsl as BufferStateLayer
end

activate bbq
bbq->>+bqc: acquireBuffer()
bqc-->>-bbq: BufferItem
Note over bbq: Save to mSubmitted
bbq->>+tx: setBuffer()
tx->>-tcl: setReleaseBufferCallback()
tx->>sf: setTransactionState()
deactivate bbq

Note right of sf: VSYNC
sf->>bsl: setBuffer()

sequenceDiagram
participant sf as SurfaceFlinger
participant ce as CompositionEngine
participant bsl as BufferStateLayer
participant tci as TransactionCallbackInvoker
participant tcl as ITransactionCompletedListener

Note left of sf: handlePageFlip()
activate sf
sf->>+bsl: latchBuffer()
bsl->>-bsl: updateActiveBuffer()
Note over bsl: New ReleaseCallbackId
deactivate sf

Note left of sf: onMessageRefresh()
activate sf
sf->>ce: present()
activate ce
ce->>bsl: onLayerDisplayed()
activate bsl
bsl->>bsl: addReleaseFence()
Note over bsl: Set ReleaseCallbackId
deactivate bsl
deactivate ce
Note over sf: postComposition()
sf->>+tci: sendCallbacks()
tci->>-tcl: onTransactionCompleted()
deactivate sf
sequenceDiagram
participant tcl as TransactionCompletedListener
participant bbq as BLASTBufferQueue
participant bqc as BufferQueueConsumer

Note left of tcl: onTransactionCompleted
tcl->>bbq: releaseBufferCallback()
Note over bbq: Get from mSubmitted
bbq -> bqc: releaseBuffer()

详细流程

根据 3 个序列图,下面分 3 个流程介绍 buffer 释放的前后流程,从中我们会回答一些关键部分:

Buffer 传递

首先介绍 buffer 从应用进程传递到 SurfaceFlinger 的流程。其中我们先从 BLASTBufferQueue 如何获取 buffer 开始介绍。

获取 buffer

当生产者绘制一个 buffer 后调用 BufferQueueProducer::queueBuffer() 把 buffer 插入到队列中,同时会调用 onFrameAvailable()。BLASTBufferQueue 实现了 ConsumerBase::FrameAvailableListener,在 onFrameAvailable() 实现中会调用 BLASTBufferQueue::acquireNextBufferLocked() 获取 buffer。