1. Camera HAL概述:HAL在Android相机架构中的位置、HAL的主要职责、HAL版本演进(HAL1 vs HAL3)

各位同学,咱们今天正式开讲Camera HAL。说实话,我做了这么多年嵌入式,每次带新人入门,第一件事就是让他们搞明白HAL到底是个什么角色。你想想看,一个手机上有那么多摄像头,从按下快门到出照片,中间经过了多少层软件?HAL就是那个承上启下的关键节点。

1.1 HAL在Android相机架构中的位置

先看一张宏观的图(我这里用文字描述一下):

应用层 (Camera App)
    ↓
Framework层 (Camera API2 / CameraService)
    ↓
HAL层 (Camera HAL)
    ↓
Kernel层 (V4L2 / 传感器驱动)
    ↓
硬件层 (Sensor / ISP / 镜头)

HAL夹在Framework和Kernel之间。说白了,它就是个翻译官。Framework说「我要拍照」,HAL得把这个指令翻译成硬件能听懂的话。反过来,硬件采集到的原始数据,也得通过HAL包装成Framework能处理的格式。

我个人习惯把HAL比作「中间人」。它不直接操作寄存器,也不直接跟App打交道。但它决定了整个相机系统的上限。我在项目中遇到过好几次,明明硬件性能很强,但HAL写得烂,导致拍照卡顿、预览延迟。嗯,这里要注意,HAL的代码质量直接决定了用户体验。

1.2 HAL的主要职责

HAL到底干哪些活?我总结了一下,核心职责有这么几块:

  • 设备管理:打开/关闭摄像头设备,管理多个摄像头(比如前后摄、广角、长焦)。
  • 流配置:App要什么分辨率的预览流、拍照流、视频流,HAL得协调好。
  • 缓冲区管理:分配、填充、回收图像缓冲区。这块最容易出内存泄漏。
  • 3A控制:自动对焦(AF)、自动曝光(AE)、自动白平衡(AWB)。说白了就是让画面清晰、亮度合适、颜色自然。
  • 元数据传递:把硬件的状态信息(比如当前对焦位置、曝光时间)打包成元数据,传给Framework。
  • 错误处理:硬件出问题了(比如传感器挂了),HAL得优雅地通知上层,而不是直接崩掉。

重点:HAL不是简单的「数据搬运工」。它要做大量的策略决策。比如,当App同时请求预览流和拍照流时,HAL得决定怎么分配ISP带宽、怎么调度DMA传输。这些决策直接影响帧率和延迟。

1.3 HAL版本演进:HAL1 vs HAL3

Android相机HAL经历了两个主要版本。我刚开始做的时候还是HAL1时代,后来HAL3出来,整个架构都变了。咱们来对比一下。

HAL1:简单但僵化

HAL1的设计思路是「一条流水线」。App发出请求,HAL按部就班地执行:预览→拍照→编码。流程是固定的,你很难插进去自定义操作。

// HAL1的典型调用流程
camera_device->ops->start_preview(dev);
camera_device->ops->take_picture(dev);
camera_device->ops->stop_preview(dev);

你看,每个操作都是同步的、阻塞的。App调了take_picture,就得等HAL把整张照片处理完才能干别的事。这在单摄时代还行,但到了多摄、高帧率、HDR这些场景,HAL1就完全不够用了。

避坑指南:我曾经在一个项目里用HAL1做双摄虚化,结果发现根本没法同时控制两个传感器的曝光参数。因为HAL1的接口设计就是「一次只能处理一个请求」。最后只能硬着头皮在HAL层做同步,代码写得极其丑陋。

HAL3:灵活但复杂

HAL3彻底推翻了HAL1的设计。它引入了「请求-结果」模型。App可以同时发出多个请求,每个请求可以指定不同的参数(比如分辨率、帧率、3A模式)。HAL异步处理这些请求,然后返回结果。

// HAL3的典型调用流程
// App发送一个捕获请求
camera3_capture_request_t req;
req.frame_number = 1;
req.settings = &settings;  // 包含AE、AF、AWB等参数
req.num_output_buffers = 2; // 同时输出预览流和拍照流

// HAL处理完成后回调
process_capture_result(..., camera3_capture_result_t *result);

HAL3最大的优势是「解耦」。App可以独立控制每个请求的参数。比如,预览流用30fps、1080p,拍照流用全分辨率、带HDR。HAL内部可以并行处理,互不干扰。

对比项 HAL1 HAL3
请求模型 同步、串行 异步、并行
参数控制 全局设置 逐帧设置
多流支持 有限(通常只能一路预览+一路拍照) 灵活(可同时输出多路流)
元数据 简单(基本只有EXIF) 丰富(包含3A状态、传感器时间戳等)
性能调优空间 小(接口固定,很难优化) 大(可以精细控制每个环节)

个人经验:我建议新项目直接上HAL3。虽然HAL3的接口比HAL1复杂得多,但它的灵活性是HAL1没法比的。特别是做多摄、高帧率、计算摄影这些功能时,HAL3几乎是唯一的选择。当然,如果你的硬件非常老旧(比如只有一颗VGA传感器),那HAL1也够用。

1.4 小结

这一章咱们把HAL的定位、职责和版本演进捋了一遍。说白了,HAL就是Android相机系统的「腰」。腰不好,整个系统都站不起来。HAL1是过去式,HAL3是现在和未来。下一章我会深入HAL3的架构细节,包括它的核心数据结构、请求生命周期、以及怎么在HAL层做性能调优。

嗯,最后说一句。如果你现在还在维护HAL1的代码,我建议你尽早规划迁移。我在好几个项目里见过,因为HAL1的限制,导致新功能加不进去,最后只能重写整个HAL。那滋味,不好受。