Camera HAL开发从入门到精通 - 第3节
3.1 HAL3 核心接口总览
Android Camera HAL3 接口是连接 Android 框架层(Framework)与底层相机硬件驱动的关键抽象层。HAL3 的设计围绕三个核心结构体展开:camera3_device_t(设备操作接口)、camera3_callback_ops_t(回调通知接口),以及底层的 hw_module_t 和 hw_device_t(HAL 模块与设备基础定义)。
理解这四个结构体的职责与协作关系,是掌握 HAL3 开发的第一步。下图展示了它们在系统架构中的位置与数据流方向:
3.2 HAL 模块定义:hw_module_t
hw_module_t 是所有 Android HAL 模块的通用基类,定义在 hardware/libhardware/include/hardware/hardware.h 中。Camera HAL 模块必须首先实现此结构体,作为 Framework 发现和加载 HAL 的入口。
3.2.1 结构体定义
typedef struct hw_module_t {
uint32_t tag; // 必须为 HARDWARE_MODULE_TAG
uint16_t module_api_version; // 模块 API 版本
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-7]; // 保留字段
} hw_module_t;
3.2.2 Camera HAL 模块实例
Camera HAL 模块需要定义一个全局的 HAL_MODULE_INFO_SYM 符号,Framework 通过 dlopen 加载该符号来获取模块句柄。典型实现如下:
static struct hw_module_methods_t camera_module_methods = {
.open = camera_device_open, // 打开相机设备
};
struct camera_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_3_0,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "Camera HAL3 Module",
.author = "Your Company",
.methods = &camera_module_methods,
.dso = NULL,
.reserved = {0},
},
};
"camera",否则 Framework 无法正确匹配 HAL 模块。module_api_version 应设置为 CAMERA_MODULE_API_VERSION_3_0 或更高版本,以标识 HAL3 接口。
3.3 HAL 设备定义:hw_device_t
hw_device_t 是 HAL 设备的通用基类,代表一个具体的硬件设备实例。当 Framework 调用模块的 open() 方法时,HAL 需要返回一个填充好的 hw_device_t 结构体,其中包含指向具体设备操作接口的指针。
3.3.1 结构体定义
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;
3.3.2 Camera 设备结构体
Camera HAL3 在 hw_device_t 基础上扩展出 camera3_device_t,其第一个成员 common 就是 hw_device_t 类型。这种“继承”关系使得 Framework 可以通过类型转换安全地访问底层设备。
| 成员 | 类型 | 说明 |
|---|---|---|
| common | hw_device_t | 基类设备结构体,包含 tag、version、close 等 |
| ops | camera3_device_ops_t * | 指向设备操作函数表,包含 initialize、configure_streams、process_capture_request 等 |
| priv | void * | 私有数据指针,HAL 实现可在此存放设备上下文 |
3.4 设备操作接口:camera3_device_t
camera3_device_t 是 HAL3 中最重要的结构体,它定义了 Framework 与 HAL 之间所有请求/响应交互的接口。每个打开的相机设备对应一个 camera3_device_t 实例。
3.4.1 结构体定义
typedef struct camera3_device {
hw_device_t common; // 基类设备
camera3_device_ops_t *ops; // 操作函数表
void *priv; // 私有数据
} camera3_device_t;
3.4.2 核心操作函数表
camera3_device_ops_t 是 HAL3 的核心操作接口,Framework 通过该表下发所有控制指令。下表列出了最关键的几个函数指针:
| 函数指针 | 职责 | 调用时机 |
|---|---|---|
| initialize | 初始化设备,注册回调接口 | 设备打开后立即调用 |
| configure_streams | 配置数据流(分辨率、格式、方向等) | 预览/录像/拍照开始前 |
| process_capture_request | 下发单次捕获请求 | 每次拍照或预览帧请求 |
| flush | 刷新所有未完成的请求 | 设备关闭或异常恢复时 |
| dump | 导出调试信息 | Framework 请求调试时 |
typedef struct camera3_device_ops {
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);
int (*process_capture_request)(const struct camera3_device *,
camera3_capture_request_t *request);
void (*get_metadata_vendor_tag_ops)(const struct camera3_device *,
vendor_tag_query_ops_t *ops);
int (*flush)(const struct camera3_device *);
void (*dump)(const struct camera3_device *, int fd);
int (*reserved[8])();
} camera3_device_ops_t;
process_capture_request 时,必须确保每个请求都能通过回调返回结果(成功或失败)。如果 HAL 未返回结果就丢弃请求,会导致 Framework 超时并触发 ANR(应用无响应)。
3.5 回调通知接口:camera3_callback_ops_t
camera3_callback_ops_t 是 Framework 提供给 HAL 的回调接口,HAL 通过此接口将捕获结果、事件通知、缓冲区状态等异步信息返回给 Framework。该结构体在 initialize() 调用时由 Framework 传入,HAL 必须保存该指针以便后续使用。
3.5.1 结构体定义
typedef struct camera3_callback_ops {
void (*process_capture_result)(const struct camera3_callback_ops *,
const camera3_capture_result_t *result);
void (*notify)(const struct camera3_callback_ops *,
const camera3_notify_msg_t *msg);
} camera3_callback_ops_t;
3.5.2 回调函数详解
| 回调函数 | 触发时机 | 传递数据 |
|---|---|---|
| process_capture_result | 捕获请求完成(或部分完成)时 | camera3_capture_result_t:包含输出缓冲区、元数据、部分结果标识等 |
| notify | 发生异步事件时 | camera3_notify_msg_t:包含错误码、快门时间、请求 ID 等 |
3.5.3 回调使用示例
// HAL 端保存回调指针
static const camera3_callback_ops_t *g_callback_ops = NULL;
int my_camera_initialize(const struct camera3_device *dev,
const camera3_callback_ops_t *callback_ops) {
g_callback_ops = callback_ops;
// 初始化硬件...
return 0;
}
// 在捕获完成时调用
void on_capture_done(uint32_t frame_number,
const camera3_capture_result_t *result) {
if (g_callback_ops && g_callback_ops->process_capture_result) {
g_callback_ops->process_capture_result(g_callback_ops, result);
}
}
// 在发生错误时调用
void on_error(uint32_t frame_number, int error_code) {
camera3_notify_msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.type = CAMERA3_MSG_ERROR;
msg.message.error.frame_number = frame_number;
msg.message.error.error_code = error_code;
if (g_callback_ops && g_callback_ops->notify) {
g_callback_ops->notify(g_callback_ops, &msg);
}
}
3.6 接口初始化流程
从 Framework 打开相机到完成初始化的完整流程如下,展示了四个核心结构体如何串联工作:
- 模块加载:Framework 通过
hw_get_module(CAMERA_HARDWARE_MODULE_ID, &module)加载 HAL 动态库,获取hw_module_t指针。 - 设备打开:调用
module->methods->open(module, camera_id, &device),HAL 返回填充好的camera3_device_t(其common成员为hw_device_t)。 - 初始化:Framework 调用
device->ops->initialize(device, callback_ops),传入camera3_callback_ops_t回调接口。 - 流配置:调用
device->ops->configure_streams(device, &stream_config)配置输出流。 - 请求循环:Framework 反复调用
device->ops->process_capture_request(device, request)下发捕获请求,HAL 通过回调返回结果。 - 设备关闭:调用
device->common.close(&device->common)释放资源。
3.7 接口实现注意事项
- 线程安全:
process_capture_request可能被多个线程并发调用,HAL 实现必须保证内部状态的一致性,建议使用互斥锁保护关键数据结构。 - 内存管理:HAL 不应在回调中直接释放 Framework 传入的缓冲区,应等待 Framework 通过
return_buffer机制(或等效方式)通知后再释放。 - 超时处理:每个捕获请求应在合理时间内(通常 3-5 秒)通过回调返回结果。超时未返回会导致 Framework 触发错误恢复流程。
- 错误上报:当硬件发生不可恢复错误时,必须通过
notify()回调上报CAMERA3_MSG_ERROR事件,并携带具体的错误码。 - 版本兼容:HAL3 接口从 Android 5.0 引入,后续版本增加了部分扩展字段。实现时应检查
module_api_version和hal_api_version,确保向后兼容。