Android Camera HAL 完整开发指南(AIDL HAL 新架构,适配 Android 16)
前置核心背景(承接上文HIDL→AIDL HAL变革)
Android 11开始支持AIDL HAL,Android 16彻底移除HIDL,Camera HAL必须基于AIDL HAL实现 ,IPC全程单Binder驱动,不再有hwbinder。
Camera HAL 两个主流版本:
- Camera HAL3(AOSP标准,主流) :
android.hardware.camera.device@3.x,AIDL重构后为android.hardware.camera.deviceAIDL接口 - Camera HAL1(废弃) :老旧设备兼容,新项目不考虑
Treble分区要求:HAL实现必须放到vendor分区,通过VNDK隔离system/vendor,遵循分区不可直接链接规则。
一、整体调用数据流(AIDL HAL新架构)
App Camera2 API → Framework CameraService(Java AIDL) → JNI → libcamera_client.so(Native)
→ AIDL HAL(标准Binder)→ vendor 厂商Camera HAL实现 → 内核V4L2驱动 → 硬件Sensor/ISP
老架构此处是HIDL+HwBinder,Android16全链路统一标准Binder。
层级拆解
- App层:Camera2 API(CaptureRequest/CaptureResult)
- Framework层:CameraService、CameraProviderManager,向上AIDL,向下调用HAL
- AIDL HAL接口层:Google定义的标准AIDL接口(camera.provider/camera.device/camera.metadata)
- Vendor HAL实现层:厂商自研代码,对接V4L2内核驱动
- Linux内核层:V4L2 subdev、ISP、CSI总线、DMA缓冲区管理
二、环境准备 & 目录结构(AOSP源码)
1. 源码路径
1)Google标准AIDL HAL接口(不可修改)
hardware/interfaces/camera/
├── device/ # ICameraDevice.aidl 设备操作接口
├── provider/ # ICameraProvider.aidl 枚举摄像头、打开设备
├── metadata/ # 元数据定义、能力参数(Characteristics/Request/Result)
└── common/ # 共用枚举、结构体
2)厂商Vendor HAL实现目录(自定义)
规范路径:vendor/[厂商名]/hardware/camera/aidl/
vendor/xxx/hardware/camera/aidl/camera_device/
├── Android.bp # Soong编译脚本(AIDL HAL必须用bp,弃用mk)
├── CameraDevice.cpp/h # 实现ICameraDevice AIDL接口
├── CameraProvider.cpp/h # 实现ICameraProvider AIDL接口
├── V4L2Wrapper.cpp/h # 封装内核V4L2 ioctl操作
├── MetadataHelper.cpp/h # 处理camera metadata静态/动态参数
└── buffer/ # Gralloc buffer管理(ANativeWindow、DMA buf)
3)Manifest声明(Treble注册HAL服务)
vendor/etc/vintf/manifest.xml 必须添加,否则Framework无法通过Binder发现HAL服务:
xml
<hal format="aidl">
<name>android.hardware.camera.provider</name>
<version>1</version>
<interface>
<name>ICameraProvider</name>
<instance>internal/0</instance>
</interface>
</hal>
2. Android.bp 核心编译模板(AIDL HAL固定写法)
json
cc_binary {
name: "android.hardware.camera.provider-service.xxx",
init_rc: ["camera_provider.rc"], // init启动脚本
srcs: [
"CameraProvider.cpp",
"CameraDevice.cpp",
"V4L2Wrapper.cpp",
"MetadataHelper.cpp",
],
// 依赖Google官方AIDL HAL接口库
shared_libs: [
"android.hardware.camera.provider-V1-ndk",
"android.hardware.camera.device-V1-ndk",
"android.hardware.camera.metadata-V1-ndk",
"libbinder_ndk", // AIDL Binder依赖
"libutils",
"libcutils",
"libgralloc", // 图形缓冲区
"libcamera_metadata",
],
// 关键:标记为vendor分区HAL,VNDK稳定
vendor: true,
soc_specific: true,
vintf_fragments: ["manifest_camera.xml"],
}
3. init.rc 启动脚本(camera_provider.rc)
让init进程开机启动HAL Binder服务,注册到servicemanager:
rc
service camera-provider-xxx /vendor/bin/android.hardware.camera.provider-service.xxx
class hal
user camera
group camera graphics drmrpc
capabilities SYS_NICE
on binder SERVICE_MANAGER_PRIORITY_HAL
三、最简代码实现示例(AIDL HAL)
示例1:ICameraProvider 核心接口实现(枚举摄像头)
cpp
#include <android/hardware/camera/provider/ICameraProvider.h>
using namespace ::android::hardware::camera::provider;
class CameraProvider : public ICameraProvider {
public:
// 1. 获取当前所有摄像头ID(后置0、前置1)
binder::Status getCameraIdList(std::vector<std::string>* outCameraIds) override {
outCameraIds->clear();
outCameraIds->push_back("0"); // 后置主摄
outCameraIds->push_back("1"); // 前置副摄
return binder::Status::ok();
}
// 2. 根据cameraId打开ICameraDevice设备
binder::Status openCameraDevice(const std::string& cameraId,
const ::android::sp<::android::hardware::camera::device::ICameraDeviceCallback>& cb,
::android::sp<::android::hardware::camera::device::ICameraDevice>* outDevice) override {
if (cameraId == "0" || cameraId == "1") {
*outDevice = new CameraDevice(cameraId, cb);
} else {
return binder::Status::fromServiceSpecificError(-1);
}
return binder::Status::ok();
}
// 3. 注册Binder服务入口
static void registerService() {
sp<ICameraProvider> provider = new CameraProvider();
::android::defaultServiceManager()->addService(
String16("android.hardware.camera.provider/internal/0"), provider);
}
};
// main函数,HAL服务入口
int main() {
CameraProvider::registerService();
::android::ProcessState::self()->startThreadPool();
pause();
return 0;
}
示例2:ICameraDevice 核心能力(下发CaptureRequest、V4L2取流)
核心需要实现的关键AIDL方法:
getCameraCharacteristics():上报摄像头静态能力(分辨率、对焦、AE、HDR、传感器尺寸)configureStreams():配置预览/拍照流尺寸、格式(YUV_420_888、RAW、JPEG)submitCaptureRequests():下发上层CaptureRequest,驱动V4L2队列buffer、触发ISP拍照flush()/close():停止流、释放buffer、关闭V4L2设备节点
V4L2极简封装片段
cpp
int V4L2Wrapper::openDev(const std::string& devPath) {
mFd = open(devPath.c_str(), O_RDWR);
// 设置捕获格式 V4L2_PIX_FMT_YUV420
struct v4l2_format fmt = {};
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 1920;
fmt.fmt.pix.height = 1080;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
ioctl(mFd, VIDIOC_S_FMT, &fmt);
// 申请MMAP缓冲区、入队buffer
requestBuffers();
enqueueAllBuffers();
// 启动捕获
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(mFd, VIDIOC_STREAMON, &type);
return mFd;
}
示例3:Camera Metadata 能力上报(决定App可用功能)
getCameraCharacteristics 必须填充标准key,Framework校验不通过摄像头直接不可用:
cpp
camera_metadata_t* chars = allocate_camera_metadata(100, 10);
// 支持自动对焦
add_camera_metadata_entry(chars, ANDROID_LENS_FOCUS_AVAILABLE_MODES,
ANDROID_LENS_FOCUS_MODE_AUTO);
// 最大预览分辨率
int32_t res[] = {1920, 1080};
add_camera_metadata_array(chars, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, res, 2);
四、调试&问题定位全套分析方法(实操工具链)
工具1:dumpsys 查看HAL服务是否注册成功
bash
# 查看camera provider AIDL HAL是否注册
adb shell dumpsys android.hardware.camera.provider
# 列出所有已注册AIDL HAL服务
adb shell dumpsys binder | grep camera
# 查看VINTF manifest是否加载正确
adb shell dumpsys vendor | grep camera.provider
正常输出能看到 internal/0 实例,失败=manifest.xml写错/rc未启动服务。
工具2:Logcat 分层日志过滤
bash
# 过滤CameraService Framework日志
adb logcat -b main CameraService:* *:S
# 过滤Vendor HAL层自定义日志(TAG:CAM_HAL)
adb logcat CAM_HAL:* *:S
# 过滤Binder AIDL调用事务日志
adb logcat Binder:* BpCamera:* BnCamera:* *:S
工具3:Perfetto 全链路性能追踪(你重点在用)
抓取要点(适配Android16 AIDL HAL)
- 数据源勾选:
binder transaction、camera、ftrace、v4l2、dmabuf - 可观测链路:
- App → CameraService Binder耗时
- CameraService → Vendor AIDL HAL Binder单次调用耗时(只有一套Binder,无HwBinder割裂)
- HAL内部V4L2 ioctl阻塞、buffer队列等待、DMA内存拷贝耗时
- 典型瓶颈:
submitCaptureRequestsBinder调用耗时过长、V4L2 poll阻塞、内存拷贝过多。
工具4:内核层V4L2调试工具
bash
# 查看摄像头V4L2设备节点
adb shell ls /dev/v4l-subdev* /dev/video*
# v4l2-ctl查看当前格式、帧率、buffer队列状态
adb shell v4l2-ctl -d /dev/video0 --get-fmt-video
adb shell v4l2-ctl --list-formats
# 查看内核CSI/ISP报错dmesg
adb shell dmesg | grep -E "camera|isp|csi|dvp|v4l2"
工具5:libcamera工具验证HAL可用性
bash
adb shell libcamera-hello
# 枚举摄像头能力
adb shell libcamera-list
如果libcamera能枚举,说明HAL服务注册、V4L2驱动基本正常,问题在上层Framework参数适配。
五、高频常见问题 + 根因 + 解决方案
问题1:打开相机提示无法连接相机,App闪退,dumpsys看不到HAL实例
根因
- vintf manifest.xml AIDL hal name/version写错;
- init.rc权限不足(缺少camera/graphics用户组);
- Android.bp未添加
vendor: true,编译进system分区,Treble拦截; - HAL进程crash,logcat有SIGSEGV空指针。
解决
- 核对manifest AIDL格式,HIDL写法全部删掉(Android16不兼容);
- rc文件group添加camera、graphics、drmrpc;
- bp强制
vendor:true,soc_specific:true; - logcat定位崩溃栈,修复空指针(大概率openCameraDevice返回空设备)。
问题2:摄像头枚举成功,configureStreams失败,预览黑屏
根因
- stream配置的分辨率/像素格式V4L2内核不支持;
- Gralloc buffer DMA内存分配失败,HAL无法映射buffer到内核;
- V4L2_STREAMON启动失败,ISP时钟/CSI硬件未上电。
解决
- 用
v4l2-ctl --list-formats只上报硬件支持的格式; - 依赖libgralloc,使用dmabuf fd传递缓冲区,避免用户态拷贝;
- dmesg排查ISP上电、时钟树、MIPI CSI配置。
问题3:拍照CaptureRequest下发无回调,CaptureResult不返回
根因
- HAL层ICameraDeviceCallback AIDL回调未触发;
- V4L2 DQBUF取帧阻塞,死锁;
- Metadata Result未填充有效数据回调给Framework。
解决
- 出队V4L2 buffer后主动调用
cb->notifyCaptureResult(); - V4L2 poll设置超时,防止无限阻塞;
- 必须填充ANDROID_SENSOR_TIMESTAMP等必填元数据。
问题4:预览卡顿、掉帧,Perfetto看到Binder耗时高
根因(Android16 AIDL HAL特有)
- CaptureRequest频繁大量AIDL Parcel序列化拷贝;
- HAL内同步阻塞ioctl占用Binder线程池;
- buffer频繁内存拷贝,未使用DMA零拷贝。
解决
- 耗时V4L2操作丢到独立工作线程,不占用Binder主线程;
- 使用dmabuf文件描述符跨进程传递buffer,零拷贝;
- 批量合并CaptureRequest,减少Binder事务次数。
问题5:Android16编译报错,提示HIDL接口找不到
根因
Android16完全移除HIDL库,旧项目依赖@3.5 HIDL接口直接编译失败。
解决
全部迁移为AIDL HAL,替换所有hidl-gen编译规则为aidl-gen,删除hwbinder依赖,全程使用标准binder。
问题6:前后摄切换卡死,CameraDevice关闭释放异常
根因
- V4L2文件句柄未close,fd泄漏;
- Binder强引用sp循环引用导致对象无法析构;
- buffer队列未flush,V4L2缓冲区未释放。
解决
- close接口中停止V4L2流、释放mmap buffer、close fd;
- 手动弱引用断开ICameraDeviceCallback;
- submit flush命令清空pending请求队列。
问题7:相机特性缺失(HDR、美颜、自动对焦App不显示)
根因
getCameraCharacteristics metadata关键字段未正确上报,Framework判定硬件不支持。
解决
对照AOSP camera_metadata_tags.h,完整填充对焦模式、AE模式、可用流配置、动态范围能力。
六、进阶优化点(车载/智能座舱场景,HiCar适配常用)
- 多摄像头并发:CameraProvider管理多个ICameraDevice实例,线程池隔离;
- 低功耗:Idle状态关闭ISP/CSI时钟,降低功耗;
- 360全景拼接:HAL层多目同步曝光、时间戳对齐,输出拼接后大图;
- 安全权限 :vendor sepolicy添加camera HAL对/dev/video、dmabuf、sysfs的访问权限(
device/vendor/sepolicy); - VNDK稳定性:所有对外接口使用NDK稳定库,禁止直接链接system私有库,避免大版本升级兼容断裂。
七、开源参考工程(直接对照仿写)
- AOSP默认参考HAL:
hardware/google/camera/aidl/(Google官方AIDL Camera HAL最简实现) - 第三方开源V4L2 Camera AIDL HAL:android-v4l2-camera-hal(github)
- 车载厂商参考:高通QCOM Camera HAL、瑞芯微RK Camera AIDL HAL(vendor目录下可扒逻辑)
如果你需要,我可以:
- 给你完整可直接编译的全套Android.bp + rc + manifest.xml文件;
- 或者给一份Perfetto抓取Camera AIDL Binder卡顿的pbtxt配置;
- 或者拆解车载360全景摄像头HAL同步逻辑。