一、Camera HAL概述

什么是Camera HAL

Camera HAL,全称是 Hardware Abstraction Layer。说白了,它就是一道桥梁。

这道桥梁连接着 Android 框架和你的摄像头硬件。我经常跟团队里的新人说:「你把它想象成一个翻译官」。上层框架说「我要拍照」,HAL 就把这句话翻译成硬件能听懂的指令。反过来,硬件传回来的图像数据,HAL 再包装成框架能识别的格式。

为什么要多这么一层?

你想想看,市面上有几百种摄像头传感器。索尼的、三星的、豪威的……每家驱动接口都不一样。如果没有 HAL,Google 得为每款芯片写一套框架代码。那工作量,想想都头疼。

HAL 的存在,让手机厂商可以各自实现底层逻辑。只要遵循 Google 定义的接口规范,上层不用改一行代码。我在做第一个项目时就深刻体会到了这一点——当时我们换了一颗 sensor,只需要重写 HAL 层的驱动适配,上层 App 完全不受影响。

HAL在Android相机架构中的位置

咱们从上往下捋一遍 Android 相机架构:

  1. 应用层:你打开相机 App,点拍照按钮。这是最上层。
  2. Framework 层:Android 的 Camera API 在这里。它把 App 的请求转成标准化的操作。
  3. Camera Service:这是系统服务,管理多个相机实例。它负责跟 HAL 打交道。
  4. Camera HAL:就是我们今天的主角。它接收 Service 下发的请求,然后操作硬件。
  5. 硬件层:sensor、ISP、闪光灯……这些物理设备。

HAL 的位置很关键。它卡在软件和硬件的交界处。向上,它必须严格遵守 Android 定义的接口。向下,它要搞定千奇百怪的硬件。

核心要点:HAL 是 Android 相机系统的「分水岭」。分水岭以上,代码是通用的。分水岭以下,全是厂商自己的活。

我记得有一次调试一个问题,App 端预览画面是黑的。我沿着链路一层层查,最后发现是 HAL 层没有正确配置 sensor 的时钟。如果 HAL 这层出了问题,上层再怎么折腾也没用。

HAL的主要职责与接口

HAL 到底干哪些活?我总结了一下,主要有这几块:

1. 设备管理

打开、关闭摄像头设备。管理多个摄像头实例。嗯,这里要注意——现在的手机至少两三个摄像头,HAL 要能区分哪个是主摄、哪个是广角。

2. 流配置

App 想要什么分辨率的预览?想要什么格式的输出?HAL 得告诉框架:「行,这个我支持」 或者 「不行,换一个」

3. 请求处理

每一帧画面,都是 App 发起一个请求,HAL 去执行。请求里包含了曝光时间、白平衡、对焦位置等等参数。HAL 要把这些参数转成硬件寄存器能理解的值。

4. 数据传递

拍完的照片、录好的视频,数据要从硬件传到 HAL,再从 HAL 传回 Framework。这个过程对性能要求极高。我曾经遇到过一个问题,数据拷贝太慢导致预览掉帧。后来改成用 DMA 直接传输,问题才解决。

5. 错误处理

硬件出错了怎么办?sensor 突然断连了怎么办?HAL 要能捕获这些异常,并且上报给上层。

说到接口,Android 目前主推的是 Camera HAL3。它比 HAL1 复杂得多,但功能也更强大。HAL3 的核心接口是 camera3_device_ops_t,里面定义了十几个函数指针:

typedef struct camera3_device_ops {
    int (*initialize)(...);
    int (*configure_streams)(...);
    int (*register_stream_buffers)(...);
    int (*process_capture_request)(...);
    void (*dump)(...);
    int (*flush)(...);
    // ... 还有其他函数
} camera3_device_ops_t;

这里面最重要的就是 process_capture_request。每一帧的请求都会走到这个函数。我刚开始写 HAL 时,就是在这个函数里踩了不少坑。

避坑指南:我曾经在 configure_streams 里没有正确检查输出格式,结果 App 请求 YUV 格式,我给了 JPEG。画面直接花屏。后来我养成了一个习惯——每个接口入口先做参数校验,别相信上层传过来的东西一定是合法的。

小结

Camera HAL 不是什么神秘的东西。它就是一层适配代码。把 Android 的标准请求,转成硬件能执行的指令。把硬件吐出来的数据,包装成框架能识别的格式。

做 HAL 开发,说白了就是跟这两头打交道。一头是 Google 的规范文档,另一头是芯片厂商的 datasheet。能把这两边对清楚,你就入门了。

下一章,我会带大家搭建实际的开发环境。到时候咱们手把手来,把代码跑起来。