常见问题实战:Camera HAL工程排查与案例解析 - 第1节

1.1 Camera HAL 在 Android 系统中的位置与作用

Camera HAL(Hardware Abstraction Layer)是 Android 相机子系统中连接 Framework 与底层硬件驱动的关键中间层。它定义了上层相机服务(CameraService)与硬件实现之间的标准接口,使得同一套 Android 系统能够适配不同厂商的摄像头硬件。

核心定位:HAL 层将硬件差异封装在接口之下,上层无需关心具体的传感器型号、ISP 实现或驱动协议,只需调用标准化的 HAL 接口即可完成图像采集、参数控制与数据流处理。

1.1.1 系统层级关系

从 Android 相机软件栈的纵向分层来看,Camera HAL 处于承上启下的关键位置:

  1. 应用层(App):调用 Camera2 API 或 Camera1 API 发起拍照/录像请求。
  2. Framework 层:CameraService 管理客户端连接、权限校验、流配置与数据分发。
  3. HAL 层:实现 camera_module_t、camera3_device_t 等接口,负责将 Framework 的请求转换为硬件指令。
  4. Kernel 层:V4L2、CSI、I2C 等驱动与传感器、ISP 硬件交互。
排查要点:HAL 层是问题高发区。Framework 与 HAL 之间的接口版本不匹配、HAL 返回的元数据格式错误、流配置参数超出硬件能力,是导致相机黑屏、预览卡顿、拍照失败的三大常见根因。

1.1.2 作用总结

作用维度 具体说明
接口标准化 定义统一的 HAL 接口,屏蔽不同 SoC 平台(Qualcomm、MTK、Rockchip)的硬件差异
数据流管理 管理从传感器到输出 buffer 的完整图像流水线,包括请求排队、帧回调、buffer 复用
参数控制 将 Framework 的 AE/AWB/AF 控制参数转换为硬件寄存器配置,并返回实际生效的元数据
性能隔离 通过 buffer 管理、流超时检测、异常恢复机制,隔离硬件故障对上层的影响

1.2 HAL3 与 HAL1 架构对比

Android 相机 HAL 经历了从 HAL1 到 HAL3 的重大架构演进。HAL3(即 Camera3 HAL)是当前主流架构,HAL1 仅用于兼容老旧设备或特定低端场景。理解两者的差异是排查 HAL 问题的前提。

1.2.1 架构设计对比

对比维度 HAL1 HAL3
设计理念 基于固定流水线,操作模式固化 基于请求-响应模型,灵活配置流
数据流模型 单路输出,预览/拍照/录像切换需重新配置 多路并行输出,支持同时预览+拍照+录像
控制粒度 粗粒度,全局参数一次性设置 逐帧控制,每帧可独立指定 AE/AWB/AF 参数
Buffer 管理 HAL 内部管理 buffer,Framework 被动接收 Framework 提供 buffer,HAL 填充后回调
元数据传递 通过固定结构体传递少量参数 使用 camera_metadata_t 传递数百个控制项与结果项
多摄像头支持 逻辑摄像头支持困难 原生支持物理摄像头与逻辑摄像头组合

1.2.2 HAL3 请求-响应模型

HAL3 的核心是 Capture Request / Capture Result 模型。每一帧的采集都由一个独立的请求驱动,HAL 处理完成后返回结果。这种设计使得每一帧的控制参数、输出流、元数据都可以独立配置。

// HAL3 核心接口:process_capture_request
int process_capture_request(const camera3_capture_request_t *request);

// 请求结构体关键字段
typedef struct camera3_capture_request {
    uint32_t                frame_number;       // 帧序号,单调递增
    const camera3_stream_t  **output_buffers;   // 输出 buffer 数组
    size_t                  num_output_buffers; // 输出 buffer 数量
    const camera_metadata_t *settings;          // 帧控制元数据
    // ...
} camera3_capture_request_t;
常见排查陷阱:HAL3 要求 HAL 实现必须支持 flush() 接口,用于在异常时快速中止所有待处理请求。如果 HAL 未正确实现 flush(),在应用退出或切换摄像头时可能导致 dumpsys 中残留大量未完成的请求,进而引发 buffer 泄漏或死锁。

