1、AOSP相机概览:Android相机架构演进、Camera HAL3简介、AOSP相机代码结构

各位同学,咱们今天正式开讲。做相机系统移植,第一件事不是撸代码,而是先把整个架构的来龙去脉搞清楚。我当年刚接触Android相机时,面对一堆HAL、Provider、Service的术语,说实话,头都是大的。后来踩了不少坑,才慢慢理清这条线。

这一节,我们就从三个维度切入:架构怎么变的HAL3到底是个啥代码该看哪。嗯,跟着我走一遍,你心里就有底了。

1.1 Android相机架构演进:从石器时代到现代

Android相机架构,说白了,经历了三个阶段。

第一阶段:Camera HAL v1(Android 4.0及之前)

那时候的架构很简单。上层应用调一下open(),底层就直接操作硬件了。我印象最深的是,当时做一款平板,每次预览都要自己算帧率,稍微没调好就卡成PPT。HAL v1的问题在于:

  • 不支持多路并发(你开了预览就不能拍照)
  • 没有缓冲区管理(内存拷贝频繁,性能差)
  • 扩展性差(加个新功能得改整个HAL)

第二阶段:Camera HAL v3(Android 5.0引入)

Google终于受不了了,搞了个大重构。HAL v3的核心思想是:把控制权和数据流分开。应用层下发CaptureRequest,HAL返回CaptureResult,中间走一套标准的Pipeline。我在项目中遇到过,从v1迁移到v3,最痛苦的不是改代码,而是理解“请求-响应”这个模型。你想想看,以前是直接操作寄存器,现在要写一个状态机,确实需要适应。

第三阶段:Camera HAL v3 + Treble(Android 8.0之后)

Treble架构把HAL层独立成vendor模块,和系统框架解耦。这样做的好处是:厂商升级系统时,不用重新适配相机驱动。我个人的习惯是,只要项目基于Android 8.0以上,一律用HAL3 + Treble方案,维护成本低很多。

核心演进脉络:

从“直接操作硬件” → “Pipeline标准化” → “框架与HAL解耦”

说白了,Google一直在做一件事:让相机系统更通用、更稳定、更好移植。

1.2 Camera HAL3简介:你不得不懂的核心概念

HAL3,全称是Camera Hardware Abstraction Layer version 3。它不是一套代码,而是一套接口规范。你只要实现了这套接口,Android框架就能用你的相机。

我建议你记住三个核心角色:

  • CameraDevice:代表一个物理相机。比如后摄、前摄,每个都是一个Device。
  • CaptureSession:一次拍照或录像的会话。你打开相机后,先创建Session,然后往里面丢Request。
  • CaptureRequest:一次捕获请求。里面包含了你要的参数(曝光、对焦、帧率等)。

举个例子,你按下快门时,流程是这样的:

App → CameraService → CameraProvider → HAL3 Implementation
    ↓
CaptureRequest (包含AE/AWB/AF设置)
    ↓
HAL3 Pipeline (ISP处理、3A算法)
    ↓
CaptureResult (包含最终的图像数据 + 元数据)

嗯,这里要注意:HAL3是异步的。你发一个Request,HAL不一定马上返回结果。它可能先返回一个部分结果(比如先告诉你曝光值),等处理完了再返回完整结果。我曾经在调试时,因为没处理好这个异步回调,导致预览画面一直黑屏——其实就是没等HAL把第一帧送上来。

避坑指南:

我曾经在移植时,发现HAL3的process_capture_request()函数一直没被调用。查了两天才发现,是camera_metadata的tag填错了。记住:HAL3对metadata的格式要求非常严格,多一个空格、少一个字节,都可能让整个Pipeline挂掉。

1.3 AOSP相机代码结构:从哪里下手?

很多新手拿到AOSP源码,第一反应是:这么多目录,看哪个?我告诉你,别慌。相机相关的代码,主要集中在三个地方:

目录 作用 我建议的关注点
packages/apps/Camera2/ 相机应用层代码(UI + 业务逻辑) CameraActivity.javaCameraCaptureSession.java
frameworks/av/camera/ CameraService和Provider(框架层) CameraService.cppCameraProviderManager.cpp
hardware/interfaces/camera/ HAL接口定义(HIDL + HAL3头文件) ICameraDevice.haltypes.hal

我个人习惯,先看hardware/interfaces/camera/。为什么?因为这里是HAL3的“契约”。你只有理解了接口长什么样,才知道底层该实现什么。举个例子,ICameraDevice.hal里定义了open()close()configureStreams()等方法,这些就是你要在HAL里实现的。

然后看frameworks/av/camera/。这里你会看到CameraService是怎么调用HAL的。比如CameraService::connect()函数,它会通过HIDL去打开HAL的CameraDevice。我建议你重点看CameraProviderManager,它负责管理多个CameraProvider(比如后摄一个Provider,前摄另一个)。

最后才是应用层。应用层的代码,说白了就是调框架层的API。你如果只改应用,不改HAL,那基本不用看底层代码。但如果你要做移植,那底层和框架层才是关键。

警告:

不要一上来就改packages/apps/Camera2/。很多新手觉得“应用层代码我熟”,结果改了半天发现底层HAL根本没对接上。记住:移植的核心在HAL,不在UI。

1.4 小结:这一节你该带走什么?

好,咱们捋一下。这一节你至少要知道:

  • Android相机架构从v1到v3,核心变化是标准化Pipeline异步模型
  • HAL3的三个核心角色:Device、Session、Request。记住它们的关系,后面调试时你会反复用到。
  • AOSP相机代码的三大目录:应用层、框架层、HAL接口层。移植时,重点看HAL接口和框架层。

下一节,我们会深入HAL3的接口细节,手把手教你写一个最简单的HAL实现。到时候,你会真正理解“CaptureRequest”是怎么从应用一路传到硬件的。嗯,做好准备,后面才是硬仗。