第一章:Android Camera 系统架构全景

从 App 到 HAL 的完整数据流,HAL 在其中的位置与作用。

大家好,我是你们的讲师。今天咱们聊聊 Android Camera 的整体架构。

很多新人一上来就扎进 HAL 代码里,结果越看越懵。为什么?

因为你不知道数据从哪来,到哪去。说白了,你只看到了一个点,没看到整条线。

我个人习惯,学任何子系统,先看全景图。就像去一个陌生城市,先看地图,再走街串巷。

1.1 一张图看懂 Camera 数据流

先别急着看代码。咱们把 Camera 系统想象成一条流水线。

  • App 层:用户点一下拍照按钮。这是起点。
  • Framework 层:接收指令,调度资源。这是大脑。
  • HAL 层:真正操作硬件。这是双手。
  • Kernel 层:驱动传感器、ISP。这是肌肉。

数据流是这样的:

App → Framework → CameraService → HAL → Kernel → 硬件

反过来,图像数据从硬件上来,经过 HAL 处理,再一路送回 App 显示。

嗯,这里要注意:HAL 是承上启下的关键节点。它把上层抽象的请求,翻译成底层具体的硬件操作。

1.2 HAL 到底在哪个位置?

我经常跟团队里的新人说:HAL 就是一道墙。

墙的左边,是 Android 通用的 Framework 代码。墙的右边,是各家芯片厂商的私有实现。

为什么要有这道墙?

你想想看,高通、MTK、展锐,每家 ISP 都不一样。如果 Google 直接跟硬件打交道,那代码得写成什么样?

所以 Google 定义了 HAL 接口。你只要实现这个接口,你的 Camera 就能跑在 Android 上。

核心要点:

HAL 是硬件抽象层。它隐藏了硬件差异,向上提供统一接口。

说白了,Framework 不关心你用的是 OV 还是 Sony 的 sensor。它只调用 HAL 的 open、close、processCaptureRequest 这些函数。

1.3 数据流中的关键角色

咱们把每个角色拆开看看。

层级 组件 职责
App Camera2 API 发起请求,接收结果
Framework CameraService 管理权限、协调多个 App 访问
HAL Camera HAL 模块 处理请求,控制硬件
Kernel V4L2 / 私有驱动 操作寄存器,传输数据

我在项目中遇到过一个问题:App 打开相机特别慢。查了半天,发现是 HAL 层的初始化里,有个 I2C 通信超时了。

你看,问题出在 HAL,但表象在 App。不懂架构,你根本不知道从哪下手。

1.4 一次拍照请求的完整旅程

咱们走一遍流程。假设用户按下了拍照键。

  1. App 调用 capture():构造一个 CaptureRequest,里面包含各种参数(曝光、白平衡、对焦区域等)。
  2. CameraService 收到请求:检查权限,然后转发给 HAL。
  3. HAL 的 processCaptureRequest() 被调用:这是咱们开发者最熟悉的入口。
  4. HAL 下发命令到 Kernel:通过 ioctl 或者 DMA 方式,告诉 sensor 开始曝光。
  5. 硬件返回 RAW 数据:Kernel 把数据送到 HAL 的 buffer 里。
  6. HAL 做后处理:比如 3A 统计、YUV 转换、JPEG 编码。
  7. HAL 回调通知 Framework:数据准备好了,你拿走吧。
  8. Framework 把结果送回 App:App 拿到图片,显示在屏幕上。

个人经验:

我曾经调试过一个 bug,预览画面卡顿。从 App 一路查到 HAL,最后发现是 HAL 里 buffer 申请太慢。

嗯,这种问题,如果你不懂整条链路,光看 HAL 代码是找不到根因的。

1.5 HAL 的核心价值

说了这么多,HAL 到底有什么用?我总结三点:

  • 解耦:Framework 和硬件不直接依赖。换 sensor 只需要改 HAL,Framework 不用动。
  • 复用:同一套 Framework 代码,可以跑在不同芯片上。Google 的 CTS 测试也是基于 HAL 接口。
  • 性能:HAL 可以做一些底层优化。比如我习惯在 HAL 里做 buffer 复用,减少内存拷贝。

避坑指南:

千万不要在 HAL 里做耗时操作!

我曾经见过有人把 JPEG 编码放在 HAL 的 processCaptureRequest 里同步执行。结果拍照卡死,ANR 了。

记住:HAL 的接口调用是有超时限制的。耗时的操作要放到单独线程里。

1.6 小结

这一章咱们把 Camera 架构的全景看了一遍。

你知道了数据从 App 到硬件的完整路径。也明白了 HAL 就是那个翻译官,把上层需求变成硬件指令。

下一章,咱们会深入 HAL 的代码结构。看看那些 open、close、processCaptureRequest 到底是怎么实现的。

嗯,先消化这些。有问题随时问我。