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架构从上到下捋一遍:

  1. Application层:调用Camera2 API,比如openCamera、createCaptureSession
  2. Framework层:CameraService管理多个Camera设备,通过HIDL/AIDL跟HAL通信
  3. HAL层:实现ICameraDevice、ICameraDeviceSession等接口,处理request、返回result
  4. V4L2层:操作具体的Sensor驱动,完成图像采集
  5. 硬件层:Sensor、ISP、MIPI接口等

我个人习惯在HAL层和V4L2层之间再加一个抽象层,叫「CameraDeviceAdapter」。这样做的好处是,换Sensor的时候只需要改这个Adapter,不用动HAL的核心逻辑。嗯,这个技巧后面章节会详细讲。

避坑指南:我曾经在一个项目里,HAL直接调用V4L2的ioctl,没有做任何封装。结果换了一个Sensor,V4L2的格式、分辨率、帧率全变了,HAL代码改得面目全非。从那以后,我坚持在HAL和V4L2之间加一层抽象。

好了,这一章就到这里。记住一句话:HAL是桥梁,V4L2是工具,搞清楚它们的关系,后面适配Sensor才能游刃有余。下一章咱们聊聊如何从零开始搭建一个HAL3的框架。