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 架构中,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 最常见的性能瓶颈之一。
1.3 HAL1 在 Camera 服务中的位置
在 Android 相机系统中,CameraService 是连接应用层与 HAL 层的核心系统服务。HAL1 作为 CameraService 的下层接口,承担着将上层请求翻译为硬件指令、并将硬件数据返回给上层的职责。
具体位置关系如下:
- 应用层:通过
android.hardware.CameraAPI 调用 CameraService 的 Binder 接口。 - CameraService:运行在
cameraserver进程中,管理多个 Camera 客户端,调用 HAL 模块的open()、startPreview()、takePicture()等接口。 - HAL1 模块:以共享库(
.so)形式存在,由 CameraService 通过dlopen动态加载。模块入口是HAL_MODULE_INFO_SYM结构体。 - HAL1 设备:通过
camera_device_t结构体暴露操作函数指针,包括set_preview_window、start_preview、take_picture等。
性能陷阱: 在 HAL1 架构中,CameraService 与 HAL 模块运行在同一个进程(cameraserver)中。如果 HAL 实现中存在死循环或长时间阻塞,会直接导致整个 CameraService 无响应,进而触发 ANR(应用无响应)。这是定位性能瓶颈时需要优先排查的方向。
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(),计算差值。