1. 初始化Camera HAL模块

初始化Camera HAL模块 学习卡片

任务说明

本案例目标是在Android Camera HAL层实现模块初始化入口,完成HAL模块结构体定义、open函数注册及基础能力查询,使上层Camera Service能够通过标准HAL接口成功加载并打开相机模块。最终交付一个可编译的HAL模块骨架,支持查询相机设备数量与基本信息。

HAL模块结构定义

// camera_hal_module.c
#include <hardware/hardware.h>
#include <hardware/camera_common.h>
#include <cutils/log.h>

#define CAMERA_MODULE_API_VERSION CAMERA_MODULE_API_VERSION_2_4
#define CAMERA_DEVICE_API_VERSION CAMERA_DEVICE_API_VERSION_2_4

static int camera_device_count(const struct camera_module *module);
static int camera_get_vendor_tag_ops(vendor_tag_ops_t *ops);
static int camera_open_legacy(const struct hw_module_t *module,
                              const char *id, uint32_t halVersion,
                              struct hw_device_t **device);
static int camera_set_callbacks(const struct camera_module *module,
                                camera_module_callbacks_t *callbacks);
static int camera_get_physical_camera_info(const struct camera_module *module,
                                           int camera_id,
                                           camera_metadata_t **info);

static struct hw_module_methods_t camera_module_methods = {
    .open = camera_module_open
};

struct camera_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag           = HARDWARE_MODULE_TAG,
        .module_api_version = CAMERA_MODULE_API_VERSION,
        .hal_api_version    = HARDWARE_HAL_API_VERSION,
        .id            = CAMERA_HARDWARE_MODULE_ID,
        .name          = "Demo Camera HAL Module",
        .author        = "Camera HAL Team",
        .methods       = &camera_module_methods,
        .dso           = NULL,
        .reserved      = {0}
    },
    .get_number_of_cameras = camera_device_count,
    .get_camera_info       = camera_get_camera_info,
    .set_callbacks         = camera_set_callbacks,
    .get_vendor_tag_ops    = camera_get_vendor_tag_ops,
    .open_legacy           = camera_open_legacy,
    .set_torch_mode        = NULL,
    .init                  = NULL,
    .reserved              = {0}
};

核心函数实现

static int camera_device_count(const struct camera_module *module) {
    (void)module;
    // 当前仅模拟1个后置摄像头
    return 1;
}

static int camera_get_camera_info(const struct camera_module *module,
                                  int camera_id,
                                  struct camera_info *info) {
    (void)module;
    if (camera_id < 0 || camera_id >= camera_device_count(NULL)) {
        ALOGE("Invalid camera id: %d", camera_id);
        return -ENODEV;
    }

    // 静态配置相机基本信息
    info->device_version = CAMERA_DEVICE_API_VERSION;
    info->device_type    = CAMERA_DEVICE_TYPE_HAL;
    info->resource_cost  = 100;
    info->conflicting_devices = NULL;
    info->conflicting_devices_length = 0;

    // 构造静态相机特征(仅包含必要字段)
    static camera_metadata_t *static_metadata = NULL;
    if (static_metadata == NULL) {
        int32_t facing = CAMERA_FACING_BACK;
        uint8_t orientation = 90;
        static_metadata = allocate_camera_metadata(8, 16);
        add_camera_metadata_entry(static_metadata,
            ANDROID_LENS_FACING, &facing, 1);
        add_camera_metadata_entry(static_metadata,
            ANDROID_SENSOR_ORIENTATION, &orientation, 1);
    }
    info->static_camera_characteristics = static_metadata;
    return 0;
}

static int camera_module_open(const struct hw_module_t *module,
                              const char *id,
                              struct hw_device_t **device) {
    (void)module;
    (void)id;
    // 设备打开逻辑在案例2中实现,此处仅返回占位
    *device = NULL;
    ALOGI("camera_module_open called for id: %s", id);
    return -ENODEV;
}

static int camera_set_callbacks(const struct camera_module *module,
                                camera_module_callbacks_t *callbacks) {
    (void)module;
    (void)callbacks;
    return OK;
}

static int camera_get_vendor_tag_ops(vendor_tag_ops_t *ops) {
    (void)ops;
    return OK;
}

static int camera_open_legacy(const struct hw_module_t *module,
                              const char *id, uint32_t halVersion,
                              struct hw_device_t **device) {
    (void)module; (void)id; (void)halVersion; (void)device;
    return -ENOSYS;
}

static int camera_get_physical_camera_info(const struct camera_module *module,
                                           int camera_id,
                                           camera_metadata_t **info) {
    (void)module; (void)camera_id; (void)info;
    return -ENOSYS;
}

Android.bp构建配置

// Android.bp
cc_library_shared {
    name: "camera.demo.hal",
    vendor: true,
    relative_install_path: "hw",
    srcs: ["camera_hal_module.c"],
    shared_libs: [
        "libhardware",
        "libcamera_metadata",
        "libcutils",
        "liblog"
    ],
    header_libs: [
        "libhardware_headers",
        "libcamera_metadata_headers"
    ],
    cflags: ["-Wall", "-Werror"],
    proprietary: true,
}

编译与验证

在Android源码树中执行以下命令完成编译与验证:

# 编译HAL模块
source build/envsetup.sh
lunch <target>
m camera.demo.hal

# 验证模块加载(adb shell)
adb push ${OUT}/vendor/lib64/hw/camera.demo.hal.so /vendor/lib64/hw/
adb shell chmod 644 /vendor/lib64/hw/camera.demo.hal.so
adb shell "cat /vendor/lib64/hw/camera.demo.hal.so | grep -c 'HAL_MODULE_INFO_SYM'"
Camera HAL 模块初始化调用时序 Camera Service HAL_MODULE_INFO_SYM Camera Device hw_get_module("camera") 返回 camera_module_t* get_number_of_cameras() 返回 camera_count = 1 get_camera_info(0, &info) 返回 static_camera_characteristics open("0") → 案例2实现 HAL_MODULE_INFO_SYM 必须位于 .so 固定导出符号位置

验证判定标准

  • 编译通过:执行m camera.demo.hal无错误,生成camera.demo.hal.so文件;
  • 符号检查:使用readelf -s camera.demo.hal.so | grep HAL_MODULE_INFO_SYM确认符号存在且为GLOBAL类型;
  • 加载测试:在设备端执行adb shell "cameraserver",日志中无Failed to load HAL module错误,且通过adb shell dumpsys media.camera可看到相机数量为1;
  • 信息查询:调用getCameraInfo(0)返回的facing为BACK,orientation为90,与代码配置一致。