camera3_device_t 结构体:设备接口定义

好,咱们接着往下聊。上一章我讲了 HAL3 的整体架构,今天咱们聚焦到一个具体的结构体——camera3_device_t。这个结构体,说白了就是 Camera HAL 设备在 Framework 眼中的「门面」。Framework 要操作相机设备,全得通过它。

我个人习惯把 camera3_device_t 理解成「设备句柄的升级版」。它不像 camera3_callback_ops_t 那样只负责回调,它承载了真正的设备操作入口。

结构体定义解析

先看定义,在 hardware/libhardware/include/hardware/camera3.h 中:

typedef struct camera3_device {
    hw_device_t common;
    camera3_device_ops_t *ops;
    void *priv;
} camera3_device_t;

嗯,就三个字段。但每个字段都不简单。

字段 类型 说明
common hw_device_t Android HAL 设备通用头,包含 open/close 等基础接口
ops camera3_device_ops_t * 函数指针表,所有相机操作入口
priv void * 私有数据指针,HAL 实现方自己用

核心要点common 是 Android HAL 层的统一规范,所有硬件设备都必须以 hw_device_t 开头。这样 Framework 才能用统一的方式打开、关闭设备。

ops 函数指针表

这才是重头戏。camera3_device_ops_t 里定义了十几个函数指针,我挑几个最关键的说说。

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 *stream_list);
    int (*register_stream_buffers)(const struct camera3_device *,
                                   const camera3_stream_buffer_set_t *buffer_set);
    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 *);
    void (*signal_stream_flush)(const struct camera3_device *,
                                uint32_t num_streams,
                                const camera3_stream_t *const *streams);
    int (*is_reconfiguration_required)(const struct camera3_device *,
                                       const camera_metadata_t *old_session_params,
                                       const camera_metadata_t *new_session_params);
} camera3_device_ops_t;

这里我重点讲三个:

  • initialize:初始化设备,注册回调。Framework 会传进来 camera3_callback_ops_t,HAL 用它来通知 Framework 各种事件。
  • configure_streams:配置数据流。说白了就是告诉 HAL:「我要三个流:预览、拍照、录像,你准备好。」
  • process_capture_request:处理拍照请求。这是最核心的函数,每次拍照、预览帧都通过它下发。

我的经验:我在项目中遇到过 configure_streams 被反复调用导致性能问题。后来发现是 Framework 在某些场景下会重新配置流。建议在实现时做好缓存,避免不必要的重配置。

open/close 流程

好,咱们看看设备是怎么打开和关闭的。这个流程我画过很多次,今天用文字讲清楚。

打开流程

  1. Framework 调用 hw_get_module() 加载 HAL 库
  2. 调用 camera3_module_t->common.methods->open()
  3. HAL 实现中分配 camera3_device_t 结构体
  4. 填充 common 字段(tag、version、close 函数指针等)
  5. 填充 ops 字段,指向实际的函数实现
  6. 设置 priv 指向私有数据(比如硬件句柄、状态机等)
  7. 返回设备句柄给 Framework
// 典型的 open 实现片段
static int camera_device_open(const hw_module_t* module, 
                               const char* id,
                               hw_device_t** device) {
    camera3_device_t *camera_dev = malloc(sizeof(*camera_dev));
    memset(camera_dev, 0, sizeof(*camera_dev));
    
    // 填充 common
    camera_dev->common.tag = HARDWARE_DEVICE_TAG;
    camera_dev->common.version = CAMERA_DEVICE_API_VERSION_3_5;
    camera_dev->common.module = (hw_module_t*)module;
    camera_dev->common.close = camera_device_close;
    
    // 填充 ops
    camera_dev->ops = &g_camera3_ops;
    
    // 设置私有数据
    camera_dev->priv = init_private_data();
    
    *device = &camera_dev->common;
    return 0;
}

注意common.close 必须实现!我曾经见过有人忘了设置这个指针,结果 Framework 调用 close 时直接崩溃。嗯,这种低级错误排查起来特别痛苦。

关闭流程

  1. Framework 调用 camera3_device_t->common.close()
  2. HAL 实现中释放所有资源(停止硬件、释放内存、关闭文件描述符等)
  3. 释放 camera3_device_t 结构体本身
static int camera_device_close(hw_device_t* device) {
    camera3_device_t *camera_dev = (camera3_device_t*)device;
    
    // 停止所有正在处理的请求
    camera_dev->ops->flush(camera_dev);
    
    // 释放私有数据
    release_private_data(camera_dev->priv);
    
    // 释放设备结构体
    free(camera_dev);
    return 0;
}

避坑指南

我做了这么多年 Camera HAL,总结几个常见坑:

  • 线程安全process_capture_request 可能被多个线程同时调用。你的实现必须是线程安全的。
  • 内存管理priv 指向的内存必须在 close 时释放。别漏了。
  • 版本兼容common.version 要填对。填低了 Framework 可能不支持某些功能,填高了可能不兼容。
  • 回调注册initialize 中拿到的 callback_ops 要保存好,后续所有事件通知都靠它。

总结一下camera3_device_t 是 HAL3 设备接口的基石。它通过 ops 函数指针表暴露所有操作,通过 common 融入 Android HAL 框架,通过 priv 保持灵活性。理解了这个结构体,你就掌握了 HAL3 设备层的核心。

下一章我会讲 camera3_stream_t 和流配置,那是数据通路的关键。咱们到时候见。