1. HAL1 架构概述

Android Camera HAL1(Hardware Abstraction Layer 1)是 Android 早期版本中定义的相机硬件抽象层标准接口。它采用 同步阻塞 的设计模型,应用层通过 CameraService 与 HAL 层交互,最终控制底层传感器与 ISP(图像信号处理器)。理解 HAL1 的整体架构、与 HAL3 的核心差异以及在 Camera 服务中的位置,是定位性能瓶颈的第一步。

1.1 HAL1 整体架构

HAL1 架构自上而下分为三个主要层级:应用框架层、CameraService 层 和 HAL 层。HAL 层内部又细分为 Camera HAL 模块 和 Camera 设备 两个子层。

架构核心特征: 整个数据流是同步的——应用发起一次 capture(拍照/预览帧),必须等待 HAL 返回结果后才能发起下一次请求。这种设计简化了实现,但直接限制了帧率和并发能力。
HAL1 整体架构分层图 HAL1 整体架构分层图 应用框架层 (App Framework) CameraService 层 HAL 层 - Camera HAL 模块 HAL 层 - Camera 设备 (硬件接口) 硬件层 (Sensor / ISP) 关键接口 camera_module_t camera_device_t preview / capture

在 HAL1 架构中,Camera HAL 模块 负责枚举设备、打开/关闭相机;Camera 设备 则实现具体的预览、拍照、参数设置等操作。所有接口调用都是同步的,这意味着一次 process_capture 调用会阻塞直到硬件完成帧采集并返回。

1.2 HAL1 与 HAL3 的区别

HAL3(Camera3)是 Android 从 Lollipop(API 21)开始引入的新一代 HAL 接口,与 HAL1 有本质区别。下表从多个维度对比两者的核心差异:

对比维度 HAL1 HAL3
设计模型 同步阻塞 异步流水线
请求模式 单次 capture 阻塞等待 多请求入队,异步回调
帧率控制 受限于应用调用频率 硬件自主调度,支持高帧率
多路复用 不支持(一次只能一个流) 支持多个输出流(YUV/RAW/JPEG)
元数据 简单参数(参数结构体) 丰富的 metadata(android.* 键值对)
性能瓶颈 CPU 空转等待、帧率低、延迟高 流水线并行,延迟低,吞吐高
适用场景 低端设备、兼容模式 中高端设备、专业相机应用
性能提示: 在 HAL1 架构下,如果应用层调用 startPreview() 后没有及时调用 getPreviewFrame(),HAL 层会一直阻塞等待,导致预览帧率骤降。这是 HAL1 最常见的性能瓶颈之一。
HAL1 vs HAL3 流程对比 HAL1 vs HAL3 流程对比 HAL1: 同步阻塞模型 App 发起 capture HAL 阻塞等待 硬件完成返回 App 收到帧数据 一次 capture 阻塞整个调用链 帧率 = 1 / (阻塞时间 + 处理时间) HAL3: 异步流水线模型 App 提交请求 HAL 入队返回 硬件异步处理 回调通知 App 请求入队后立即返回,不阻塞 硬件流水线并行处理多帧 核心差异总结 HAL1 是同步阻塞,一次一帧,CPU 空转等待;HAL3 是异步流水线,多请求并行,硬件自主调度。 HAL1 性能瓶颈通常出现在“等待返回”阶段;HAL3 瓶颈更多在“流水线深度”和“回调延迟”。

1.3 HAL1 在 Camera 服务中的位置

在 Android 相机系统中,CameraService 是连接应用层与 HAL 层的核心系统服务。HAL1 作为 CameraService 的下层接口,承担着将上层请求翻译为硬件指令、并将硬件数据返回给上层的职责。

具体位置关系如下:

  1. 应用层:通过 android.hardware.Camera API 调用 CameraService 的 Binder 接口。
  2. CameraService:运行在 cameraserver 进程中,管理多个 Camera 客户端,调用 HAL 模块的 open()、startPreview()、takePicture() 等接口。
  3. HAL1 模块:以共享库(.so)形式存在,由 CameraService 通过 dlopen 动态加载。模块入口是 HAL_MODULE_INFO_SYM 结构体。
  4. HAL1 设备:通过 camera_device_t 结构体暴露操作函数指针,包括 set_preview_window、start_preview、take_picture 等。
性能陷阱: 在 HAL1 架构中,CameraService 与 HAL 模块运行在同一个进程(cameraserver)中。如果 HAL 实现中存在死循环或长时间阻塞,会直接导致整个 CameraService 无响应,进而触发 ANR(应用无响应)。这是定位性能瓶颈时需要优先排查的方向。
HAL1 在 Camera 服务中的位置 HAL1 在 Camera 服务中的位置 应用进程 (App) Binder IPC cameraserver 进程 CameraService dlopen HAL 共享库 (.so) camera_module_t 硬件设备 关键调用路径 App → CameraService → HAL 模块 → HAL 设备 → 硬件 所有调用在 cameraserver 进程内同步执行 HAL 阻塞 → CameraService 阻塞 → App 阻塞 性能瓶颈定位关键点 1. 检查 HAL 模块的 open() 耗时 → 2. 检查 start_preview() 阻塞时间 → 3. 检查 take_picture() 返回延迟 4. 检查 preview 帧回调间隔是否均匀 → 5. 检查是否有死锁或长时间持锁

1.4 HAL1 接口关键数据结构

HAL1 的核心接口定义在 hardware/libhardware/include/hardware/camera.h 中。以下是两个最重要的结构体:

// HAL 模块结构体
typedef struct camera_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;

// HAL 设备结构体
typedef struct camera_device {
    hw_device_t common;
    int (*set_preview_window)(struct camera_device *dev,
                              struct preview_stream_ops *window);
    void (*start_preview)(struct camera_device *dev);
    void (*stop_preview)(struct camera_device *dev);
    int (*take_picture)(struct camera_device *dev);
    // ... 其他操作函数指针
} camera_device_t;
性能分析切入点: 在 HAL1 中,take_picture() 和 start_preview() 是最容易产生性能瓶颈的接口。建议在 HAL 层插入时间戳日志,精确测量每个接口的阻塞时长。例如,在 take_picture() 入口和出口分别记录 ktime_get_ns(),计算差值。