2. HAL1 接口概述:Legacy Camera HAL 接口定义与关键数据结构

在 Android Camera 架构演进中,HAL1(也称为 Legacy Camera HAL)是第一个正式定义的硬件抽象层接口。尽管从 Android 8.0 起 Google 已弃用 HAL1,但在大量旧平台、低端设备以及第三方移植项目中,HAL1 仍然是必须面对的现实。理解 HAL1 的接口定义和核心数据结构,是调试 CameraProvider 兼容性问题的基本功。

2.1 HAL1 接口定义

HAL1 定义在 hardware/libhardware/include/hardware/camera.h 中。它采用 Android 标准 HAL 架构:通过 hw_module_t 暴露模块入口,通过 hw_device_t 暴露设备操作接口。Camera HAL1 模块的 ID 固定为 CAMERA_HARDWARE_MODULE_ID(即 "camera")。

关键点: HAL1 是同步阻塞模型——每次调用 start_preview、take_picture 等操作时,HAL 实现必须等待操作完成才返回。这与 HAL3 的异步 pipeline 模型有本质区别。

2.2 关键数据结构回顾

2.2.1 hw_module_t —— 模块描述符

hw_module_t 是所有 Android HAL 模块的通用头部。Camera HAL1 模块必须以此结构开头,并填充正确的 tag、module_api_version、hal_api_version 和 id。

typedef struct hw_module_t {
    uint32_t tag;               // 必须为 HARDWARE_MODULE_TAG
    uint16_t module_api_version; // 模块版本,HAL1 通常为 1
    uint16_t hal_api_version;    // HAL API 版本
    const char *id;             // 模块 ID,Camera 为 "camera"
    const char *name;           // 模块名称
    const char *author;         // 作者
    struct hw_module_methods_t* methods; // 模块方法表
    void* dso;                  // 动态库句柄
    uint32_t reserved[32];      // 保留字段
} hw_module_t;

Camera HAL1 模块在实现时,通常定义一个 camera_module_t 结构体,其第一个成员就是 hw_module_t,后面再扩展 Camera 特有的字段(如 get_number_of_cameras、get_camera_info 等)。

2.2.2 hw_device_t —— 设备描述符

hw_device_t 是所有 HAL 设备对象的通用头部。Camera HAL1 的设备结构体 camera_device_t 同样以此开头。

typedef struct hw_device_t {
    uint32_t tag;               // 必须为 HARDWARE_DEVICE_TAG
    uint32_t version;           // 设备版本
    struct hw_module_t* module; // 指向所属模块
    uint32_t reserved[12];      // 保留字段
    int (*close)(struct hw_device_t* device); // 关闭设备
} hw_device_t;

在 Camera HAL1 中,camera_device_t 扩展了 hw_device_t,并包含指向 camera_device_ops_t 的指针——后者才是真正的 Camera 操作函数表。

2.2.3 camera_device_ops_t —— 操作函数表

这是 HAL1 的核心接口,定义了所有 Camera 操作的回调函数指针。以下是关键函数(共约 30+ 个):

函数名 功能描述 调用时机
set_preview_window 设置预览窗口(ANativeWindow) start_preview 之前
start_preview 启动预览流 应用调用 startPreview
stop_preview 停止预览流 应用调用 stopPreview
take_picture 拍照(返回 JPEG 或 raw) 应用调用 takePicture
set_parameters 设置 Camera 参数(字符串形式) 应用调用 setParameters
get_parameters 获取当前 Camera 参数 应用调用 getParameters
auto_focus 触发自动对焦 应用调用 autoFocus
cancel_auto_focus 取消自动对焦 应用调用 cancelAutoFocus
调试提示: HAL1 的 set_parameters 和 get_parameters 使用字符串键值对传递参数(如 "preview-size=640x480"),这与 HAL3 的结构化 metadata 完全不同。在兼容性调试中,参数解析错误是最常见的崩溃来源之一。

2.3 HAL1 模块与设备的关系

下图展示了 HAL1 中模块、设备、操作函数表之间的层级关系:

HAL1 模块-设备-操作函数表层级关系 HAL1 模块-设备-操作函数表层级关系 hw_module_t (camera_module_t) tag | module_api_version | id = "camera" | methods → open() 扩展字段: get_number_of_cameras() | get_camera_info() open() 创建 hw_device_t (camera_device_t) tag | version | module(回指) | close() | ops → camera_device_ops_t* ops 指针 camera_device_ops_t set_preview_window | start_preview | stop_preview | take_picture set_parameters | get_parameters | auto_focus | cancel_auto_focus | ... (共约 30+ 个函数指针)

2.4 HAL1 关键数据结构对比

下表总结了 HAL1 中三个核心数据结构的职责和生命周期:

数据结构 生命周期 创建者 主要职责
hw_module_t 进程生命周期(单例) HAL 库加载时 暴露模块入口、枚举 Camera、提供 open() 方法
hw_device_t Camera 打开到关闭 module->methods->open() 代表一个 Camera 设备实例,持有操作函数表
camera_device_ops_t 与设备同生命周期 设备创建时赋值 所有 Camera 操作的具体实现入口

2.5 HAL1 兼容性调试要点

  • 模块加载失败: 检查 hw_module_t.tag 是否为 HARDWARE_MODULE_TAG(0x534C4F48),否则 HAL 框架拒绝加载。
  • 设备打开失败: 确认 camera_device_t 的 ops 指针在 open() 中已正确赋值,且所有函数指针非 NULL。
  • 参数传递错误: HAL1 使用字符串参数,注意键名大小写、分隔符(逗号、括号)必须与 framework 期望一致。
  • 预览窗口设置: set_preview_window 传入的 ANativeWindow 可能为 NULL(表示取消预览),HAL 实现必须正确处理。
常见陷阱: 许多 HAL1 实现在 take_picture 中直接调用 stop_preview,但 framework 可能期望拍照后预览继续。这种语义差异在 CameraProvider 适配时会导致预览黑屏或 ANR。

2.6 HAL1 调用流程示意

以下流程图展示了一个典型的 HAL1 预览+拍照调用序列:

HAL1 预览+拍照典型调用序列 HAL1 预览+拍照典型调用序列 1. open() 打开 Camera 2. set_preview_window() 3. set_parameters() 4. start_preview() 5. take_picture() 6. stop_preview() / close() 调试关注点 ① 参数格式是否正确 ② 预览窗口是否有效 ③ 拍照后预览状态