1. Camera HAL 架构概述

Camera HAL(硬件抽象层)是 Android 相机子系统中连接 Framework 与底层硬件驱动的关键中间层。它定义了统一的接口规范,使上层应用无需关心具体硬件实现,同时为芯片厂商(OEM/SOC Vendor)提供标准化的硬件适配入口。本章从整体架构、HAL 版本演进及接口技术三个维度展开,为后续 Stream 复用与数据传输优化奠定基础。

1.1 Android Camera HAL 整体架构

Android Camera 软件栈自上而下分为应用层、Framework 层、HAL 层和内核驱动层。HAL 层位于 Framework 与内核之间,负责将上层请求转换为硬件操作,并返回图像数据。整体架构如下图所示:

Android Camera 软件栈整体架构 应用层(Camera App / SDK) Framework 层 CameraService / CameraProvider / CameraDeviceClient HIDL / AIDL 接口 Camera HAL 层 HAL 1 / HAL 3 实现 Stream 复用 / Buffer 管理 / 3A 控制 Camera Module / Sensor 适配 内核驱动层(V4L2 / CSI / ISP) Sensor 驱动 / ISP 驱动 / DMA-BUF 硬件层(Camera Sensor / ISP)

HAL 层在整个相机系统中承担以下核心职责:

  • 请求分发:将 Framework 下发的 CaptureRequest 转换为硬件可执行的参数序列。
  • Buffer 管理:通过 Gralloc / DMA-BUF 机制管理图像缓冲区,实现零拷贝或低拷贝传输。
  • Stream 配置:管理多个图像流(Preview、Video、Snapshot)的复用与切换。
  • 3A 控制:集成自动对焦(AF)、自动曝光(AE)、自动白平衡(AWB)算法。
  • 元数据传递:将硬件生成的统计信息(如帧数、时间戳、人脸检测结果)上报给 Framework。

1.2 HAL3 与 HAL1 的区别

Android Camera HAL 经历了从 HAL1 到 HAL3 的重大演进。HAL1 是早期 Android 版本(Android 4.x 及之前)使用的接口,设计简单但灵活性差;HAL3 从 Android 5.0 开始引入,支持多流并发、逐帧控制和高级特性。下表从多个维度对比两者的核心差异:

对比维度 HAL1 HAL3
引入版本 Android 2.x ~ 4.x Android 5.0+
架构模式 单线程、阻塞式操作 异步流水线、多请求并发
Stream 支持 仅支持单流(Preview 或 Video 或 Snapshot) 支持多流并发(Preview + Video + Snapshot 同时)
逐帧控制 不支持,参数全局设置 支持逐帧 CaptureRequest 精细控制
Buffer 管理 Framework 管理 Buffer,HAL 被动接收 HAL 主动申请 Buffer,支持灵活复用
元数据 固定格式,扩展困难 基于 CameraMetadata 键值对,可扩展
适用场景 低端设备、功能简单的相机 高端设备、多摄、HDR、夜景等复杂场景

关键结论:HAL3 是当前 Android 相机开发的主流标准。HAL1 已在新版本中被标记为 deprecated,但部分低端平台或 legacy 设备仍在使用。本课程所有 Stream 复用与数据传输优化方案均基于 HAL3 架构。

HAL3 相比 HAL1 的核心改进在于引入了 Camera3Stream 和 Camera3Request 数据结构,支持以下关键能力:

  • 多流复用:同一 Sensor 可以同时输出 Preview 流(低分辨率)、Video 流(编码格式)和 Snapshot 流(高分辨率),无需切换模式。
  • 逐帧参数:每一帧都可以独立设置曝光时间、ISO、对焦位置、白平衡等参数,实现类似专业相机的控制粒度。
  • Buffer 复用:HAL 可以通过 process_capture_request 回调直接操作 Buffer 句柄,支持 GPU/ISP 直接处理,减少内存拷贝。

1.3 HIDL 与 AIDL 接口演进

Android 接口定义语言(IDL)是 Framework 与 HAL 之间通信的契约。从 Android 8.0 开始,Google 引入 HIDL(HAL Interface Definition Language)替代传统的 legacy HAL 头文件方式;Android 14 及之后,AIDL(Android Interface Definition Language)逐渐成为主流。两者的演进关系如下图所示:

HIDL → AIDL 接口演进时间线 Legacy HAL Android 2.x ~ 7.x 头文件 + dlopen HIDL Android 8.0 ~ 13 Treble 架构 AIDL HAL Android 12+ 统一接口 未来 AIDL 统一 演进核心变化 • HIDL:基于 .hal 文件,生成 C++/Java 绑定,支持 passthrough 和 binderized 模式 • AIDL:复用 Android 原有 AIDL 语法,减少学习成本,支持跨进程和同进程调用 • 趋势:Google 推荐新项目直接使用 AIDL HAL,HIDL 将在未来版本中逐步移除

HIDL 与 AIDL 在 Camera HAL 开发中的具体差异如下表所示:

对比维度 HIDL AIDL
定义文件 .hal 文件(如 ICameraDevice.hal) .aidl 文件(如 ICameraDevice.aidl)
包名规范 android.hardware.camera.device@3.4 android.hardware.camera.device.ICameraDevice
版本管理 通过 @version 注解,支持 minor/major 版本 通过接口继承和包名区分版本
传输模式 Binderized(默认)或 Passthrough 仅 Binderized
代码生成 hidl-gen 生成 C++/Java 桩代码 aidl 工具生成 C++/Java/Rust 桩代码
性能开销 略高(额外序列化层) 较低(直接复用 Binder 机制)
Google 推荐 已停止新特性开发 新项目首选

开发建议:对于新启动的 Camera HAL 项目,建议直接使用 AIDL 接口。如果维护现有 HIDL 项目,可以逐步迁移到 AIDL,Google 提供了 hidl2aidl 工具辅助转换。在 Stream 复用场景中,AIDL 的 Binder 直传模式能减少一次序列化开销,对高帧率场景(如 60fps Video)有明显性能收益。

在 Camera HAL 开发中,接口定义直接影响 Stream 复用和数据传输的实现方式。以 AIDL 为例,CameraProvider 接口定义如下:

// ICameraProvider.aidl (Android 14+)
package android.hardware.camera.provider;

interface ICameraProvider {
    /**
     * 获取当前设备支持的 Camera 设备列表
     */
    String[] getCameraIdList();

    /**
     * 根据 cameraId 创建 CameraDevice 接口
     */
    ICameraDevice getCameraDevice(String cameraId);

    /**
     * 通知 Framework 设备状态变化
     */
    void notifyDeviceStateChange(long deviceState);
}

相比 HIDL 版本,AIDL 接口更加简洁,去掉了 @entry 和 @callflow 等注解,直接使用标准的 AIDL 语法。在数据传输层面,AIDL 支持 in、out、inout 参数方向,可以更精细地控制跨进程 Buffer 的传递方式,这对 Stream 复用场景中的 Buffer 共享至关重要。