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.java和CameraCaptureSession.java |
frameworks/av/camera/ |
CameraService和Provider(框架层) | 看CameraService.cpp和CameraProviderManager.cpp |
hardware/interfaces/camera/ |
HAL接口定义(HIDL + HAL3头文件) | 看ICameraDevice.hal和types.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”是怎么从应用一路传到硬件的。嗯,做好准备,后面才是硬仗。