2. Android Camera 架构概览:从 App 到 HAL 再到 Kernel 的完整数据流
Android Camera 子系统是一个典型的 分层解耦 架构,从上至下依次为:应用层 (App)、框架层 (Framework)、硬件抽象层 (HAL) 与 内核层 (Kernel)。理解每一层的职责与层间接口,是进行 HAL 与 Kernel 对齐策略设计的前提。
核心要点: 数据流本质是“控制流 + 数据流”的双通道。控制流负责配置参数与下发命令,数据流负责图像帧的搬运与处理。HAL 是承上启下的关键枢纽,Kernel 是硬件交互的最终执行者。
2.1 四层架构与核心组件
下表总结了各层的主要模块与职责:
| 层级 | 核心模块/进程 | 主要职责 | 关键接口/协议 |
|---|---|---|---|
| App 层 | Camera App (Java/Kotlin) | 调用 Camera API2,发起预览/拍照/录像请求 | android.hardware.camera2 |
| Framework 层 | CameraService, CameraProvider | 权限管理、流配置、会话创建、数据分发 | AIDL / HIDL |
| HAL 层 | Camera HAL (CameraProvider HAL) | 实现 CameraDevice、CaptureSession、Result 回调 | HIDL / AIDL (Camera HAL 接口) |
| Kernel 层 | V4L2 驱动、ISP 驱动、Sensor 驱动 | 硬件寄存器操作、帧采集、MIPI CSI 接收、DMA 搬运 | V4L2 ioctl / mmap / dma-buf |
架构演进提示: Android 从 Treble 项目开始强制使用 HIDL 隔离 HAL,到近期逐步迁移至 AIDL 实现更轻量的 IPC。无论哪种形式,HAL 与 Kernel 之间的 V4L2 接口始终是底层事实标准。
2.2 完整数据流:一次拍照请求的生命周期
以一次 单帧拍照 为例,数据流可拆解为 6 个关键步骤:
- App 发起请求: App 通过 CameraCaptureSession.capture() 提交 CaptureRequest,包含输出目标 Surface、3A 参数、帧率等。
- Framework 序列化: CameraService 将请求封装为 HIDL/AIDL 消息,通过 Binder 发送至 HAL 进程。
- HAL 配置与下发: HAL 解析请求,通过 V4L2 ioctl 设置 sensor 模式、曝光时间、增益,并调用 VIDIOC_QBUF 将空 buffer 入队。
- Kernel 硬件采集: Sensor 曝光输出 RAW 数据,ISP 处理为 YUV/JPEG,DMA 将数据写入 dma-buf,驱动通过中断通知帧完成。
- Kernel 上报完成: 驱动调用 VIDIOC_DQBUF 将 filled buffer 出队,并通过 V4L2_EVENT 或 poll 机制通知 HAL。
- HAL 回调至 App: HAL 将 filled buffer 与 metadata 打包为 CaptureResult,通过回调返回 Framework,最终送达 App 的 ImageReader。
常见瓶颈: 步骤 3 与步骤 5 之间的 buffer 周转效率,以及 HAL 与 Kernel 之间的 ioctl 调用延迟,是影响帧率与拍照延迟的核心因素。对齐策略主要针对这两个环节。
2.3 数据流架构 SVG 图
下图展示了从 App 到 Kernel 的完整数据流与关键接口:
2.4 关键接口对比:HAL 与 Kernel 的交互契约
HAL 与 Kernel 之间通过 V4L2 框架交互,核心接口包括:
| 接口类型 | V4L2 调用 | HAL 侧行为 | Kernel 侧行为 |
|---|---|---|---|
| 设备打开 | open() / VIDIOC_QUERYCAP | 获取驱动能力,确认支持格式 | 初始化硬件,返回 capabilities |
| 格式协商 | VIDIOC_S_FMT / VIDIOC_TRY_FMT | 设置输出分辨率、像素格式、fps | 配置 ISP 与 sensor 输出模式 |
| Buffer 管理 | VIDIOC_REQBUFS / VIDIOC_QBUF / VIDIOC_DQBUF | 申请 buffer 并入队/出队 | 管理 DMA 缓冲区,处理帧完成中断 |
| 流控制 | VIDIOC_STREAMON / VIDIOC_STREAMOFF | 启动/停止数据流 | 控制 sensor 与 ISP 时钟门控 |
| 控制参数 | VIDIOC_S_CTRL / VIDIOC_G_CTRL | 设置曝光、增益、白平衡等 | 通过 I2C/SPI 写入 sensor 寄存器 |
| 事件通知 | VIDIOC_SUBSCRIBE_EVENT / poll() | 监听帧同步、错误事件 | 上报帧完成、丢帧、硬件错误 |
对齐策略切入点: 上表中的“格式协商”与“Buffer 管理”是 HAL 与 Kernel 对齐最频繁、最容易出问题的两个区域。例如,HAL 要求输出 NV12 格式,但 Kernel 驱动只支持 NV21,就需要在 HAL 侧增加格式转换或协商 fallback 逻辑。
2.5 数据流中的 Buffer 生命周期
Buffer 在 App、HAL、Kernel 之间的流转是数据流的核心。下图展示了 Buffer 的完整生命周期:
2.6 对齐策略的三大核心矛盾
从架构概览中,我们可以提炼出 HAL 与 Kernel 对齐时必须解决的三个核心矛盾:
- 格式与分辨率协商: HAL 期望的格式(如 YUV420_888)与 Kernel 驱动实际支持的格式(如 NV12 或 NV21)不一致。需要建立格式优先级列表与 fallback 机制。
- Buffer 元数据同步: HAL 与 Kernel 对 buffer 的 stride、plane offset、timestamp、metadata 的理解必须一致。否则会导致花屏、绿屏或帧率异常。
- 控制参数映射: HAL 的 3A 参数(曝光、增益、白平衡)需要精确映射到 Kernel 驱动的 V4L2 controls 或私有 ioctl。映射错误会导致图像过曝、偏色或无法对焦。
实战建议: 在项目初期,建议使用
v4l2-ctl --list-formats 和 v4l2-ctl --list-ctrls 导出 Kernel 驱动的能力,与 HAL 的 CameraCharacteristics 进行逐项比对,形成对齐检查清单。