1. Camera HAL架构概述:Android Camera HAL整体架构、HAL3 vs HAL2区别、HAL与V4L2的关系
好,咱们直接进入正题。这一章是地基,地基打不牢,后面适配Sensor的时候你会哭的。我见过太多人上来就撸代码,结果连HAL和V4L2的关系都搞不清,调试的时候一脸懵。
先说说Android Camera HAL的整体架构。说白了,它就是连接上层Framework和底层硬件的一座桥。上层App调用Camera API,Framework层通过HIDL或AIDL接口跟HAL通信,HAL再往下操作具体的Sensor、ISP、V4L2设备。
核心链路:
App → Framework → CameraService → HAL → V4L2/硬件驱动 → Sensor
我个人习惯把HAL看作一个「翻译官」。上层说「我要拍一张1080P的照片」,HAL得把它翻译成「打开V4L2设备节点,设置format为YUYV,分辨率1920x1080,然后开始streaming」。嗯,就是这么回事。
1.1 HAL3 vs HAL2:到底差在哪?
这个问题面试常考,实际开发中也绕不开。HAL2是Android 4.4时代的产物,HAL3从Android 5.0开始引入。你想想看,现在都Android 14了,谁还用HAL2?但有些老平台、老Sensor模组,还真就只支持HAL2。
| 对比项 | HAL2 | HAL3 |
|---|---|---|
| 架构模式 | 同步、阻塞 | 异步、Pipeline |
| Buffer管理 | HAL自己管 | Framework统一管理 |
| 3A控制 | HAL内部实现 | Framework可参与 |
| 多路流支持 | 有限 | 原生支持 |
| 性能 | 低 | 高 |
我在项目中遇到过一件事:一个客户非要在一款老RK3288平台上用HAL3,结果Sensor驱动只支持V4L2的旧版API,折腾了两周才跑通。后来我建议他们直接上HAL2,三天搞定。所以啊,不是越新越好,得看平台和Sensor的实际情况。
我的建议:新项目一律用HAL3。但如果你的Sensor驱动只支持V4L2的旧版ioctl,或者平台性能太弱(比如单核A7),老老实实用HAL2吧。
1.2 HAL与V4L2的关系
这个坑很多人踩过。V4L2是Linux内核的Video for Linux 2,它负责跟硬件打交道。HAL是Android上层,它通过V4L2来操作Camera设备。
说白了,HAL是「指挥官」,V4L2是「士兵」。HAL说「我要开始预览了」,V4L2就去打开设备、设置格式、申请buffer、入队出队。
我曾经在一个项目里,HAL层死活拿不到图像数据。查了两天,最后发现是V4L2的buffer队列没处理好——用户空间的mmap地址错了。嗯,这种问题最坑,因为HAL层报错信息很模糊,只说「buffer timeout」。
注意:V4L2的ioctl调用是阻塞的,如果你在HAL的主线程里直接调用,整个Camera服务都会卡死。一定要用单独的线程池来处理V4L2操作。
这里给个简单的V4L2打开设备的代码片段,大家感受一下:
// 打开V4L2设备
int fd = open("/dev/video0", O_RDWR);
if (fd < 0) {
// 我习惯在这里打log,不然出问题都不知道设备节点对不对
ALOGE("Failed to open /dev/video0: %s", strerror(errno));
return -1;
}
// 查询设备能力
struct v4l2_capability cap;
ioctl(fd, VIDIOC_QUERYCAP, &cap);
// 检查是不是capture设备
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
ALOGE("Not a capture device");
close(fd);
return -1;
}
你想想看,如果HAL和V4L2的接口没对齐,比如HAL要求NV12格式,但V4L2只支持YUYV,那出来的图像颜色就是花的。我刚开始做适配时,就因为这个被坑过一次,图像偏绿,还以为是Sensor坏了。
1.3 整体架构的层次感
咱们把整个Camera HAL架构从上到下捋一遍:
- Application层:调用Camera2 API,比如openCamera、createCaptureSession
- Framework层:CameraService管理多个Camera设备,通过HIDL/AIDL跟HAL通信
- HAL层:实现ICameraDevice、ICameraDeviceSession等接口,处理request、返回result
- V4L2层:操作具体的Sensor驱动,完成图像采集
- 硬件层:Sensor、ISP、MIPI接口等
我个人习惯在HAL层和V4L2层之间再加一个抽象层,叫「CameraDeviceAdapter」。这样做的好处是,换Sensor的时候只需要改这个Adapter,不用动HAL的核心逻辑。嗯,这个技巧后面章节会详细讲。
避坑指南:我曾经在一个项目里,HAL直接调用V4L2的ioctl,没有做任何封装。结果换了一个Sensor,V4L2的格式、分辨率、帧率全变了,HAL代码改得面目全非。从那以后,我坚持在HAL和V4L2之间加一层抽象。
好了,这一章就到这里。记住一句话:HAL是桥梁,V4L2是工具,搞清楚它们的关系,后面适配Sensor才能游刃有余。下一章咱们聊聊如何从零开始搭建一个HAL3的框架。