在 Android Camera HAL(硬件抽象层)架构中,camera_module_t 是整个 Camera HAL 动态库的入口点。它是一个标准的 C 结构体,定义了 Camera 服务(Camera Service)如何与底层硬件驱动进行交互。
可以把 camera_module_t 理解为 Camera HAL 的"名片"或"总管",Camera Service 通过它来获取摄像头数量、查询参数以及打开具体的摄像头设备。
以下是关于 camera_module_t 的详细介绍:
1. 定义位置
camera_module_t 定义在头文件: hardware/libhardware/include/hardware/camera_common.h
2. 结构体继承关系
在 C 语言中,Android 使用"结构体嵌套"来模拟继承。camera_module_t 的第一个成员必须是 hw_module_t。
c
typedef struct camera_module {
/**
* 必须是第一个成员,由 libhardware 使用。
* 包含了版本、ID、名称、作者等基础信息。
*/
hw_module_t common;
// 获取系统中可用的摄像头数量
int (*get_number_of_cameras)(void);
// 获取特定摄像头的静态信息(如:朝向、旋转角度、资源能力等)
int (*get_camera_info)(int camera_id, struct camera_info *info);
// 设置回调函数,用于处理热插拔(Hotplug)等异步事件
int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
// 获取供应商特定的标签操作接口(用于扩展参数)
void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
// 打开旧版本的摄像头设备(主要为了兼容 HAL1)
int (*open_legacy)(const struct hw_module_t* module, const char* id,
uint32_t hal_Version, struct hw_device_t** device);
// 设置闪光灯的手电筒模式
int (*set_torch_mode)(const char* camera_id, bool enabled);
// 资源成本估算(用于多摄像头并发场景)
int (*get_resource_cost)(int camera_id, struct camera_resource_cost *res_cost);
// 获取摄像头物理属性(针对多摄像头模块)
int (*get_physical_camera_info)(int camera_id, camera_metadata_t **static_metadata);
/* 预留位,用于后续扩展 */
void* reserved[8];
} camera_module_t;
3. 核心成员详解
(1) common (hw_module_t)
这是 Android 硬件模块的通用标准。它包含了一个非常关键的函数指针 open。虽然 Camera 后来引入了更直接的 open 方式,但底层的加载逻辑依然依赖它。
(2) get_number_of_cameras
Camera Service 启动时首先调用。它返回当前设备上连接的摄像头总数。
- 如果是固定摄像头,通常返回 2(前后各一)。
- 如果是外接 USB 摄像头,该值会动态变化。
(3) get_camera_info
返回 struct camera_info。这个结构体非常重要,它告诉 Framework:
facing: 摄像头方向(前置、后置、外置)。orientation: 传感器的安装旋转角度。device_version: 该摄像头支持的 HAL 版本(如CAMERA_DEVICE_API_VERSION_3_2)。static_camera_characteristics: (针对 HAL3)包含极其详尽的硬件参数,如焦距范围、分辨率列表、是否支持抗锯齿等。
(4) set_callbacks
允许 Camera Service 向 HAL 注册回调。最常见的用途是热插拔支持(Hotplug)。当外接 USB 摄像头插入或拔出时,HAL 通过这个回调通知系统,而无需重启服务。
(5) set_torch_mode
控制闪光灯作为手电筒使用。这是在 camera_module_t 级别定义的,因为开启手电筒通常不需要完整打开(Open)整个摄像头管线,这样更省电。
4. 运行流程:它是如何工作的?
- 加载 HAL 库 :Camera Service 启动时,使用
hw_get_module()根据 ID (CAMERA_HARDWARE_MODULE_ID) 查找并加载对应的.so库(如camera.msm8998.so)。 - 获取结构体指针 :库加载后,系统会找到一个名为
HAL_MODULE_INFO_SYM的符号,并强制转换为camera_module_t*。 - 初始化 :Camera Service 调用
get_number_of_cameras()。 - 枚举与查询 :循环调用
get_camera_info()获取每个摄像头的基本参数。 - 打开设备 :当 App 请求打开相机时,Framework 调用
common.methods->open。- 在 HAL3 中,
open函数会返回一个camera3_device_t结构体,后续所有的拍照、预览操作都通过这个device结构体进行。
- 在 HAL3 中,
5. 如何在 HAL 实现中定义它?
开发者在编写 Camera HAL 时,必须实例化这个结构体。以下是一个典型的代码片段:
c
static struct hw_module_methods_t camera_module_methods = {
.open = camera_device_open, // 指向打开设备的函数
};
camera_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_2_4,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "My Vendor Camera HAL",
.author = "The Android Open Source Project",
.methods = &camera_module_methods,
},
.get_number_of_cameras = get_num_cameras,
.get_camera_info = get_cam_info,
.set_callbacks = set_callbacks,
.set_torch_mode = set_torch_mode,
};
6. 总结
camera_module_t 是 Camera 子系统的 控制面(Control Plane) 接口:
- 它负责全局管理(多少个相机、谁能用手电筒)。
- 它是创建者 (通过
open创建具体的设备实例)。 - 它不负责具体的图像流传输(那是
camera3_device_t的职责)。
在现代 Android 系统(HIDL/AIDL 架构)中,虽然具体的底层实现可能封装在 ICameraProvider 之下,但其核心逻辑依然是围绕着 camera_module_t 所定义的这些操作展开的。