1.3 HAL 接口定义与核心数据结构

Camera HAL 的接口定义集中在 hardware/libhardware/include/hardware/camera3.h 和 camera_common.h 中。理解这些接口和数据结构是进行 HAL 层问题定位的基础。

1.3.1 模块级接口:camera_module_t

HAL 模块的入口点,Framework 通过 hw_get_module() 加载并获取该结构体。

typedef struct camera_module {
    hw_module_t common;                         // 继承自 hw_module_t
    int (*get_number_of_cameras)(void);         // 获取摄像头数量
    int (*get_camera_info)(int id, struct camera_info *info); // 获取摄像头信息
    int (*set_callbacks)(const camera_module_callbacks_t *callbacks); // 注册回调
    void (*get_vendor_tag_ops)(vendor_tag_ops_t *ops); // 获取厂商自定义 tag
    int (*open_legacy)(const struct hw_module_t *module, const char *id,
                       uint32_t halVersion, struct hw_device_t **device); // 打开旧版 HAL
    // ...
} camera_module_t;

1.3.2 设备级接口:camera3_device_t

每个摄像头设备对应一个 camera3_device_t 实例,Framework 通过 open() 获取。

typedef struct camera3_device {
    hw_device_t common;                         // 继承自 hw_device_t
    int (*initialize)(const struct camera3_device *,
                      const camera3_callback_ops_t *callback_ops); // 初始化
    int (*configure_streams)(const struct camera3_device *,
                             camera3_stream_configuration_t *config); // 配置流
    int (*register_stream_buffers)(const struct camera3_device *,
                                   const camera3_stream_buffer_set_t *buffer_set); // 注册 buffer
    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 *request); // 处理捕获请求
    void (*dump)(const struct camera3_device *, int fd); // 导出调试信息
    int (*flush)(const struct camera3_device *); // 刷新所有待处理请求
    // ...
} camera3_device_t;

1.3.3 核心数据结构

数据结构 用途 关键字段
camera3_stream_t 描述一个输出流(预览、拍照、录像等) stream_type、width、height、format、usage、max_buffers
camera3_stream_configuration_t 描述一次流配置操作的所有流信息 num_streams、streams、operation_mode、session_parameters
camera3_capture_request_t 描述一次捕获请求的所有参数 frame_number、settings、output_buffers、input_buffer
camera3_capture_result_t 描述一次捕获请求的处理结果 frame_number、result、output_buffers、partial_result
camera_metadata_t 存储控制参数和结果元数据(key-value 形式) 内部以 camera_metadata_entry_t 组织,支持 int32/float/int64/double/rational 类型

1.3.4 元数据系统

camera_metadata_t 是 HAL3 中最重要的数据结构之一。它使用紧凑的二进制格式存储数百个控制项(如 ANDROID_SENSOR_EXPOSURE_TIME)和结果项(如 ANDROID_SENSOR_TIMESTAMP)。

// 元数据查找示例
camera_metadata_entry_t entry;
int ret = find_camera_metadata_entry(metadata,
    ANDROID_SENSOR_SENSITIVITY, &entry);
if (ret == 0) {
    int32_t iso = entry.data.i32[0];  // 读取 ISO 值
}
排查技巧:当遇到预览画面异常或参数不生效时,优先检查 HAL 返回的 camera_metadata_t 中是否包含了所有必需的 result 项。使用 adb shell dumpsys media.camera 可以导出当前会话的元数据内容,对比预期值与实际值即可快速定位问题。
Camera HAL 核心接口与数据流关系图 CameraService (Framework) camera_module_t (模块加载与枚举) camera3_device_t (设备初始化、流配置、请求处理) 核心数据结构 camera3_stream_t camera3_capture_request_t camera3_capture_result_t camera_metadata_t Kernel Driver (V4L2 / CSI / ISP) Camera Sensor Hardware 数据流方向:Framework → HAL 模块 → HAL 设备 → 核心数据结构 → Kernel/硬件