Camera HAL工程实战:从移植到量产优化 - 第1节
1.1 Camera HAL 在 Android 系统中的位置
Camera HAL(硬件抽象层)位于 Android 相机系统的中间层,向上承接 Camera Framework,向下直接操作 Camera 硬件设备。它是 Android 系统“分层解耦”设计思想在相机子系统中的具体体现。
Android 相机软件栈从上到下分为四个主要层级:
| 层级 | 组件 | 职责 | 语言 |
|---|---|---|---|
| 应用层 | Camera App / SDK | 提供拍照、录像、预览等用户交互 | Java / Kotlin |
| 框架层 | Camera Framework | 管理 Camera 服务、权限、流、会话 | Java / C++ |
| HAL 层 | Camera HAL | 硬件抽象、设备控制、数据传递 | C / C++ |
| 内核层 | Kernel Driver / V4L2 | 传感器驱动、ISP 控制、DMA 传输 | C |
HAL 层是 Android 相机系统的“分水岭”:Framework 侧不关心具体硬件实现,HAL 侧不关心上层应用逻辑。这种隔离使得同一套 Framework 代码可以适配不同厂商的硬件平台。
1.2 HAL 层的作用与设计哲学
1.2.1 HAL 层的三大核心作用
- 硬件抽象:将不同厂商、不同型号的 Camera 硬件差异封装在 HAL 内部,向上提供统一的接口。Framework 无需关心底层是 Qualcomm ISP 还是 MediaTek ISP。
- 设备控制:负责 Camera 设备的打开/关闭、流(Stream)的配置、Buffer 的分配与传递、3A(自动对焦/自动曝光/自动白平衡)控制等。
- 数据传递:将 Sensor 采集的原始图像数据经过 ISP 处理后,通过 HAL 接口传递给 Framework 层,最终呈现给应用或编码器。
1.2.2 HAL 的设计哲学
Android Camera HAL 的设计遵循以下核心原则:
| 设计原则 | 说明 | 工程意义 |
|---|---|---|
| 接口稳定 | HAL 接口版本化(如 HAL1、HAL3),向后兼容 | Framework 升级无需修改 HAL 代码 |
| 性能优先 | HAL 层使用 C/C++ 实现,避免 Java 层开销 | 保证预览、拍照、录像的低延迟 |
| 厂商自主 | HAL 内部实现完全由厂商决定 | 芯片厂商可以发挥硬件最大能力 |
| 可测试性 | HAL 接口可被 CTS/VTS 测试覆盖 | 保证兼容性和稳定性 |
1.3 Camera HAL 与 Camera Framework 的接口关系
1.3.1 接口演进历史
Android Camera HAL 接口经历了三个主要阶段:
| 阶段 | Android 版本 | 接口类型 | 特点 |
|---|---|---|---|
| HAL1 | Android 4.0 ~ 5.0 | Legacy HAL | 简单、功能有限、不支持多流 |
| HAL3 | Android 5.0 ~ 9.0 | camera3_device_t | 支持多流、高速连拍、ZSL、手动控制 |
| Treble HAL | Android 8.0+ | HIDL / AIDL | HAL 与 Framework 分离,支持独立升级 |
1.3.2 HAL3 核心接口结构
以目前最广泛使用的 HAL3 为例,Camera HAL 与 Framework 之间的接口通过以下关键结构体定义:
// HAL3 核心接口定义(位于 hardware/libhardware/include/hardware/camera3.h)
typedef struct camera3_device {
hw_device_t common;
// 设备操作函数指针
int (*initialize)(const struct camera3_device *, const camera3_callback_ops_t *);
int (*configure_streams)(const struct camera3_device *, camera3_stream_configuration_t *);
int (*register_stream_buffers)(const struct camera3_device *, const camera3_stream_buffer_set_t *);
const camera_metadata_t *(*construct_default_request_settings)(const struct camera3_device *, int type);
int (*process_capture_request)(const struct camera3_device *, camera3_capture_request_t *);
void (*dump)(const struct camera3_device *, int fd);
int (*flush)(const struct camera3_device *);
void (*signal_stream_flush)(const struct camera3_device *, uint32_t num_streams, const int32_t *streams);
int (*is_reconfiguration_required)(const struct camera3_device *, const camera3_stream_configuration_t *);
} camera3_device_t;
Framework 通过调用这些函数指针与 HAL 交互,HAL 则通过 camera3_callback_ops_t 回调将结果(如捕获完成的图像 Buffer、元数据)返回给 Framework。
1.3.3 关键接口调用流程
一次典型的 Camera 预览 + 拍照流程中,Framework 与 HAL 的接口调用顺序如下:
- open() — Framework 打开 Camera 设备,获取
camera3_device_t实例 - initialize() — Framework 注册回调函数指针给 HAL
- configure_streams() — Framework 配置预览流、拍照流等,HAL 返回支持的 Buffer 格式和尺寸
- construct_default_request_settings() — Framework 获取默认的捕获参数(Metadata)
- process_capture_request() — Framework 发送捕获请求,HAL 开始处理
- process_capture_result() — HAL 通过回调返回捕获结果(图像 Buffer + 结果 Metadata)
- flush() — Framework 请求 HAL 清空所有待处理的请求
- close() — Framework 关闭 Camera 设备
1.3.4 Treble 架构下的接口变化
从 Android 8.0 开始,Treble 架构将 HAL 接口从 libhardware 迁移到 HIDL(HAL Interface Definition Language)或 AIDL(Android Interface Definition Language)。这意味着:
- HAL 不再直接编译进 Framework 进程,而是运行在独立的 HAL 进程(
cameraserver或 vendor 进程)中 - 接口调用通过 Binder 或 HwBinder 进行跨进程通信(IPC)
- HAL 实现可以独立于 Framework 升级,无需重新编译整个系统
对于 HAL 开发者而言,虽然接口定义方式变了,但核心的相机控制逻辑(流配置、捕获请求、回调)没有本质变化。理解 HAL3 的 camera3_device_t 接口仍然是掌握 Camera HAL 的基础。