4. HAL模块初始化:HAL_MODULE_INFO_SYM结构体定义、open函数实现、camera_info填充、静态特性元数据构建
HAL模块初始化是Camera HAL驱动开发的起点,也是整个相机框架与硬件交互的桥梁。本章深入剖析HAL模块初始化的四个核心环节:HAL_MODULE_INFO_SYM结构体定义、open函数实现、camera_info填充以及静态特性元数据构建。掌握这些内容,你将能够构建一个符合Android HAL规范的相机模块入口。
4.1 HAL_MODULE_INFO_SYM结构体定义
在Android Camera HAL中,HAL_MODULE_INFO_SYM是每个HAL模块必须导出的符号,它是HAL框架与驱动代码之间的契约。该结构体定义了模块的ID、版本号、作者信息以及最重要的回调函数指针——open。
以下是一个标准的HAL_MODULE_INFO_SYM定义示例:
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_2_4,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "Camera HAL Module",
.author = "Your Company",
.methods = &camera_module_methods,
.dso = NULL,
.reserved = {0},
},
.get_number_of_cameras = get_number_of_cameras,
.get_camera_info = get_camera_info,
.set_callbacks = set_callbacks,
.get_vendor_tag_ops = get_vendor_tag_ops,
.open_legacy = NULL,
.set_torch_mode = set_torch_mode,
.init = NULL,
.reserved = {0},
};
结构体字段说明:
| 字段 | 说明 | 典型值 |
|---|---|---|
| tag | 模块标签,固定为HARDWARE_MODULE_TAG | HARDWARE_MODULE_TAG |
| module_api_version | 模块API版本,决定HAL层支持的功能集 | CAMERA_MODULE_API_VERSION_2_4 |
| hal_api_version | HAL框架API版本 | HARDWARE_HAL_API_VERSION |
| id | 模块唯一标识符 | CAMERA_HARDWARE_MODULE_ID |
| methods | 指向hw_module_methods_t结构体的指针,包含open函数 | &camera_module_methods |
| get_number_of_cameras | 返回设备上可用的摄像头数量 | 函数指针 |
| get_camera_info | 填充指定摄像头的camera_info结构体 | 函数指针 |
4.2 open函数实现
open函数是HAL模块的入口点,负责创建并初始化摄像头设备实例。当CameraService调用hw_module_t->methods->open()时,HAL驱动需要完成设备节点的打开、硬件资源的分配以及回调接口的注册。
open函数的标准实现流程:
- 参数校验:检查module和hw_device_t指针是否有效,验证设备ID是否在合法范围内。
- 内存分配:为camera_device_t结构体分配内存,并初始化为零。
- 设备初始化:打开V4L2设备节点或ISP驱动接口,初始化传感器和ISP硬件。
- 回调注册:设置camera_device_ops_t中的函数指针,包括get_metadata、ops等。
- 返回设备句柄:将初始化完成的camera_device_t通过参数返回给框架。
static int camera_device_open(const struct hw_module_t *module,
const char *id,
struct hw_device_t **hw_device) {
int camera_id = atoi(id);
camera_device_t *camera_dev = NULL;
// 1. 参数校验
if (module == NULL || hw_device == NULL) {
ALOGE("Invalid parameters");
return -EINVAL;
}
if (camera_id < 0 || camera_id >= MAX_CAMERAS) {
ALOGE("Invalid camera id: %d", camera_id);
return -ENODEV;
}
// 2. 内存分配
camera_dev = (camera_device_t *)calloc(1, sizeof(camera_device_t));
if (camera_dev == NULL) {
ALOGE("Failed to allocate camera device");
return -ENOMEM;
}
// 3. 设备初始化
camera_dev->priv = init_camera_hardware(camera_id);
if (camera_dev->priv == NULL) {
ALOGE("Failed to init camera hardware for id %d", camera_id);
free(camera_dev);
return -EIO;
}
// 4. 设置设备操作函数
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;
camera_dev->ops = &camera_device_ops;
// 5. 返回设备句柄
*hw_device = &camera_dev->common;
ALOGI("Camera device opened for id %d", camera_id);
return 0;
}
4.3 camera_info填充
camera_info结构体描述了摄像头的静态属性,包括设备方向、是否支持闪光灯、设备姿态等。框架通过get_camera_info回调获取这些信息,用于上层应用决策。
camera_info结构体定义:
typedef struct camera_info {
int device_version;
uint32_t device_id;
int facing;
int orientation;
const char *resource_cost;
camera_metadata_t *static_camera_characteristics;
int status;
int device_type;
char *logical_camera_id;
int physical_camera_count;
char **physical_camera_ids;
bool is_remote_device;
int capability;
int conflict_camera_count;
char **conflict_camera_ids;
} camera_info_t;
填充camera_info的典型实现:
static int get_camera_info(int camera_id, struct camera_info *info) {
if (camera_id < 0 || camera_id >= MAX_CAMERAS) {
return -ENODEV;
}
// 设置设备版本
info->device_version = CAMERA_DEVICE_API_VERSION_3_5;
// 设置摄像头朝向
if (camera_id == 0) {
info->facing = CAMERA_FACING_BACK;
info->orientation = 90; // 后置摄像头旋转角度
} else {
info->facing = CAMERA_FACING_FRONT;
info->orientation = 270; // 前置摄像头旋转角度
}
// 设置资源开销
info->resource_cost = "100";
// 设置静态特性元数据
info->static_camera_characteristics = build_static_metadata(camera_id);
// 设置设备状态
info->status = CAMERA_DEVICE_STATUS_PRESENT;
// 设置设备类型
info->device_type = CAMERA_DEVICE_TYPE_PHYSICAL;
return 0;
}
| 字段 | 含义 | 常见值 |
|---|---|---|
| facing | 摄像头朝向(前置/后置/外接) | CAMERA_FACING_BACK / CAMERA_FACING_FRONT |
| orientation | 图像相对于自然方向的旋转角度 | 0, 90, 180, 270 |
| resource_cost | 摄像头资源开销,用于多摄像头场景的调度决策 | "100"(百分比字符串) |
| status | 摄像头当前状态 | CAMERA_DEVICE_STATUS_PRESENT |
| device_type | 设备类型(物理/逻辑/虚拟) | CAMERA_DEVICE_TYPE_PHYSICAL |
4.4 静态特性元数据构建
静态特性元数据(static_camera_characteristics)是Camera HAL中最复杂的数据结构,它描述了摄像头所有不可变的硬件能力。这些元数据以camera_metadata_t的形式存储,包含传感器尺寸、像素大小、AE/AWB/AF能力、支持的输出格式等数百个标签。
构建静态特性元数据的核心步骤:
- 创建元数据缓冲区:使用
allocate_camera_metadata()分配足够大的缓冲区。 - 填充基础信息:设置传感器信息、像素阵列大小、颜色特性等。
- 填充能力信息:设置AE/AWB/AF模式、场景模式、特效等支持情况。
- 填充输出配置:设置支持的图像格式、分辨率、帧率范围。
- 填充控制能力:设置3A控制、同步能力、请求管线深度等。
static camera_metadata_t *build_static_metadata(int camera_id) {
camera_metadata_t *metadata;
int32_t sensor_width = 3264;
int32_t sensor_height = 2448;
int32_t pixel_array_size[] = {sensor_width, sensor_height};
int32_t active_array_size[] = {0, 0, sensor_width, sensor_height};
// 1. 计算元数据所需空间
size_t entry_capacity = 100;
size_t data_capacity = 4096;
metadata = allocate_camera_metadata(entry_capacity, data_capacity);
// 2. 填充传感器信息
int32_t sensor_info[] = {ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB};
add_camera_metadata_entry(metadata,
ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
pixel_array_size, 2);
add_camera_metadata_entry(metadata,
ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
active_array_size, 4);
// 3. 填充AE/AWB/AF能力
uint8_t ae_available_modes[] = {
ANDROID_CONTROL_AE_MODE_ON,
ANDROID_CONTROL_AE_MODE_OFF,
ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH
};
add_camera_metadata_entry(metadata,
ANDROID_CONTROL_AE_AVAILABLE_MODES,
ae_available_modes,
sizeof(ae_available_modes));
// 4. 填充支持的输出格式和分辨率
int32_t stream_config[] = {
HAL_PIXEL_FORMAT_YCbCr_420_SP, sensor_width, sensor_height,
HAL_PIXEL_FORMAT_YCbCr_420_SP, 640, 480,
HAL_PIXEL_FORMAT_BLOB, sensor_width, sensor_height,
};
add_camera_metadata_entry(metadata,
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
stream_config,
sizeof(stream_config) / sizeof(int32_t));
// 5. 填充帧率范围
int32_t fps_ranges[] = {15, 30, 30, 30};
add_camera_metadata_entry(metadata,
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
fps_ranges, 4);
return metadata;
}
4.5 初始化流程总览
下图展示了HAL模块初始化的完整流程,从框架加载模块到最终返回设备句柄:
4.6 静态特性元数据关键标签速查
静态特性元数据包含数百个标签,以下表格列出了开发中最常使用的核心标签及其用途:
| 标签ID | 类型 | 说明 | 必填 |
|---|---|---|---|
| ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE | int32[2] | 传感器像素阵列的宽高 | 是 |
| ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE | int32[4] | 有效像素区域(左、上、宽、高) | 是 |
| ANDROID_SENSOR_INFO_SENSITIVITY_RANGE | int32[2] | ISO感光度范围 | 是 |
| ANDROID_CONTROL_AE_AVAILABLE_MODES | uint8[n] | 支持的自动曝光模式列表 | 是 |
| ANDROID_CONTROL_AF_AVAILABLE_MODES | uint8[n] | 支持的自动对焦模式列表 | 是 |
| ANDROID_CONTROL_AWB_AVAILABLE_MODES | uint8[n] | 支持的白平衡模式列表 | 是 |
| ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS | int32[n*4] | 支持的输出流配置(格式、宽、高、方向) | 是 |
| ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS | int64[n*4] | 各格式的最小帧持续时间(纳秒) | 是 |
| ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS | float[n] | 可用焦距列表(毫米) | 是 |
| ANDROID_FLASH_INFO_AVAILABLE | uint8 | 是否支持闪光灯 | 是 |
camera_metadata_t的验证工具进行自检。
4.7 静态特性元数据构建架构
静态特性元数据的构建涉及多个硬件抽象层的协同工作,下图展示了元数据从硬件参数到最终camera_metadata_t的转换路径:
4.8 常见问题与调试技巧
- HAL模块加载失败:检查
HAL_MODULE_INFO_SYM符号是否被正确导出,使用readelf -s hal_module.so | grep HAL_MODULE_INFO_SYM验证。 - open函数返回错误:确认设备节点权限正确,使用
ls -l /dev/video*检查节点是否存在且可读写。 - camera_info填充异常:使用
dumpsys media.camera查看框架层接收到的camera_info内容,与预期值对比。 - 静态元数据CTS失败:使用
camera_metadata_t的dump_camera_metadata()函数打印所有标签,对照Android兼容性定义文档(CDD)逐项检查。
adb shell setprop persist.camera.hal.debug 1控制日志输出级别,快速定位初始化阶段的问题。