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 中无空指针崩溃。