
Android 框架为 2D 和 3D 图形提供了各种渲染 API,这些 API 与制造商对图形驱动程序的实现进行交互,因此务必充分了解这些 API 在较高层级上的工作原理。本页介绍了构建这些驱动程序所依据的图形硬件抽象层 (HAL)。在继续阅读本部分之前,请先熟悉以下术语
Canvas
(API 元素)Surface
对象实际位的合成。Canvas
具有用于位图、线条、圆形、矩形、文本等标准计算机绘图的方法,并且绑定到位图或 surface。canvas 是在屏幕上绘制 2D 对象的最简单、最便捷的方式。基类是 Canvas
。android.graphics.drawable
的子类中。如需详细了解 drawable 和其他资源,请参阅资源。android.opengl
和 javax.microedition.khronos.opengles
软件包公开了 OpenGL ES 功能。Surface
(API 元素)Surface
对象的大小。请使用 SurfaceView
类,而不是直接使用 Surface
类。SurfaceView
(API 元素)View
对象,它封装了用于绘图的 Surface
对象,并公开了动态指定其大小和格式的方法。surface view 提供了一种独立于 UI 线程进行绘制的方式,适用于资源密集型操作(例如游戏或相机预览),但会导致占用更多内存。surface view 同时支持 canvas 和 OpenGL ES 图形。SurfaceView
对象的基础类是 SurfaceView
。R.style
中列出,并以 Theme_
作为前缀。View
(API 元素)View
类是 Activity 或对话框屏幕的大多数布局组件(例如文本框和窗口)的基类。View
对象接收来自其父对象(请参阅 ViewGroup
)的调用以绘制自身,并将其首选大小和位置告知其父对象,父对象可能不会遵循此大小和位置。如需了解详情,请参阅 View
。ViewGroup
(API 元素)widget
软件包中,但扩展了 ViewGroup
类。android.widget
软件包中。Window
(API 元素)Window
抽象类派生的对象,用于指定通用窗口的元素,例如外观、标题栏文本以及菜单的位置和内容。对话框和 Activity 使用 Window
类的实现来渲染 Window
对象。您无需在应用中实现 Window
类或使用窗口。应用开发者通过三种方式在屏幕上绘制图片:使用 Canvas、OpenGL ES 或 Vulkan。
Android 图形组件
无论开发者使用什么渲染 API,所有内容都会渲染到 surface 上。surface 表示缓冲区队列的生产者端,缓冲区队列通常由 SurfaceFlinger 消耗。在 Android 平台上创建的每个窗口都由 surface 提供支持。所有渲染的可见 surface 都由 SurfaceFlinger 合成到显示屏上。
下图展示了关键组件如何协同工作

图 1. surface 的渲染方式。
主要组件描述如下
图像流生产者
图像流生产者可以是任何生成图形缓冲区以供使用的对象。示例包括 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
图像流消费者
图像流最常见的消费者是 SurfaceFlinger,这是一种系统服务,用于消耗当前可见的 surface,并使用窗口管理器提供的信息将其合成到显示屏上。SurfaceFlinger 是唯一可以修改显示屏内容的服务。SurfaceFlinger 使用 OpenGL 和硬件合成器来合成一组 surface。
其他 OpenGL ES 应用也可以消耗图像流,例如相机应用消耗相机预览图像流。非 GL 应用也可以是消费者,例如 ImageReader 类。
硬件合成器
显示子系统的硬件抽象层。SurfaceFlinger 可以将某些合成工作委托给硬件合成器,以从 OpenGL 和 GPU 卸载工作。SurfaceFlinger 充当另一个 OpenGL ES 客户端。因此,当 SurfaceFlinger 主动将一个或两个缓冲区合成为第三个缓冲区时,例如,它会使用 OpenGL ES。这使得合成比让 GPU 执行所有计算的功耗更低。
硬件合成器 HAL 执行另一半工作,并且是所有 Android 图形渲染的中心点。硬件合成器必须支持事件,其中一个事件是 VSYNC(另一个事件是用于即插即用 HDMI 支持的热插拔)。
Gralloc
图形内存分配器 (Gralloc) 是分配图像生产者请求的内存所必需的。如需了解详情,请参阅Gralloc HAL。
数据流
下图展示了 Android 图形管道的数据流

图 2. 通过 Android 的图形数据流
左侧的对象是渲染器,用于生成图形缓冲区,例如主屏幕、状态栏和系统 UI。SurfaceFlinger 是合成器,硬件合成器是合成器。
BufferQueue
BufferQueue 在 Android 图形组件之间提供粘合。这些是一对队列,用于协调从生产者到消费者的缓冲区恒定循环。生产者交出缓冲区后,SurfaceFlinger 负责将所有内容合成到显示屏上。
下图展示了 BufferQueue 通信过程。

图 3. BufferQueue 通信过程
BufferQueue 包含将图像流生产者和图像流消费者联系在一起的逻辑。图像生产者的一些示例包括相机 HAL 或 OpenGL ES 游戏生成的相机预览。图像消费者的一些示例包括 SurfaceFlinger 或另一个显示 OpenGL ES 流的应用,例如显示相机取景器的相机应用。
BufferQueue 是一种数据结构,它将缓冲区池与队列相结合,并使用 Binder IPC 在进程之间传递缓冲区。生产者接口,或者您传递给想要生成图形缓冲区的人员的接口,是 IGraphicBufferProducer(SurfaceTexture 的一部分)。BufferQueue 通常用于渲染到 Surface 并通过 GL Consumer 使用,以及执行其他任务。
BufferQueue 可以在三种不同的模式下运行
类同步模式 - BufferQueue 默认以类同步模式运行,在这种模式下,来自生产者的每个缓冲区都会在消费者端输出。在这种模式下,永远不会丢弃任何缓冲区。如果生产者速度过快,并且创建缓冲区的速度快于缓冲区被消耗的速度,则它将阻止并等待空闲缓冲区。
非阻塞模式 - BufferQueue 也可以在非阻塞模式下运行,在这种模式下,它会生成错误,而不是在这些情况下等待缓冲区。在这种模式下,也永远不会丢弃任何缓冲区。这对于避免应用程序软件中可能不了解图形框架复杂依赖关系的潜在死锁非常有用。
丢弃模式 - 最后,BufferQueue 可以配置为丢弃旧缓冲区,而不是生成错误或等待。例如,如果对纹理视图执行 GL 渲染并尽可能快地绘制,则必须丢弃缓冲区。
为了执行大部分工作,SurfaceFlinger 充当另一个 OpenGL ES 客户端。因此,当 SurfaceFlinger 主动将一个或两个缓冲区合成为第三个缓冲区时,例如,它会使用 OpenGL ES。
硬件合成器 HAL 执行另一半工作。此 HAL 充当所有 Android 图形渲染的中心点。