Android Camera HAL从零到项目落地 - 第3节

3.1 HIDL 与 AIDL:Camera HAL 接口定义语言的选择

在 Android 系统中,Camera HAL 与 Framework 之间的通信依赖接口定义语言(IDL)。从 Android 8.0 到 Android 14+,Google 先后推广了 HIDL(HAL Interface Definition Language)和 AIDL(Android Interface Definition Language)两种方案。理解两者的差异,是设计稳定、可维护的 Camera HAL 的第一步。

3.1.1 核心差异对比

对比维度 HIDL(Android 8~10 主流) AIDL(Android 11+ 推荐)
设计目标 为 HAL 层独立设计,与 Framework 解耦 统一 Framework 与 HAL 的 IPC 语言
稳定性 使用 @1.0、@2.0 版本化接口 使用 @VendorNdk 注解,版本化更简洁
后端 仅支持 C++(hidl-gen) 支持 Java / C++ / NDK 后端
包名风格 android.hardware.camera.provider@2.4 android.hardware.camera.provider
服务注册 hwservicemanager servicemanager(与 Framework 统一)
迁移成本 需维护两套 .hal 文件 复用 .aidl 语法,学习成本低
关键结论: 新项目(Android 12+)应优先选择 AIDL 方式。HIDL 在 Android 14 中已被标记为 deprecated,Google 要求所有新 HAL 实现使用 AIDL。

3.1.2 接口定义示例对比

HIDL 定义(ICameraProvider.hal):

package android.hardware.camera.provider@2.4;

interface ICameraProvider {
    getCameraIdList() generates (Status status, vec<string> cameraIds);
    getCameraDeviceInterface(
        string cameraId
    ) generates (Status status, ICameraDevice device);
};

AIDL 定义(ICameraProvider.aidl):

package android.hardware.camera.provider;

interface ICameraProvider {
    String[] getCameraIdList();
    ICameraDevice getCameraDeviceInterface(in String cameraId);
}
迁移提示: AIDL 支持 in / out / inout 方向标记,而 HIDL 使用 generates 关键字。AIDL 的异常处理通过 SecurityException 或 IllegalArgumentException 传递,HIDL 则依赖 Status 枚举。

3.1.3 架构演进 SVG 图

Camera HAL 接口定义语言演进 HIDL 时代(Android 8~10) • 独立 .hal 文件 • hwservicemanager 注册 • 仅 C++ 后端 • 版本化:@2.4, @2.5 迁移 AIDL 时代(Android 11+) • 统一 .aidl 语法 • servicemanager 统一注册 • Java / C++ / NDK 后端 • @VendorNdk 注解 HIDL 底层 • 基于 hidl-gen 生成桩代码 • 使用 libhwbinder 通信 • 独立线程模型 AIDL 底层 • 基于 aidl 生成桩代码 • 使用 libbinder 通信 • 与 Framework 共享线程池

3.2 ICameraProvider 接口详解

ICameraProvider 是 Camera HAL 的入口接口,负责枚举相机设备、管理设备生命周期。它是 Framework 与 HAL 建立连接的第一个接触点。

3.2.1 核心方法

方法 功能描述 返回值
getCameraIdList() 返回所有可用相机 ID 列表 String[](AIDL)/vec<string>(HIDL)
getCameraDeviceInterface(cameraId) 根据 ID 获取对应的 ICameraDevice 接口 ICameraDevice
setCallback(providerCallback) 注册回调,用于通知 Framework 设备热插拔事件 void

3.2.2 典型实现流程

  1. 服务注册: HAL 实现启动时,通过 servicemanager 注册 ICameraProvider 实例。
  2. 设备枚举: getCameraIdList() 遍历底层传感器驱动(如 V4L2、MIPI CSI),返回物理 ID。
  3. 接口分发: getCameraDeviceInterface() 根据 ID 创建或返回已有的 ICameraDevice 实例。
  4. 热插拔通知: 通过 ICameraProviderCallback 上报设备插入/移除事件。
常见陷阱: 某些 SoC 平台(如 MTK、Qualcomm)会在 getCameraIdList() 中返回逻辑 ID(如 "0"、"1"),但底层实际对应多个物理传感器。务必在 HAL 层做好 ID 映射表,避免 Framework 层出现 ID 不匹配。

3.2.3 ICameraProvider 架构 SVG 图

ICameraProvider 接口架构 Camera Framework CameraService IPC ICameraProvider HAL 入口接口 设备管理 getCameraIdList() 返回 ["0", "1", "2"] getCameraDevice() 返回 ICameraDevice setCallback() 热插拔通知

3.3 ICameraDevice 接口详解

