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")。
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 |
set_parameters 和 get_parameters 使用字符串键值对传递参数(如 "preview-size=640x480"),这与 HAL3 的结构化 metadata 完全不同。在兼容性调试中,参数解析错误是最常见的崩溃来源之一。
2.3 HAL1 模块与设备的关系
下图展示了 HAL1 中模块、设备、操作函数表之间的层级关系:
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 实现必须正确处理。
take_picture 中直接调用 stop_preview,但 framework 可能期望拍照后预览继续。这种语义差异在 CameraProvider 适配时会导致预览黑屏或 ANR。
2.6 HAL1 调用流程示意
以下流程图展示了一个典型的 HAL1 预览+拍照调用序列: