android 图像显示框架二——流程分析

一.Android图形组件协作工作

首先先上流程图:

如下是Android12及以后得Android图形组件协作的流程图

上述的图片清晰的展示了Android图形系统最核心的基石------基于BufferQueue的生产者-消费者模式。整个流程是是描述一个图形缓存区(GraphicBuffer)从被绘制到最终被显示出来的完整生命周期。

全景概述:三大角色

整个架构围绕着三大角色展开,对应图中的三个主要部分:

1.图像生产者(Image Producer) :负责**生产(绘制)**图像内容,例如:应用程序、视频解码器。

2.图像消费者(Image Consumer) :负责**使用(消耗)**已生成的图像内容。例如:将图像合成后送到显示屏的SurfaceFlinger。

3.BufferQueue:作为核心中介 ,连接生产者和消费者,它管理着一组图形缓冲区(GraphicBuffer),是数据交换的通道。

模块详解:

1.图像生产者(右侧)

  • **是什么:**所有需要将画面绘制到屏幕上的实体。
  • 常见生产者:
  1. OpenGL ES/Vulkan:3D图形渲染库。
  2. Skia :2D图形绘制库,常用于应用界面绘制。
  3. Decoder:视频解码器,解码视频帧。

2.图像消费者(左侧)

  • **是什么:**获取并使用生产者提交的图像数据实体。
  • 核心消费者:
  1. SurfaceFlinger:Android系统的合成器。它接受多个应用(生产者)的缓冲区,将它们最终合成一帧,然后交个HWComposer显示到屏幕上。
  2. OpenGL ES:在某些情况下(如应用内纹理渲染),它也可以作为消费者。

3.核心枢纽:BufferQueue(中间)

这是整个流程的心脏,它内部包含了三个核心组件,共同管理着缓冲区的一生。

  • BufferQueueCore:
  1. 核心大脑:管理整个队列的状态。
  2. 资源池:持有固定数量的Buffer Slots(缓冲区槽位)和GraphicBuffer对象。GraphicBuffer是真正存储像素数据的内存块。
  3. 状态跟踪:跟踪每个缓冲区的状态(空闲、已排队、已获取)
  • BufferQueueProducer:
  1. 面向生产者的接口:生产者只与它交互
  2. 关键操作:

dequeueBuffer():向生产者分配一个空闲的缓冲区。

queueBuffer():接受生产者已经绘制完成的缓冲区,并将他置于已排队的状态,通知消费者。

  • BufferQueueConsumer:
  1. 面向消费者的接口:消费者只与它打交道
  2. 关键操作:

acquireBuffer():从队列中获取一个已排队的缓冲区,交个消费者使用

releaseBuffer():消费者使用完毕后,将其释放回空闲状态,可供生产者再次使用

缓冲区生命周期与数据流(重点)

让我们跟随一个GraphicBuffer的旅程,对应流程图中的箭头和文字:

1.dequeue(出队):

  • 生产者(如App)通过Surface------>dequeueBuffer()调用BufferQueueProducer。
  • Producer从BufferQueue的缓冲区槽位(Buffer Slots)中找到一个状态为FREE(空闲)的GraphicBuffer,将其状态改为DEQUEUED,并返回给生产者。

2.生产/渲染:

  • 生产者获取到GraphicBuffer后,使用OpenGL ES或者Skia等库在其上进行绘制,填充图像数据。

3.queue(入队):

  • 绘制完成后,生产者调用Surface------>queueBuffer()。
  • Producer将该GraphicBuffer的状态改成QUEUED(已排队),并将其放入队列中。同时,通过回调通知消费者:"有新的数据可以用了!"

4.acquire(获取):

  • 消费者(如SurfaceFlinger)被唤醒,调用acquireBuffer()。
  • BufferQueueConsumer从队列中取出一个QUEUED状态的缓冲区,将其状态改成ACQUIRED(已获取),然后交给消费者

5.消费(合成/显示):

  • 消费者对获取的缓冲区内容进行处理,对于SurfaceFlinger来说,就是将多个应用的缓冲区合成最终的画面

6.release(释放):

  • 消费者使用完毕后,调用releaseBuffer()。
  • Consumer将该GraphicBuffer的状态重置为FREE(空闲),并将其放会空闲池。
  • 此时,这个缓冲区又可以再次被生产者dequeue,开始新一轮的循环。

关键技术与进阶概念

1.同步机制-Fence(栅栏)

图中箭头旁的acquire和release信号,在实际实现中通常与Fence机制紧密相关。

  • 为什么需要:GPU渲染是异步的。当生产者queueBuffer是,GPU的渲染指令可能还没有真正执行完。直接让消费者读取可能读取不到完整的帧。
  • 如何工作:生产者提交缓冲区时,会附带一个Fence。消费者在acquire缓冲区后,会等待这个Fence发出"信号"(表示GPU渲染完成),才去读取缓冲区内容。这保证了数据同步,避免屏幕撕裂

2.BLASTBufferQueue(Buffer Latency and Synchronization Task)

  • 是什么:Android10/11中引入的现代化BufferQueue。
  • 解决什么问题:传统的Surface和BufferQueue是一对一绑定的。一个窗口(如Activity)通常只有一个Surface,这限制了性能(例如:难以实现无缝转场动画)
  • 优势:BLASTBufferQueue允许一个窗口管理多个缓冲区会话,提供了更加精细、更加灵活的缓冲区控制,显著改善了应用切换、分屏和动画的流畅度。可以看做是BufferQueue的增强版。

总结:

这张图精妙的描绘出Android图形系统解耦和异步处理的核心思想:

  • 解耦:生产者(App)和消费者(SurfaceFlinger)不需要知道对方的存在,也不需要同步工作。它们只与BufferQueue交互,从而可以独立、高效运行。
  • 流水线:通过缓冲区队列,实现了"绘制一帧"和"显示一帧"的并行操作。当消费者正在显示第N帧时,生产者可能已经在绘制第"N+1"帧了。这是Android系统保持界面流畅的关键。
相关推荐
nee~1 小时前
Android设备USB连接转无线操作(windows)
android·windows
sun0077002 小时前
android上ethernet和wifi共存
android
青莲8433 小时前
Android Jetpack - 3 LiveData
android·前端
小蜜蜂嗡嗡3 小时前
flutter namespace问题
android·flutter
Cat God 0073 小时前
MySQL-查漏补缺版(六:MySQL-优化)
android·数据库·mysql
QING6184 小时前
Jetpack Compose Brush API 简单使用实战 —— 新手指南
android·kotlin·android jetpack
Swizard4 小时前
别让 AI 假装在工作:Android "Vibe Coding" 的生存指南
android·java·vibe coding
电饭叔5 小时前
《python语言程序设计》2018版--第8章14题利用字符串输入作为一个信用卡号之一(Luhn算法解释)
android·java·python
QING6185 小时前
Jetpack Compose Brush API 详解 —— 新手指南
android·kotlin·android jetpack
Huanzhi_Lin5 小时前
安卓连接夜神模拟器命令及原理
android