4. Camera HAL 初始化流程:核心结构与静态信息填充

Camera HAL 的初始化是上层框架与底层硬件驱动建立通信的第一道关卡。本章深入剖析初始化阶段最核心的三个要素:camera_module_t 结构体、get_number_of_cameras() 的实现逻辑,以及 get_camera_info() 如何填充静态信息。理解这一流程,是后续进行 Stream 配置和 Camera 管道控制的基础。

4.1 camera_module_t:HAL 模块的“身份证”

camera_module_t 是 Android Camera HAL 中定义的标准模块结构体,它继承自 hw_module_t,是上层框架通过 hw_get_module() 加载 HAL 库后获取的第一个对象。该结构体不仅标识了 HAL 的版本和作者,更重要的是提供了两个关键的初始化接口指针。

成员 类型 说明
common hw_module_t 标准硬件模块结构体,包含 tag、module_api_version、hal_api_version、name、author、methods 等基础字段。
get_number_of_cameras 函数指针 返回设备上可用的 Camera 数量,是框架了解硬件拓扑的第一步。
get_camera_info 函数指针 填充 camera_info 结构体,提供指定 Camera 的静态能力信息。
set_callbacks 函数指针 (可选)注册框架回调,用于通知 HAL 模块状态变化。
get_vendor_tag_ops 函数指针 (可选)提供厂商自定义 metadata tag 的操作接口。
open_legacy 函数指针 (可选)打开旧版本 HAL 接口,用于兼容性场景。
set_torch_mode 函数指针 (可选)控制闪光灯手电筒模式。
init 函数指针 (可选)HAL 模块级初始化,在 hw_get_module 之后调用。
关键点: get_number_of_cameras 和 get_camera_info 是每个 Camera HAL 必须实现的两个接口,它们是框架获取设备能力信息的唯二入口。

4.2 get_number_of_cameras():探测 Camera 数量

该接口的实现通常非常直接,其核心任务是返回一个非负整数,代表系统中可用的 Camera 设备数量。这个数字决定了后续框架会调用多少次 get_camera_info()。

典型的实现方式包括:

  • 静态定义: 在 HAL 模块的 .cpp 文件中直接定义一个常量,例如 #define CAMERA_DEVICE_NUM 2,适用于硬件拓扑固定的嵌入式设备。
  • 动态扫描: 遍历 /dev/video* 节点或读取设备树(Device Tree)信息,动态统计可用的 Camera 设备数量,适用于模块化或可插拔 Camera 方案。
  • 配置文件驱动: 从 .cfg 或 .xml 配置文件中读取 Camera 列表,增加灵活性。
// 示例:基于静态定义的 get_number_of_cameras 实现
#include <hardware/camera_common.h>

#define BACK_CAMERA_ID  0
#define FRONT_CAMERA_ID 1
#define CAMERA_DEVICE_NUM 2

static int camera_device_open(const struct hw_module_t* module,
                              const char* id,
                              struct hw_device_t** device);

static int get_number_of_cameras(void) {
    // 对于固定硬件平台,直接返回常量
    ALOGI("get_number_of_cameras: returning %d", CAMERA_DEVICE_NUM);
    return CAMERA_DEVICE_NUM;
}

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 = "Example Camera HAL Module",
        .author = "Embedded System Team",
        .methods = &camera_module_methods,
    },
    .get_number_of_cameras = get_number_of_cameras,
    .get_camera_info = get_camera_info,
    .set_callbacks = NULL,
    .get_vendor_tag_ops = NULL,
    .open_legacy = NULL,
    .set_torch_mode = NULL,
    .init = NULL,
};
实践建议: 在 HAL 初始化阶段,建议在 get_number_of_cameras() 中添加日志输出,便于在调试初期快速确认 HAL 模块是否被正确加载以及 Camera 数量是否与预期一致。

4.3 get_camera_info():填充静态信息

get_camera_info() 负责填充 camera_info 结构体,该结构体包含了 Camera 设备的静态属性,这些属性在设备生命周期内不会改变。框架通过此接口了解每个 Camera 的朝向、安装位置、是否支持闪光灯等基本信息。

camera_info 结构体定义如下:

typedef struct camera_info {
    int                     device_version;     // HAL 设备版本号
    uint32_t                static_camera_characteristics_size; // metadata 大小
    camera_metadata_t*      static_camera_characteristics;      // 静态 metadata 指针
    int                     resource_cost;      // 资源开销(0-100)
    int                     conflicting_devices_length; // 冲突设备数量
    char**                  conflicting_devices; // 冲突设备 ID 列表
} camera_info_t;

填充 static_camera_characteristics 是 get_camera_info() 中最复杂、最核心的部分。它需要构建一个包含大量 Camera 能力信息的 metadata 包,例如:

  • 基础信息: ANDROID_LENS_FACING(前置/后置/外接)、ANDROID_SENSOR_ORIENTATION(图像方向)。
  • 分辨率支持: ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS(支持的输出格式和尺寸列表)。
  • 帧率范围: ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES。
  • 硬件能力: ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL(LIMITED / FULL / LEVEL_3)。
  • 同步能力: ANDROID_SYNC_MAX_LATENCY。
常见陷阱: static_camera_characteristics 的构建必须严格遵循 Android CDD(兼容性定义文档)的要求。遗漏关键 tag 或填充错误的值,可能导致 Camera 服务无法正常启动或上层应用崩溃。建议使用 camera_metadata 库提供的 API(如 allocate_camera_metadata()、add_camera_metadata_entry())进行构建,避免手动操作内存。

4.4 初始化流程全景图

下面的 SVG 图展示了从框架加载 HAL 模块到获取所有 Camera 静态信息的完整流程。

Camera HAL 初始化流程 CameraService hw_get_module(CAMERA_HARDWARE_MODULE_ID) 获取 camera_module_t 指针 get_number_of_cameras() → N for (i=0; i<N; i++) get_camera_info(i, &info) 填充 camera_info 说明:初始化完成后,CameraService 持有所有 Camera 的静态信息,准备进入设备打开和 Stream 配置阶段。

4.5 静态信息填充的关键字段对比

在 get_camera_info() 中,static_camera_characteristics 的构建质量直接决定了上层应用的能力。以下表格对比了三个关键字段的典型值及其影响:

Metadata Tag 典型值 对上层的影响
ANDROID_LENS_FACING LENS_FACING_BACK / LENS_FACING_FRONT 决定 Camera 应用默认打开前置还是后置 Camera;影响 UI 镜像逻辑。
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS 例如:{HAL_PIXEL_FORMAT_YCbCr_420_888, 1920, 1080, ...} 限制应用可以请求的预览/拍照/录像分辨率;配置错误会导致 Stream 创建失败。
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL INFO_SUPPORTED_HARDWARE_LEVEL_FULL 定义 Camera 设备的能力等级(LIMITED/FULL/LEVEL_3);影响是否支持 RAW、YUV reprocessing 等高级功能。
核心要点: get_camera_info() 的成功执行标志着 HAL 初始化阶段的完成。此时,框架已经掌握了所有 Camera 设备的静态能力,为后续的 open() 调用和 Stream 配置做好了准备。任何静态信息的错误或遗漏,都会在后续的配置阶段暴露出来,导致难以调试的问题。