3. HAL3 初始化流程:open()、initialize() 与静态特性配置
HAL3 初始化是 Camera HAL 移植中最关键的入口阶段,它决定了上层 Camera Service 能否成功加载 HAL 模块并与底层硬件建立通信。本章深入剖析 open() 函数实现、initialize() 回调注册机制、camera_info 填充以及静态特性配置的完整流程。
3.1 初始化流程总览
HAL3 初始化流程分为三个主要阶段,每个阶段都有明确的职责和交付物:
| 阶段 | 触发时机 | 核心职责 | 交付物 |
|---|---|---|---|
| Phase 1: open() | CameraService 调用 hw_module_t->open() |
创建设备实例、初始化硬件抽象层、分配资源 | camera3_device_t 结构体指针 |
| Phase 2: initialize() | CameraService 调用 camera3_device->ops->initialize() |
注册回调接口、建立与 Framework 的通信通道 | camera3_callback_ops_t 回调集 |
| Phase 3: 静态特性配置 | CameraService 调用 get_camera_info() |
填充设备信息、构建静态特性元数据 | camera_info + static_metadata |
移植要点: 三个阶段的执行顺序严格固定,任何阶段的失败都会导致 Camera HAL 无法被 Framework 识别。建议在
open() 阶段完成所有硬件资源预分配,避免在 initialize() 中执行耗时操作。
3.2 open() 函数实现
open() 是 HAL 模块与 Framework 的第一次握手。其核心任务是创建 camera3_device_t 实例并填充操作函数表。
3.2.1 标准实现模板
static int hal3_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device) {
int camera_id = atoi(id);
if (camera_id < 0 || camera_id >= MAX_CAMERAS) {
ALOGE("Invalid camera id: %s", id);
return -ENODEV;
}
// 1. 分配设备上下文
camera3_device_t* hal3_dev = (camera3_device_t*)
calloc(1, sizeof(camera3_device_t));
if (!hal3_dev) return -ENOMEM;
// 2. 填充通用设备头
hal3_dev->common.tag = HARDWARE_DEVICE_TAG;
hal3_dev->common.version = CAMERA_DEVICE_API_VERSION_3_5;
hal3_dev->common.module = (hw_module_t*)module;
hal3_dev->common.close = hal3_close;
// 3. 填充 HAL3 操作函数表
hal3_dev->ops = &g_camera3_ops;
// 4. 初始化私有上下文(硬件抽象层)
camera_private_t* priv = (camera_private_t*)
calloc(1, sizeof(camera_private_t));
priv->camera_id = camera_id;
priv->hal_dev = hal3_dev;
hal3_dev->priv = priv;
// 5. 初始化硬件资源
if (init_hardware(priv) != 0) {
ALOGE("Hardware init failed for camera %d", camera_id);
free(priv);
free(hal3_dev);
return -ENODEV;
}
*device = &hal3_dev->common;
ALOGI("Camera %d opened successfully", camera_id);
return 0;
}
3.2.2 操作函数表定义
camera3_device_ops_t 是 HAL3 设备的核心接口表,必须实现所有函数指针:
static camera3_device_ops_t g_camera3_ops = {
.initialize = hal3_initialize,
.configure_streams = hal3_configure_streams,
.register_stream_buffers = NULL, // HAL3.2+ 已废弃
.process_capture_request = hal3_process_capture_request,
.get_metadata_vendor_tag_ops = NULL,
.dump = hal3_dump,
.flush = hal3_flush,
.signal_stream_flush = NULL,
.is_reconfiguration_required = NULL,
};
常见陷阱:
register_stream_buffers在 HAL3.2 及以上版本必须设为NULL,否则 Framework 会拒绝加载。common.version必须与 HAL 实现版本一致,推荐使用CAMERA_DEVICE_API_VERSION_3_5。- 私有上下文
priv的生命周期管理必须在close()中妥善处理。
3.3 initialize() 回调注册
initialize() 是 HAL3 设备初始化中唯一与 Framework 建立双向通信的入口。Framework 通过此函数将回调接口传递给 HAL,HAL 后续通过回调上报事件、返回结果。
3.3.1 回调接口结构
typedef struct camera3_callback_ops {
// 通知回调:上报错误、快门事件等
void (*notify)(const struct camera3_callback_ops *ops,
const camera3_notify_msg_t *msg);
// 结果回调:返回捕获结果元数据
void (*process_capture_result)(
const struct camera3_callback_ops *ops,
const camera3_capture_result_t *result);
// HAL3.2+ 新增:返回部分元数据结果
void (*process_capture_result_early)(
const struct camera3_callback_ops *ops,
const camera3_capture_result_t *result);
// 缓冲区回调:返回已处理的输出缓冲区
void (*return_stream_buffers)(
const struct camera3_callback_ops *ops,
uint32_t num_buffers,
const camera3_stream_buffer_t *const *buffers);
} camera3_callback_ops_t;
3.3.2 initialize() 实现要点
static int hal3_initialize(const struct camera3_device *device,
const camera3_callback_ops_t *callback_ops) {
camera_private_t* priv = (camera_private_t*)device->priv;
// 1. 保存回调指针(Framework 传入)
priv->callback_ops = callback_ops;
// 2. 初始化传感器驱动
if (sensor_init(priv) != 0) {
ALOGE("Sensor init failed");
return -ENODEV;
}
// 3. 初始化 ISP 管线
if (isp_init(priv) != 0) {
ALOGE("ISP init failed");
return -ENODEV;
}
// 4. 初始化元数据缓冲区池
priv->metadata_pool = metadata_pool_create(64);
if (!priv->metadata_pool) {
ALOGE("Metadata pool creation failed");
return -ENOMEM;
}
ALOGI("Camera %d initialized", priv->camera_id);
return 0;
}
最佳实践:
- 回调指针
callback_ops必须保存到私有上下文中,后续所有结果上报都依赖此指针。 - 不要在
initialize()中执行耗时超过 500ms 的操作,否则 Framework 会触发 ANR。 - 建议在
initialize()中完成所有硬件初始化,确保后续configure_streams()可以快速响应。
3.4 camera_info 填充与静态特性配置
camera_info 和静态特性元数据是 Framework 识别 Camera 能力的关键依据。错误的配置会导致上层应用无法正确使用 Camera 功能。
3.4.1 camera_info 结构
typedef struct camera_info {
int device_version; // 必须为 CAMERA_DEVICE_API_VERSION_3_5
const char* static_camera_characteristics; // 静态元数据
int resource_cost; // 资源开销等级 (0-100)
int conflicting_devices_length; // 冲突设备数量
const char** conflicting_devices; // 冲突设备列表
} camera_info_t;
3.4.2 静态特性元数据构建
静态特性元数据是 HAL3 移植中最繁琐的部分,涉及 200+ 个元数据标签。以下是关键标签的配置示例:
static int build_static_metadata(camera_private_t* priv,
camera_metadata_t** metadata) {
camera_metadata_t* m = allocate_camera_metadata(
STATIC_METADATA_ENTRY_COUNT,
STATIC_METADATA_DATA_SIZE);
// 1. 基础信息
int32_t facing = ANDROID_LENS_FACING_BACK;
add_camera_metadata_entry(m,
ANDROID_LENS_FACING, &facing, 1);
// 2. 传感器尺寸
int32_t sensor_size[] = {3264, 2448}; // 8MP
add_camera_metadata_entry(m,
ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
sensor_size, 2);
// 3. 支持的输出格式
int32_t formats[] = {
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
HAL_PIXEL_FORMAT_YCbCr_420_888,
HAL_PIXEL_FORMAT_BLOB
};
add_camera_metadata_entry(m,
ANDROID_SCALER_AVAILABLE_FORMATS,
formats, 3);
// 4. 支持的帧率范围
int32_t fps_ranges[] = {15, 30, 30, 30}; // [min1,max1,min2,max2]
add_camera_metadata_entry(m,
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
fps_ranges, 4);
// 5. 硬件能力级别
uint8_t hw_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
add_camera_metadata_entry(m,
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
&hw_level, 1);
*metadata = m;
return 0;
}
3.4.3 get_camera_info() 实现
static int hal3_get_camera_info(int camera_id,
struct camera_info* info) {
if (camera_id < 0 || camera_id >= MAX_CAMERAS)
return -ENODEV;
// 1. 填充设备版本
info->device_version = CAMERA_DEVICE_API_VERSION_3_5;
// 2. 构建静态特性元数据
camera_metadata_t* static_meta = NULL;
if (build_static_metadata(&g_priv[camera_id], &static_meta) != 0)
return -ENODEV;
info->static_camera_characteristics =
(const char*)static_meta;
// 3. 资源开销(默认值)
info->resource_cost = 50;
// 4. 冲突设备(无冲突)
info->conflicting_devices_length = 0;
info->conflicting_devices = NULL;
return 0;
}
关键指标:
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL决定了 Framework 启用的功能集:LIMITED(基础)、FULL(完整)、LEVEL_3(高级)。resource_cost影响多 Camera 并发策略,值越高越容易被抢占。- 静态元数据一旦构建完成,在整个 HAL 生命周期内不可修改。
3.5 初始化流程架构图
下图展示了 HAL3 初始化流程中三个阶段的调用关系与数据流向:
3.6 常见问题与调试技巧
| 问题现象 | 可能原因 | 排查方法 |
|---|---|---|
| CameraService 无法加载 HAL | open() 返回错误或 device_version 不匹配 |
检查 logcat 中 CameraService 标签的错误日志 |
| initialize() 回调后无响应 | callback_ops 指针未正确保存或被覆盖 |
在 notify() 调用处添加断点验证指针有效性 |
| 上层应用无法预览 | 静态特性中缺少关键格式或分辨率配置 | 使用 dumpsys media.camera 查看设备能力 |
| 多 Camera 并发冲突 | conflicting_devices 配置错误 |
检查 resource_cost 和冲突设备列表 |
调试建议:
- 在
open()和initialize()的关键路径添加ALOGI日志,便于追踪初始化进度。 - 使用
adb shell dumpsys media.camera -v验证静态特性元数据是否正确。 - 建议在
build_static_metadata()中增加元数据校验逻辑,确保所有必填标签都已配置。
3.7 初始化流程状态机
HAL3 设备初始化过程可以抽象为有限状态机,每个状态对应特定的操作集合:
移植总结: HAL3 初始化流程是 Camera HAL 移植的基石。成功的初始化需要确保:
open()正确创建设备实例并初始化硬件资源initialize()妥善保存回调指针并完成硬件管线初始化- 静态特性元数据完整、准确,覆盖所有 Framework 要求的必填标签
- 状态机转换严格遵循单向流程,任何阶段的失败都需要妥善清理已分配资源