Camera HAL工程实战:从移植到量产优化 - 第1节

1.1 Camera HAL 在 Android 系统中的位置

Camera HAL(硬件抽象层)位于 Android 相机系统的中间层,向上承接 Camera Framework,向下直接操作 Camera 硬件设备。它是 Android 系统“分层解耦”设计思想在相机子系统中的具体体现。

核心定位:HAL 是 Android 系统与硬件厂商代码之间的契约边界。Google 定义接口,芯片厂商(如 Qualcomm、MediaTek)和 OEM 厂商实现具体逻辑。

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 代码可以适配不同厂商的硬件平台。

Android 相机软件栈 — Camera HAL 位置 应用层 Camera App / SDK (Java/Kotlin) 框架层 Camera Framework (Java/C++) HAL 层(Camera HAL) 硬件抽象接口 (C/C++) 内核层 Kernel Driver / V4L2 / ISP (C) HAL 层是 Android 相机系统的“分水岭”:隔离 Framework 与硬件实现,支持多平台适配

1.2 HAL 层的作用与设计哲学

1.2.1 HAL 层的三大核心作用

  1. 硬件抽象:将不同厂商、不同型号的 Camera 硬件差异封装在 HAL 内部,向上提供统一的接口。Framework 无需关心底层是 Qualcomm ISP 还是 MediaTek ISP。
  2. 设备控制:负责 Camera 设备的打开/关闭、流(Stream)的配置、Buffer 的分配与传递、3A(自动对焦/自动曝光/自动白平衡)控制等。
  3. 数据传递:将 Sensor 采集的原始图像数据经过 ISP 处理后,通过 HAL 接口传递给 Framework 层,最终呈现给应用或编码器。

1.2.2 HAL 的设计哲学

Android Camera HAL 的设计遵循以下核心原则:

设计原则 说明 工程意义
接口稳定 HAL 接口版本化(如 HAL1、HAL3),向后兼容 Framework 升级无需修改 HAL 代码
性能优先 HAL 层使用 C/C++ 实现,避免 Java 层开销 保证预览、拍照、录像的低延迟
厂商自主 HAL 内部实现完全由厂商决定 芯片厂商可以发挥硬件最大能力
可测试性 HAL 接口可被 CTS/VTS 测试覆盖 保证兼容性和稳定性
实战经验:在移植 Camera HAL 时,最常遇到的问题就是“接口版本不匹配”。Android 从 HAL1 演进到 HAL3,再到 Treble 架构下的 HIDL/AIDL HAL,每次接口变更都要求 HAL 实现做相应调整。建议在项目初期就确认目标 Android 版本对应的 HAL 接口版本。

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。

Camera HAL3 接口交互流程 Camera Framework CameraService CameraDeviceClient CaptureSession CameraMetadata Camera HAL camera3_device_t configure_streams() process_capture_request() camera3_callback_ops_t initialize() configure_streams() process_capture_request() notify() / process_capture_result() Framework 通过函数指针调用 HAL,HAL 通过回调返回结果 所有数据传递均通过 Buffer Handle 和 CameraMetadata 完成,避免数据拷贝 接口关系关键点 • 接口定义在 camera3.h 中,Framework 和 HAL 都引用同一份头文件 • HAL 实现必须提供所有函数指针,Framework 通过 hw_get_module() 加载 HAL • 元数据(Metadata)是 Framework 与 HAL 之间传递配置和结果的标准格式

1.3.3 关键接口调用流程

一次典型的 Camera 预览 + 拍照流程中,Framework 与 HAL 的接口调用顺序如下:

  1. open() — Framework 打开 Camera 设备,获取 camera3_device_t 实例
  2. initialize() — Framework 注册回调函数指针给 HAL
  3. configure_streams() — Framework 配置预览流、拍照流等,HAL 返回支持的 Buffer 格式和尺寸
  4. construct_default_request_settings() — Framework 获取默认的捕获参数(Metadata)
  5. process_capture_request() — Framework 发送捕获请求,HAL 开始处理
  6. process_capture_result() — HAL 通过回调返回捕获结果(图像 Buffer + 结果 Metadata)
  7. flush() — Framework 请求 HAL 清空所有待处理的请求
  8. close() — Framework 关闭 Camera 设备
常见陷阱:在 configure_streams() 阶段,HAL 必须根据 Framework 传入的 stream 配置,返回实际支持的 Buffer 大小和格式。如果 HAL 返回的配置与 Framework 期望的不一致,会导致流配置失败。实际项目中,经常因为分辨率对齐问题(如对齐到 16 或 32 像素)导致配置失败。

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 的基础。