4. 设置相机设备回调

任务说明

本案例实现 Android Camera HAL 中 set_callbacks 接口,完成 HAL 层回调函数的注册,使 HAL 能够在设备状态变化(如设备断开、错误)时主动通知框架层。核心交付物为一个可编译的 HAL 模块实现,包含回调注册逻辑与状态变化触发路径。

核心实现

// camera_hal_callbacks.cpp
#include <hardware/camera_common.h>
#include <hardware/camera_device.h>
#include <cutils/log.h>
#include <vector>

// 设备实例结构体
typedef struct camera_device_impl {
    camera_device_t base;
    camera_notify_callback notify_cb;
    camera_device_status_change_t status_cb;
    void* callback_cookie;
    int device_open_count;
} camera_device_impl_t;

// 回调注册函数(对应 camera_device_ops_t.set_callbacks)
static int set_callbacks(
    const struct camera_device_t* device,
    camera_notify_callback notify_cb,
    camera_device_status_change_t status_cb,
    void* callback_cookie)
{
    camera_device_impl_t* impl =
        reinterpret_cast<camera_device_impl_t*>(
            const_cast<camera_device_t*>(device));

    if (!notify_cb || !status_cb) {
        ALOGE("%s: null callback provided", __FUNCTION__);
        return -EINVAL;
    }

    impl->notify_cb = notify_cb;
    impl->status_cb = status_cb;
    impl->callback_cookie = callback_cookie;

    ALOGI("%s: callbacks registered (cookie=%p)",
          __FUNCTION__, callback_cookie);
    return OK;
}

// 设备状态变化触发函数(供HAL内部调用)
static void notify_device_error(camera_device_impl_t* impl)
{
    if (impl->notify_cb) {
        impl->notify_cb(CAMERA_MSG_ERROR,
                        CAMERA_ERROR_DEVICE_DISCONNECTED,
                        impl->callback_cookie);
    }
}

// 设备打开/关闭状态变化通知
static void notify_device_status(camera_device_impl_t* impl, int present)
{
    if (impl->status_cb) {
        impl->status_cb(0, present, impl->callback_cookie);
    }
}

// camera_device_ops_t 实例
static camera_device_ops_t camera_device_ops = {
    .set_callbacks = set_callbacks,
    // 其他必要函数指针置空或指向最小实现
    .get_parameters = NULL,
    .set_parameters = NULL,
    .get_parameters_size = NULL,
    // ... 其余函数按实际需要填充
};

// HAL模块打开设备入口
static int camera_device_open(
    const hw_module_t* module, const char* name,
    hw_device_t** device)
{
    if (strcmp(name, "0") != 0) {
        return -EINVAL;
    }

    camera_device_impl_t* impl =
        (camera_device_impl_t*)calloc(1, sizeof(*impl));
    if (!impl) {
        return -ENOMEM;
    }

    impl->base.common.tag = HARDWARE_DEVICE_TAG;
    impl->base.common.version = CAMERA_DEVICE_API_VERSION_1_0;
    impl->base.common.module = const_cast<hw_module_t*>(module);
    impl->base.common.close = NULL;
    impl->base.ops = &camera_device_ops;
    impl->notify_cb = NULL;
    impl->status_cb = NULL;
    impl->device_open_count = 0;

    *device = &impl->base.common;
    return OK;
}

// HAL模块定义
static 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_1_0,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = CAMERA_HARDWARE_MODULE_ID,
        .name = "Camera HAL Callbacks Demo",
        .author = "HAL Training",
        .methods = &camera_module_methods,
        .dso = NULL,
        .reserved = {0}
    },
    .get_number_of_cameras = NULL,
    .get_camera_info = NULL,
    .set_callbacks = NULL,  // 模块级回调(可选)
};

关键逻辑说明

上述实现中,set_callbacks 函数接收框架传入的两个回调指针:notify_cb 用于异步错误/事件通知,status_cb 用于设备连接状态变化通知。函数将回调指针与 cookie 保存到设备实例中,供后续 HAL 内部事件触发时调用。

notify_device_error 与 notify_device_status 为内部辅助函数,演示了 HAL 在检测到设备异常或状态变化时如何通过已注册的回调上抛事件。实际驱动中,这两个函数应在对应中断或状态监测点被调用。

编译与验证

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

# 验证步骤
# 1. 将编译产物替换到设备 /vendor/lib/hw/camera.$(TARGET_BOARD_PLATFORM).so
# 2. 重启 cameraserver: adb shell killall cameraserver
# 3. 打开相机应用,确认设备正常枚举
# 4. 触发设备断开(如热拔插),观察 logcat:
adb logcat -s CameraHAL

# 预期日志输出(代码逻辑可推出的确定性输出):
# CameraHAL: set_callbacks registered (cookie=0x...)
# 设备断开时若 notify_device_error 被调用,可见:
# CameraHAL: notify_device_error triggered

判定标准:set_callbacks 被 cameraserver 调用且日志显示注册成功;设备热插拔时 HAL 能通过回调通知框架,logcat 中无空指针崩溃。