3. 获取相机信息

任务说明

本案例实现 Android Camera HAL 中的 get_camera_info 回调,用于向 Camera Service 上报相机设备的基本信息。需要填充 camera_info_t 结构体中的设备 ID、朝向、资源成本等字段,并确保返回的相机数量与设备列表一致。

核心代码实现

// camera_hal.cpp
#include <hardware/camera_common.h>
#include <hardware/camera.h>
#include <cutils/log.h>
#include <vector>
#include <string>

#define CAMERA_DEVICE_ID_0 "0"
#define CAMERA_DEVICE_ID_1 "1"

// 设备列表:本 HAL 暴露两个摄像头
static std::vector<std::string> g_device_list = {
    CAMERA_DEVICE_ID_0,
    CAMERA_DEVICE_ID_1
};

// 静态相机信息表(实际项目中可从配置或驱动读取)
static camera_info_t g_camera_info[] = {
    {
        .device_id = const_cast<char*>(CAMERA_DEVICE_ID_0),
        .device_version = CAMERA_DEVICE_API_VERSION_1_0,
        .facing = CAMERA_FACING_BACK,
        .orientation = 90,
        .resource_cost = 100,
        .conflicting_devices = nullptr,
        .conflicting_devices_length = 0,
    },
    {
        .device_id = const_cast<char*>(CAMERA_DEVICE_ID_1),
        .device_version = CAMERA_DEVICE_API_VERSION_1_0,
        .facing = CAMERA_FACING_FRONT,
        .orientation = 270,
        .resource_cost = 100,
        .conflicting_devices = nullptr,
        .conflicting_devices_length = 0,
    }
};

// HAL 模块回调:返回相机数量
static int get_number_of_cameras(void) {
    return static_cast<int>(g_device_list.size());
}

// HAL 模块回调:填充相机信息
static int get_camera_info(int camera_id, struct camera_info *info) {
    if (camera_id < 0 || camera_id >= static_cast<int>(g_device_list.size())) {
        ALOGE("Invalid camera_id: %d", camera_id);
        return -EINVAL;
    }
    if (info == nullptr) {
        ALOGE("info is null");
        return -EINVAL;
    }

    *info = g_camera_info[camera_id];
    ALOGI("get_camera_info: id=%d, device_id=%s, facing=%d, orientation=%d",
          camera_id, info->device_id, info->facing, info->orientation);
    return 0;
}

// 模块定义
static hw_module_methods_t g_module_methods = {
    .open = [](const struct hw_module_t* module, const char* id,
               struct hw_device_t** device) -> int {
        // 本案例聚焦 get_camera_info,open 实现从略
        return -ENOSYS;
    }
};

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 = "Demo Camera HAL",
        .author = "Camera HAL 100 Cases",
        .methods = &g_module_methods,
        .dso = nullptr,
        .reserved = {0},
    },
    .get_number_of_cameras = get_number_of_cameras,
    .get_camera_info = get_camera_info,
    .set_callbacks = nullptr,
    .get_vendor_tag_ops = nullptr,
    .open_legacy = nullptr,
    .set_torch_mode = nullptr,
    .init = nullptr,
    .reserved = {0},
};

关键实现说明

get_camera_info 回调接收两个参数:camera_id 表示查询的相机序号,info 为输出参数。实现中先做边界检查,再通过结构体赋值将预定义的 g_camera_info 内容拷贝到输出参数。设备 ID 使用字符串 "0" 和 "1",与 g_device_list 一一对应。朝向字段分别设置为后置(CAMERA_FACING_BACK)和前置(CAMERA_FACING_FRONT),orientation 表示图像顺时针旋转角度。resource_cost 设为 100 表示满资源占用,conflicting_devices 为空表示无互斥设备。

编译与验证

# 编译(Android 源码树内)
mmm hardware/libhardware/modules/camera/

# 或使用 ndk-build 独立编译(需适配 Android.mk)
# 验证方式:编写单元测试调用 get_camera_info
# 1. 调用 get_number_of_cameras() 应返回 2
# 2. 对 camera_id=0 调用 get_camera_info,检查:
#    - device_id == "0"
#    - facing == CAMERA_FACING_BACK
#    - orientation == 90
#    - resource_cost == 100
# 3. 对 camera_id=1 调用 get_camera_info,检查:
#    - device_id == "1"
#    - facing == CAMERA_FACING_FRONT
#    - orientation == 270
# 4. 对 camera_id=2 调用应返回 -EINVAL
# 5. 传入 nullptr 作为 info 应返回 -EINVAL

判定标准:上述 5 项检查全部通过,且 get_camera_info 返回 0 时 info 结构体各字段与预期一致,即视为实现正确。本案例代码可直接编译进 HAL 模块,通过 Camera Service 的 ICameraService::getCameraInfo 路径进行端到端验证。