兼容性与碎片化处理:不同SoC平台差异
做Camera HAL这么多年,我最大的感触就是——Android的碎片化,是每个底层工程师的必修课。你想想看,同一套Camera HAL代码,要在高通、联发科、三星Exynos、谷歌Tensor上跑通,还要兼容从Android 10到14的API差异,再加上各家OEM的定制魔改……嗯,这活儿真不是谁都能干的。
我个人习惯把碎片化问题分成三个维度来拆解:SoC平台差异、Android版本API差异、OEM定制化问题。咱们一个一个说。
1. 不同SoC平台的底层差异
先说高通。高通平台在Camera HAL这块做得最成熟,文档也最全。它的camx架构从Android 9开始就稳定了,CHI(Camera HAL Interface)这套东西,说白了就是帮你把ISP、传感器、算法模块串起来。我在项目中遇到过最典型的问题——高通平台的UVC Camera兼容性。有些第三方USB摄像头在高通上跑得好好的,换到MTK上就黑屏。为什么?因为MTK的UVC驱动实现跟高通不一样,它要求特定的帧间隔配置。
核心差异点:
- 高通:camx + CHI架构,ISP管线可编程性强,支持多Camera并发
- MTK:自研ISP + 私有HAL实现,对第三方Sensor兼容性较差
- Exynos:三星自研,ISP集成度高,但文档封闭,调试困难
- Tensor:基于Exynos魔改,加入了Google自己的ML加速单元
MTK平台我踩过的坑最多。有一次客户要求在MTK平台上实现HDR+拍照,结果发现MTK的ISP不支持多帧合成的硬件加速。没办法,只能走CPU后处理,帧率直接掉到2fps。后来我学乖了——做MTK平台,一定要先确认ISP的硬件能力。
Exynos平台呢?说实话,它的ISP性能其实不差,但问题在于文档和工具链。三星的Camera HAL代码里经常有未公开的私有API,你只能靠反编译和抓log来猜。我记得有一次调试Exynos的AE(自动曝光)算法,发现它的曝光收敛速度比高通慢一倍,最后查出来是三星的ISP驱动里有个默认的防抖参数没关。
Tensor平台比较新,我接触得不多。但有一点可以肯定——它的ML加速单元对Camera pipeline有直接影响。比如Google的Real Tone算法,就是靠Tensor的TPU来做肤色还原。如果你要在Tensor上做第三方Camera App,得注意它的HAL层可能已经绑定了Google自己的算法模块。
2. Android版本API差异
Android版本升级,对Camera HAL来说就是一场噩梦。我列个表,你感受一下:
| Android版本 | 关键API变化 | 对HAL的影响 |
|---|---|---|
| Android 10 | 引入CameraX,HAL3成为强制 | 老设备必须升级HAL3,否则无法使用 |
| Android 11 | 新增CAMERA_SERVICE_PRIORITY |
多Camera场景下优先级调度变化 |
| Android 12 | 强制CONFIGURATION_SUCCESS回调 |
HAL必须正确返回配置状态 |
| Android 13 | 引入SESSION_CONFIGURATION新接口 |
老HAL代码需要适配新接口 |
| Android 14 | Ultra HDR支持,RAW16格式变化 | ISP管线需要支持新的HDR元数据 |
我个人觉得,Android 12到13的过渡是最痛苦的。为什么?因为Google在Android 13里改了CameraMetadata的序列化方式。以前你写HAL代码,直接往metadata里塞key-value就行。现在不行了,必须走VendorTag注册流程。我有个项目,就因为没及时适配这个变化,导致第三方Camera App在Android 13上无法获取到自定义的AE参数。
避坑指南:我曾经在Android 11升级到12时,忽略了CAMERA_SERVICE_PRIORITY的变化。结果多Camera场景下,主摄和广角同时打开时,广角经常被系统杀掉。后来发现是优先级没配好。解决办法很简单——在HAL的open()函数里,根据Camera ID设置不同的优先级。
3. OEM定制化问题处理
OEM定制化,说白了就是各家手机厂商在Android原生基础上加自己的私货。小米的MiuiCamera、OPPO的ColorOS Camera、华为的EMUI Camera……每个都有自己的HAL扩展。
我遇到过最离谱的一次——某厂商在HAL层加了一个vendor.qti.hardware.camera.postproc的私有服务,用来做美颜。结果这个服务跟高通的camx有冲突,导致拍照时ISP管线卡死。查了三天log,最后发现是私有服务的线程优先级比camx的ISP线程高,抢占了CPU资源。
处理OEM定制化问题,我有三个原则:
- 先看Vendor目录:OEM的定制代码通常放在
vendor/目录下,别去动hardware/里的原生代码 - 抓取Vendor log:用
logcat -b vendor抓取OEM私有服务的日志 - 对比原生HAL:把OEM的HAL代码跟AOSP原生代码做diff,找出差异点
警告:千万不要直接修改OEM的HAL代码!我曾经手贱改了一行小米的MiuiCamera代码,结果OTA升级时被覆盖了,导致线上用户拍照闪退。正确的做法是——在HAL层之上加一个适配层,用VendorTag来桥接OEM的私有接口。
4. 知识体系总览
下面这张图,是我自己整理的Camera碎片化处理知识体系。你看一眼,心里就有数了:
5. 实战建议
最后,给你几个实战建议:
- 建立平台兼容性矩阵:把每个SoC平台支持的Camera特性列出来,比如HDR、多帧合成、RAW格式等。我习惯用Excel维护这个矩阵,每次新项目先查一遍。
- 使用抽象层隔离差异:在HAL之上加一个
CameraPlatformAdapter,把平台相关的代码封装起来。这样换平台时,只需要改适配层。 - 自动化测试覆盖:写一个脚本,自动在多个Android版本上跑Camera CTS测试。我吃过亏——Android 13上有个
testCameraMetadata用例没过,结果导致Google认证卡了两周。
小技巧:如果你要在新平台上快速验证Camera HAL,可以用adb shell dumpsys media.camera来查看当前设备的Camera能力。这个命令会输出所有Camera ID、支持的分辨率、帧率范围等信息。我每次拿到新设备,第一件事就是跑这个命令。
嗯,碎片化处理这事儿,说白了就是经验积累 + 工具链完善。你踩过的坑越多,后面的路就越顺。别怕,慢慢来。