ICameraDevice 代表一个具体的相机设备实例。它负责配置会话、创建数据流,并暴露设备的静态信息与能力。

3.3.1 核心方法

方法 功能描述 关键参数
getCameraCharacteristics() 返回相机静态元数据(如传感器尺寸、AE/AWB 能力) 无
open() 打开相机设备,准备硬件资源 无
close() 关闭相机设备,释放硬件资源 无
createCaptureSession() 创建捕获会话,绑定输出 Surface outputConfiguration、sessionCallback

3.3.2 设备状态机

每个 ICameraDevice 实例内部维护一个状态机,确保操作顺序合法:

  • CLOSED: 初始状态,设备未打开。
  • OPENED: 调用 open() 后进入,可查询特性。
  • CONFIGURED: 调用 createCaptureSession() 成功后进入,可提交请求。
  • ERROR: 硬件异常或驱动崩溃时进入,需重新打开。
最佳实践: 在 open() 实现中,应完成以下操作:
1. 初始化传感器驱动(如 V4L2 打开设备节点)。
2. 分配 ISP 流水线资源。
3. 读取并缓存静态元数据。
4. 注册设备错误监听(如 watchdog 超时)。

3.3.3 ICameraDevice 状态机 SVG 图

ICameraDevice 状态机 CLOSED OPENED CONFIGURED ERROR open() createSession() 异常 reopen() close()

3.4 ICameraDeviceSession 接口详解

ICameraDeviceSession 是实际处理图像捕获请求的接口。它负责接收 Framework 下发的 CaptureRequest,驱动 ISP 流水线,并返回 CaptureResult 和图像缓冲区。

3.4.1 核心方法

方法 功能描述 调用时机
processCaptureRequest() 处理单个捕获请求,触发一次拍照或预览帧 每次应用请求帧时
flush() 清空所有待处理的请求队列 会话关闭或切换配置时
close() 销毁会话,释放所有流水线资源 会话生命周期结束
configureStreams() 配置输出流(分辨率、格式、Surface) 会话创建或重新配置时

3.4.2 请求处理流水线

  1. 接收请求: Framework 调用 processCaptureRequest(),传入 CaptureRequest 对象。
  2. 解析元数据: 提取 AE/AWB/AF 设置、3A 模式、裁剪区域等。
  3. 驱动 ISP: 将元数据转换为硬件寄存器配置,触发传感器曝光。
  4. 接收 RAW/YUV/JPEG: 从 ISP 输出缓冲区获取图像数据。
  5. 返回结果: 通过回调返回 CaptureResult 和填充后的输出缓冲区。
性能关键点: processCaptureRequest() 必须在 1 帧时间内返回(通常 16.67ms @60fps)。如果 HAL 实现中涉及复杂后处理(如 HDR 合成、多帧降噪),建议使用异步线程池,避免阻塞 IPC 调用。

3.4.3 请求处理流水线 SVG 图

ICameraDeviceSession 请求处理流水线 步骤 1 接收 CaptureRequest 步骤 2 解析元数据 步骤 3 驱动 ISP 寄存器 步骤 4 接收图像数据 步骤 5 返回结果 流水线关键约束 • 步骤 1~5 必须在单帧时间内完成(16.67ms @60fps) • 步骤 3 涉及硬件寄存器操作,建议使用内核态驱动加速 • 步骤 4 的缓冲区管理必须使用 Android 的 BufferQueue 机制 • 步骤 5 的回调必须异步执行,避免阻塞 IPC 线程

3.5 接口关系总览

三个接口在 Camera HAL 中形成清晰的层级关系:

  • ICameraProvider: 全局单例,负责设备发现与生命周期管理。
  • ICameraDevice: 每个物理/逻辑相机一个实例,负责会话创建与特性查询。
  • ICameraDeviceSession: 每个活跃会话一个实例,负责实际的图像捕获流水线。
项目落地建议: 在实现 HAL 时,建议将三个接口的实现类分别放在独立的文件中:
CameraProvider.cpp / CameraDevice.cpp / CameraDeviceSession.cpp。
每个类内部维护自己的状态机与资源池,避免跨类直接访问内部数据结构。通过回调接口(如 ICameraProviderCallback)实现层级间通信。

3.5.1 接口层级关系 SVG 图

Camera HAL 接口层级关系 Camera Framework CameraService ICameraProvider 设备枚举、热插拔管理 ICameraDevice 设备控制、会话创建 ICameraDeviceSession 捕获请求处理、图像流水线

3.6 本章小结

接口 职责 关键方法 生命周期
ICameraProvider 设备枚举、热插拔 getCameraIdList()、getCameraDeviceInterface() 进程级单