4. Camera HAL3 初始化流程:open()、init()、configure_streams()、construct_default_request_settings()
Camera HAL3 的初始化流程是相机应用从启动到能够正常预览和拍照的关键路径。该流程涉及 Framework 层与 HAL 层之间的多次双向交互,核心接口包括 open()、init()、configure_streams() 和 construct_default_request_settings()。理解这些接口的调用顺序、参数含义和实现要点,是开发稳定、高性能相机 HAL 的基础。
4.1 初始化流程总览
下图展示了 Camera HAL3 初始化过程中 Framework 与 HAL 之间的主要交互节点和调用顺序:
4.2 open():打开相机设备
open() 是 HAL3 初始化流程的入口点,由 camera_module_t 结构体中的 open() 函数指针实现。Framework 通过该接口获取指定 cameraId 的设备句柄。
4.2.1 接口定义
typedef struct camera_module {
// ... 其他成员
int (*open)(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device);
} camera_module_t;
4.2.2 实现要点
- 参数校验:检查
id是否合法,确保 cameraId 在支持的范围内 - 设备分配:为
camera3_device_t分配内存,并填充common结构体中的版本号、模块句柄、关闭函数等字段 - ops 注册:将
camera3_ops_t中的函数指针(包括initialize()、configure_streams()等)注册到设备结构体中 - 硬件初始化:完成传感器、电源管理等底层硬件的上电和复位操作
- 互斥保护:防止同一 cameraId 被重复打开,需加锁保护
4.3 init():初始化相机管道
init() 对应 camera3_ops_t 中的 initialize() 函数。该接口在 open() 之后被调用,用于建立 Framework 与 HAL 之间的回调通道,并完成相机管道的初始化。
4.3.1 接口定义
typedef struct camera3_callback_ops {
void (*notify)(const camera3_notify_msg_t *msg);
void (*process_capture_result)(const camera3_capture_result_t *result);
void (*process_capture_result_async)(
const camera3_capture_result_t *result);
} camera3_callback_ops_t;
int (*initialize)(const struct camera3_device *device,
const camera3_callback_ops_t *callback_ops);
4.3.2 回调注册
callback_ops 是 Framework 向 HAL 注册的回调函数集合,HAL 通过它们将异步事件和结果返回给 Framework:
| 回调函数 | 触发时机 | 用途 |
|---|---|---|
notify() |
快门事件、错误事件 | 通知 Framework 快门开始、曝光完成或设备错误 |
process_capture_result() |
每一帧捕获完成 | 返回 metadata 和图像缓冲区给 Framework |
process_capture_result_async() |
部分结果可用时 | 支持 partial result,减少首帧延迟 |
4.3.3 初始化工作
- 保存回调指针:将
callback_ops保存到 HAL 内部,用于后续上报事件和结果 - 传感器校准:加载 AWB、AE、AF 算法的校准参数
- ISP 初始化:配置图像信号处理器的初始状态
- 内存池预分配:为后续的 request 和 result 分配初始内存
- 状态机迁移:将设备状态从
OPENED迁移到INITIALIZED
4.4 configure_streams():配置数据流
configure_streams() 是 HAL3 初始化流程中最关键的接口之一。应用层通过该接口告知 HAL 需要哪些数据流(预览流、拍照流、视频流等),HAL 据此配置 ISP、传感器输出格式和缓冲区分配策略。
4.4.1 接口定义
int (*configure_streams)(const struct camera3_device *device,
camera3_stream_configuration_t *stream_list);
4.4.2 数据结构
typedef struct camera3_stream_configuration {
uint32_t num_streams; // 流数量
camera3_stream_t **streams; // 流数组指针
uint32_t operation_mode; // 操作模式
const camera_metadata_t *session_parameters; // 会话参数
} camera3_stream_configuration_t;
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width; // 宽度
uint32_t height; // 高度
int format; // 像素格式(HAL_PIXEL_FORMAT_xxx)
uint32_t usage; // 使用标志(GRALLOC_USAGE_xxx)
uint32_t max_buffers; // HAL 请求的最大缓冲区数(输出参数)
void *priv; // HAL 私有数据
uint32_t data_space; // 色彩空间
int rotation; // 旋转角度
int crop_rect[4]; // 裁剪矩形
} camera3_stream_t;
4.4.3 配置流程
- 校验流参数:检查 width、height、format 是否在传感器支持的范围内
- 计算 max_buffers:根据流类型和硬件能力,设置每个流所需的缓冲区数量
- 配置 ISP 管线:根据所有流的组合,重新配置 ISP 的缩放、裁剪、格式转换模块
- 分配图形缓冲区:通过 Gralloc 分配输出流所需的缓冲区
- 更新传感器模式:根据最大分辨率流设置传感器的输出尺寸和帧率
- 状态机迁移:将设备状态迁移到
CONFIGURED
• 缓存 ISP 配置参数,避免重复计算
• 使用预分配的缓冲区池,减少动态分配开销
• 支持增量配置,当流参数未变化时跳过重新配置
4.5 construct_default_request_settings():获取默认请求模板
construct_default_request_settings() 是 HAL3 初始化流程的最后一步。Framework 通过该接口获取指定模板类型的默认 metadata,用于构造后续的 CaptureRequest。
4.5.1 接口定义
const camera_metadata_t* (*construct_default_request_settings)(
const struct camera3_device *device,
int type);
4.5.2 模板类型
| 模板类型 | 值 | 典型应用场景 |
|---|---|---|
CAMERA3_TEMPLATE_PREVIEW |
1 | 预览模式,优先保证帧率 |
CAMERA3_TEMPLATE_STILL_CAPTURE |
2 | 拍照模式,优先保证图像质量 |
CAMERA3_TEMPLATE_VIDEO_RECORD |
3 | 视频录制,平衡帧率和质量 |
CAMERA3_TEMPLATE_VIDEO_SNAPSHOT |
4 | 视频录制中的抓拍 |
CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG |
5 | 零快门延迟模式 |
CAMERA3_TEMPLATE_MANUAL |
6 | 手动模式,所有参数由应用控制 |
4.5.3 实现要点
- 静态 metadata 填充:返回的 metadata 必须包含所有静态能力标签(如
ANDROID_SENSOR_INFO_*、ANDROID_SCALER_AVAILABLE_*等) - 默认参数设置:根据模板类型设置合理的默认值,如 AE 模式、AWB 模式、AF 模式、帧率范围等
- 内存管理:返回的 metadata 由 HAL 管理生命周期,Framework 只读不释放。HAL 需要保证该指针在设备关闭前始终有效
- 线程安全:该接口可能被多个线程同时调用,需要加锁保护
ANDROID_CONTROL_AE_MODE),导致 Framework 构造 CaptureRequest 时失败。建议使用 CTS 的 android.hardware.camera2.cts.CameraMetadataTest 验证返回的 metadata 完整性。
4.6 初始化流程状态机
HAL3 设备在整个生命周期中维护一个状态机,初始化流程对应从 CLOSED 到 CONFIGURED 的状态迁移:
4.7 初始化流程常见问题与调试方法
| 问题现象 | 可能原因 | 调试建议 |
|---|---|---|
| open() 返回 -ENODEV | cameraId 不存在或硬件故障 | 检查 cameraId 范围,确认硬件上电正常 |
| init() 返回 -EINVAL | callback_ops 为 NULL 或设备状态错误 | 确认 open() 已成功,检查回调指针有效性 |
| configure_streams() 返回 -EINVAL | 流参数超出传感器能力范围 | 对比 stream 参数与静态 metadata 中的可用配置 |
| construct_default_request_settings() 返回 NULL | 模板类型不支持或 metadata 构造失败 | 确认模板类型在支持范围内,检查内存分配 |
| 首帧延迟过高 | configure_streams() 中执行了过多耗时操作 | 使用 systrace 分析耗时分布,优化 ISP 配置流程 |
adb shell dumpsys media.camera 查看相机服务的状态信息,包括每个 cameraId 的当前状态、配置的流信息、缓冲区使用情况等。结合 logcat -s Camera3 可以追踪 Framework 层的初始化日志。
4.8 本章小结
Camera HAL3 的初始化流程是 Framework 与 HAL 之间建立通信通道、配置数据路径的关键阶段。开发者需要深入理解以下要点:
- open() 负责设备句柄的创建和底层硬件的上电
- init() 建立回调通道,完成算法和管道的初始化
- configure_streams() 根据应用需求配置 ISP 和缓冲区分配
- construct_default_request_settings() 提供默认的请求模板,是后续 CaptureRequest 的基础
- 状态机管理是保证初始化流程正确性的核心,任何步骤失败都需要正确的回退处理
在实际开发中,建议使用 CTS 的 android.hardware.camera2.cts.CameraTest 和 CameraMetadataTest 验证初始化流程的正确性和完整性,确保 HAL 实现符合 Android 兼容性定义文档(CDD)的要求。