1. Camera HAL 架构概述
Camera HAL(硬件抽象层)是 Android 相机子系统中连接 Framework 与底层硬件驱动的关键中间层。它定义了统一的接口规范,使上层应用无需关心具体硬件实现,同时为芯片厂商(OEM/SOC Vendor)提供标准化的硬件适配入口。本章从整体架构、HAL 版本演进及接口技术三个维度展开,为后续 Stream 复用与数据传输优化奠定基础。
1.1 Android Camera HAL 整体架构
Android Camera 软件栈自上而下分为应用层、Framework 层、HAL 层和内核驱动层。HAL 层位于 Framework 与内核之间,负责将上层请求转换为硬件操作,并返回图像数据。整体架构如下图所示:
HAL 层在整个相机系统中承担以下核心职责:
- 请求分发:将 Framework 下发的 CaptureRequest 转换为硬件可执行的参数序列。
- Buffer 管理:通过 Gralloc / DMA-BUF 机制管理图像缓冲区,实现零拷贝或低拷贝传输。
- Stream 配置:管理多个图像流(Preview、Video、Snapshot)的复用与切换。
- 3A 控制:集成自动对焦(AF)、自动曝光(AE)、自动白平衡(AWB)算法。
- 元数据传递:将硬件生成的统计信息(如帧数、时间戳、人脸检测结果)上报给 Framework。
1.2 HAL3 与 HAL1 的区别
Android Camera HAL 经历了从 HAL1 到 HAL3 的重大演进。HAL1 是早期 Android 版本(Android 4.x 及之前)使用的接口,设计简单但灵活性差;HAL3 从 Android 5.0 开始引入,支持多流并发、逐帧控制和高级特性。下表从多个维度对比两者的核心差异:
| 对比维度 | HAL1 | HAL3 |
|---|---|---|
| 引入版本 | Android 2.x ~ 4.x | Android 5.0+ |
| 架构模式 | 单线程、阻塞式操作 | 异步流水线、多请求并发 |
| Stream 支持 | 仅支持单流(Preview 或 Video 或 Snapshot) | 支持多流并发(Preview + Video + Snapshot 同时) |
| 逐帧控制 | 不支持,参数全局设置 | 支持逐帧 CaptureRequest 精细控制 |
| Buffer 管理 | Framework 管理 Buffer,HAL 被动接收 | HAL 主动申请 Buffer,支持灵活复用 |
| 元数据 | 固定格式,扩展困难 | 基于 CameraMetadata 键值对,可扩展 |
| 适用场景 | 低端设备、功能简单的相机 | 高端设备、多摄、HDR、夜景等复杂场景 |
关键结论:HAL3 是当前 Android 相机开发的主流标准。HAL1 已在新版本中被标记为 deprecated,但部分低端平台或 legacy 设备仍在使用。本课程所有 Stream 复用与数据传输优化方案均基于 HAL3 架构。
HAL3 相比 HAL1 的核心改进在于引入了 Camera3Stream 和 Camera3Request 数据结构,支持以下关键能力:
- 多流复用:同一 Sensor 可以同时输出 Preview 流(低分辨率)、Video 流(编码格式)和 Snapshot 流(高分辨率),无需切换模式。
- 逐帧参数:每一帧都可以独立设置曝光时间、ISO、对焦位置、白平衡等参数,实现类似专业相机的控制粒度。
- Buffer 复用:HAL 可以通过 process_capture_request 回调直接操作 Buffer 句柄,支持 GPU/ISP 直接处理,减少内存拷贝。
1.3 HIDL 与 AIDL 接口演进
Android 接口定义语言(IDL)是 Framework 与 HAL 之间通信的契约。从 Android 8.0 开始,Google 引入 HIDL(HAL Interface Definition Language)替代传统的 legacy HAL 头文件方式;Android 14 及之后,AIDL(Android Interface Definition Language)逐渐成为主流。两者的演进关系如下图所示:
HIDL 与 AIDL 在 Camera HAL 开发中的具体差异如下表所示:
| 对比维度 | HIDL | AIDL |
|---|---|---|
| 定义文件 | .hal 文件(如 ICameraDevice.hal) |
.aidl 文件(如 ICameraDevice.aidl) |
| 包名规范 | android.hardware.camera.device@3.4 |
android.hardware.camera.device.ICameraDevice |
| 版本管理 | 通过 @version 注解,支持 minor/major 版本 | 通过接口继承和包名区分版本 |
| 传输模式 | Binderized(默认)或 Passthrough | 仅 Binderized |
| 代码生成 | hidl-gen 生成 C++/Java 桩代码 | aidl 工具生成 C++/Java/Rust 桩代码 |
| 性能开销 | 略高(额外序列化层) | 较低(直接复用 Binder 机制) |
| Google 推荐 | 已停止新特性开发 | 新项目首选 |
开发建议:对于新启动的 Camera HAL 项目,建议直接使用 AIDL 接口。如果维护现有 HIDL 项目,可以逐步迁移到 AIDL,Google 提供了 hidl2aidl 工具辅助转换。在 Stream 复用场景中,AIDL 的 Binder 直传模式能减少一次序列化开销,对高帧率场景(如 60fps Video)有明显性能收益。
在 Camera HAL 开发中,接口定义直接影响 Stream 复用和数据传输的实现方式。以 AIDL 为例,CameraProvider 接口定义如下:
// ICameraProvider.aidl (Android 14+)
package android.hardware.camera.provider;
interface ICameraProvider {
/**
* 获取当前设备支持的 Camera 设备列表
*/
String[] getCameraIdList();
/**
* 根据 cameraId 创建 CameraDevice 接口
*/
ICameraDevice getCameraDevice(String cameraId);
/**
* 通知 Framework 设备状态变化
*/
void notifyDeviceStateChange(long deviceState);
}
相比 HIDL 版本,AIDL 接口更加简洁,去掉了 @entry 和 @callflow 等注解,直接使用标准的 AIDL 语法。在数据传输层面,AIDL 支持 in、out、inout 参数方向,可以更精细地控制跨进程 Buffer 的传递方式,这对 Stream 复用场景中的 Buffer 共享至关重要。