2. Camera HAL1 架构详解
Camera HAL1 是 Android 平台上最早定义的相机硬件抽象层标准,从 Android 1.0 开始引入,直至 Android 8.0 仍被广泛支持。HAL1 的核心设计思想是以 CameraService 为中心,通过同步阻塞模型控制相机硬件。理解 HAL1 是掌握后续 HAL3、HAL4 演进的基础。
学习提示:HAL1 虽然已被 Google 标记为 deprecated(弃用),但大量中低端设备、车载系统、IoT 设备仍在沿用。掌握 HAL1 能帮助你快速定位 legacy 平台上的相机问题。
2.1 HAL1 模块结构
HAL1 在系统层次中位于 CameraService(Java/Native 层)与 Kernel Camera Driver 之间。其模块加载遵循 Android HAL 标准规范,通过 hw_get_module() 动态加载 camera.<platform>.so 共享库。
关键文件路径:
hardware/libhardware/include/hardware/camera.h —— 定义 camera_module_t 和 camera_device_thardware/libhardware/modules/camera/ —— 参考实现device/<vendor>/<platform>/camera/ —— 厂商实际 HAL 源码
2.2 CameraHardwareInterface 接口
在 HAL1 架构中,CameraHardwareInterface 是连接 CameraService 与底层硬件实现的核心 C++ 抽象类。它定义了一组纯虚函数,厂商必须实现这些接口才能驱动相机硬件。
| 接口方法 | 功能描述 | 调用时机 |
|---|---|---|
setCallbacks() |
注册通知/数据回调函数 | open() 后立即调用 |
setPreviewWindow() |
绑定 Surface 用于预览显示 | startPreview() 之前 |
startPreview() |
启动预览数据流 | 用户调用 Camera.startPreview() |
stopPreview() |
停止预览数据流 | 用户调用 Camera.stopPreview() |
takePicture() |
触发拍照流程(含 shutter/raw/compressed) | 用户调用 Camera.takePicture() |
autoFocus() |
启动自动对焦 | 拍照前或用户触发 |
setParameters() |
设置相机参数(分辨率、fps、白平衡等) | 随时可调用 |
getParameters() |
获取当前相机参数 | 随时可调用 |
接口定义示例(简化):
class CameraHardwareInterface : public virtual RefBase {
public:
virtual status_t setCallbacks(
camera_notify_callback notify_cb,
camera_data_callback data_cb,
camera_data_timestamp_callback data_cb_timestamp,
camera_request_memory get_memory,
void* user) = 0;
virtual status_t setPreviewWindow(
preview_stream_ops_t* window) = 0;
virtual status_t startPreview() = 0;
virtual void stopPreview() = 0;
virtual status_t takePicture() = 0;
virtual status_t autoFocus() = 0;
virtual status_t setParameters(const CameraParameters& params) = 0;
virtual CameraParameters getParameters() const = 0;
};
2.3 预览与拍照流程
2.3.1 预览流程
HAL1 的预览流程采用同步轮询 + 回调通知模式。CameraService 通过 preview_stream_ops_t 接口向 HAL 提供 dequeue_buffer() / enqueue_buffer() 机制,HAL 驱动在完成帧采集后直接填充 buffer 并回调。
2.3.2 拍照流程
HAL1 的拍照流程比预览复杂,因为它需要依次产生 shutter 回调、raw 数据回调(可选)、jpeg 压缩数据回调。整个过程在 HAL 内部是同步串行的,CameraService 在收到 shutter 回调后才会等待后续数据。
- 触发拍照:App 调用
Camera.takePicture()→ CameraService → HALtakePicture() - Shutter 回调:HAL 立即调用
notify_callback(SHUTTER),通知上层播放快门音效 - Raw 数据(可选):如果 App 注册了 raw 回调,HAL 输出未压缩的 Bayer 数据
- JPEG 压缩:HAL 内部完成 ISP 处理 + JPEG 编码,通过
data_callback(COMPRESSED)返回 - 停止预览(可选):部分实现会在拍照期间自动停止预览,拍照完成后再恢复
HAL1 拍照的典型问题:由于 JPEG 压缩在 HAL 内部同步完成,拍照期间整个相机管线被阻塞。如果 JPEG 编码耗时较长(例如 8MP 以上图片),会导致明显的快门延迟(shutter lag),用户体验较差。
2.4 优缺点分析
| 维度 | 优点 | 缺点 |
|---|---|---|
| 架构复杂度 | 接口简单,厂商实现门槛低 | 扩展性差,新增功能需修改核心接口 |
| 性能 | 预览延迟较低(直接 buffer 流转) | 拍照时阻塞管线;不支持并行流(如同时预览+录像) |
| 内存管理 | 使用 camera_request_memory 统一分配 |
buffer 复用策略僵化,高分辨率场景容易 OOM |
| 多相机支持 | 支持多设备 ID,但各自独立 | 无法实现双摄同步、深度融合等高级特性 |
| 兼容性 | 所有 Android 版本均支持,生态成熟 | Google 已弃用,新特性(如 HDR+、夜景)无法在 HAL1 上高效实现 |
| 调试难度 | 流程线性,日志容易追踪 | 同步模型导致死锁风险;回调上下文复杂 |
总结:HAL1 适合功能简单的单摄设备,以及需要快速上市的中低端产品。对于追求计算摄影、多摄协同、低延迟录像的旗舰设备,HAL1 已经成为瓶颈,必须迁移到 HAL3 或更高版本。