2. 实现camera_device_t的open接口
任务说明
本案例目标是在Android Camera HAL层实现camera_device_t的open接口。该接口由Camera Service通过HAL_MODULE_INFO_SYM的open方法调用,用于打开指定摄像头设备,创建设备实例,初始化camera_device_t结构体,并设置ops回调函数指针。
核心实现
// camera_hal.cpp
#include <hardware/hardware.h>
#include <hardware/camera.h>
#include <cstdlib>
#include <cstring>
// 前向声明ops回调
static int camera_device_close(struct hw_device_t* device);
// 设备实例结构体
typedef struct camera_device_impl {
camera_device_t base; // 必须为第一个成员
int camera_id;
// 可扩展私有数据
} camera_device_impl_t;
// ops回调函数实现
static int camera_set_preview_window(struct camera_device* dev,
struct preview_stream_ops* window) {
// 实际项目中在此设置预览窗口
return 0;
}
static void camera_set_callbacks(struct camera_device* dev,
camera_notify_callback notify_cb,
camera_data_callback data_cb,
camera_data_timestamp_callback data_cb_timestamp,
camera_request_memory get_memory,
void* user) {
// 实际项目中在此保存回调
}
// 完整ops结构体定义
static camera_device_ops_t camera_ops = {
.set_preview_window = camera_set_preview_window,
.set_callbacks = camera_set_callbacks,
// ... 其他必要回调按需实现
};
// open接口实现
static int camera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device) {
if (module == NULL || name == NULL || device == NULL) {
return -EINVAL;
}
// 解析摄像头ID
int camera_id = atoi(name);
if (camera_id < 0 || camera_id >= CAMERA_MODULE_MAX_CAMERAS) {
return -ENODEV;
}
// 创建设备实例
camera_device_impl_t* dev_impl = (camera_device_impl_t*)calloc(1,
sizeof(camera_device_impl_t));
if (dev_impl == NULL) {
return -ENOMEM;
}
// 初始化camera_device_t结构体
dev_impl->base.common.tag = HARDWARE_DEVICE_TAG;
dev_impl->base.common.version = CAMERA_DEVICE_API_VERSION_1_0;
dev_impl->base.common.module = (hw_module_t*)module;
dev_impl->base.common.close = camera_device_close;
dev_impl->base.ops = &camera_ops;
dev_impl->camera_id = camera_id;
// 将实例返回给调用者
*device = &dev_impl->base.common;
return 0;
}
// close接口实现
static int camera_device_close(struct hw_device_t* device) {
if (device == NULL) {
return -EINVAL;
}
camera_device_impl_t* dev_impl = (camera_device_impl_t*)device;
free(dev_impl);
return 0;
}
// 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,
.version_major = 1,
.version_minor = 0,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "Camera HAL Module",
.author = "Your Company",
.methods = &camera_module_methods,
},
.get_number_of_cameras = NULL, // 由实际实现填充
.get_camera_info = NULL, // 由实际实现填充
};
关键实现说明
camera_device_open函数接收三个参数:module指向当前HAL模块,name为摄像头标识字符串(如"0"、"1"),device为输出参数。函数内部首先校验参数有效性,然后通过atoi解析摄像头ID并检查范围。使用calloc分配设备实例内存并清零,确保所有字段初始化为安全值。初始化camera_device_t时,必须正确设置tag为HARDWARE_DEVICE_TAG,version为对应API版本,module指向所属模块,close指向关闭函数,ops指向已实现的回调集合。最后通过*device返回设备句柄。
编译与验证
在Android源码树中,将上述代码保存为camera_hal.cpp,并创建Android.bp构建文件:
cc_library_shared {
name: "camera.primary",
srcs: ["camera_hal.cpp"],
shared_libs: ["libhardware", "libcamera_metadata"],
vendor: true,
proprietary: true,
}
编译产物为camera.primary.so,需放置到/vendor/lib64/hw/目录。验证方法:
- 在系统启动日志中搜索
camera.primary加载记录,确认模块被成功加载; - 使用
dumpsys media.camera检查摄像头设备列表,确认设备枚举正常; - 调用
open后检查返回值,若返回0且device指针非空,且device->ops指向有效回调集合,则判定通过。
判定标准:open函数能正确创建设备实例,初始化所有必要字段,且close能正确释放资源,无内存泄漏。