Android - 摄像头 - hal - 开发教程,例子,常见问题,分析方法,解决方案

📅 2026/8/1 21:27:13 👁️ 阅读次数 📝 编程学习
Android - 摄像头 - hal - 开发教程,例子,常见问题,分析方法,解决方案

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 两个主流版本:

  1. Camera HAL3(AOSP标准,主流)android.hardware.camera.device@3.x,AIDL重构后为android.hardware.camera.deviceAIDL接口
  2. 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。

层级拆解

  1. App层:Camera2 API(CaptureRequest/CaptureResult)
  2. Framework层:CameraService、CameraProviderManager,向上AIDL,向下调用HAL
  3. AIDL HAL接口层:Google定义的标准AIDL接口(camera.provider/camera.device/camera.metadata)
  4. Vendor HAL实现层:厂商自研代码,对接V4L2内核驱动
  5. 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服务:

<halformat="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固定写法)

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:

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 核心接口实现(枚举摄像头)

#include<android/hardware/camera/provider/ICameraProvider.h>usingnamespace::android::hardware::camera::provider;classCameraProvider:publicICameraProvider{public:// 1. 获取当前所有摄像头ID(后置0、前置1)binder::StatusgetCameraIdList(std::vector<std::string>*outCameraIds)override{outCameraIds->clear();outCameraIds->push_back("0");// 后置主摄outCameraIds->push_back("1");// 前置副摄returnbinder::Status::ok();}// 2. 根据cameraId打开ICameraDevice设备binder::StatusopenCameraDevice(conststd::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=newCameraDevice(cameraId,cb);}else{returnbinder::Status::fromServiceSpecificError(-1);}returnbinder::Status::ok();}// 3. 注册Binder服务入口staticvoidregisterService(){sp<ICameraProvider>provider=newCameraProvider();::android::defaultServiceManager()->addService(String16("android.hardware.camera.provider/internal/0"),provider);}};// main函数,HAL服务入口intmain(){CameraProvider::registerService();::android::ProcessState::self()->startThreadPool();pause();return0;}

示例2:ICameraDevice 核心能力(下发CaptureRequest、V4L2取流)

核心需要实现的关键AIDL方法:

  1. getCameraCharacteristics():上报摄像头静态能力(分辨率、对焦、AE、HDR、传感器尺寸)
  2. configureStreams():配置预览/拍照流尺寸、格式(YUV_420_888、RAW、JPEG)
  3. submitCaptureRequests():下发上层CaptureRequest,驱动V4L2队列buffer、触发ISP拍照
  4. flush()/close():停止流、释放buffer、关闭V4L2设备节点

V4L2极简封装片段

intV4L2Wrapper::openDev(conststd::string&devPath){mFd=open(devPath.c_str(),O_RDWR);// 设置捕获格式 V4L2_PIX_FMT_YUV420structv4l2_formatfmt={};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缓冲区、入队bufferrequestBuffers();enqueueAllBuffers();// 启动捕获inttype=V4L2_BUF_TYPE_VIDEO_CAPTURE;ioctl(mFd,VIDIOC_STREAMON,&type);returnmFd;}

示例3:Camera Metadata 能力上报(决定App可用功能)

getCameraCharacteristics必须填充标准key,Framework校验不通过摄像头直接不可用:

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_tres[]={1920,1080};add_camera_metadata_array(chars,ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,res,2);

四、调试&问题定位全套分析方法(实操工具链)

工具1:dumpsys 查看HAL服务是否注册成功

# 查看camera provider AIDL HAL是否注册adb shell dumpsys android.hardware.camera.provider# 列出所有已注册AIDL HAL服务adb shell dumpsys binder|grepcamera# 查看VINTF manifest是否加载正确adb shell dumpsys vendor|grepcamera.provider

正常输出能看到internal/0实例,失败=manifest.xml写错/rc未启动服务。

工具2:Logcat 分层日志过滤

# 过滤CameraService Framework日志adb logcat-bmain 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)

  1. 数据源勾选:binder transactioncameraftracev4l2dmabuf
  2. 可观测链路:
    • App → CameraService Binder耗时
    • CameraService → Vendor AIDL HAL Binder单次调用耗时(只有一套Binder,无HwBinder割裂)
    • HAL内部V4L2 ioctl阻塞、buffer队列等待、DMA内存拷贝耗时
  3. 典型瓶颈:submitCaptureRequestsBinder调用耗时过长、V4L2 poll阻塞、内存拷贝过多。

工具4:内核层V4L2调试工具

# 查看摄像头V4L2设备节点adb shellls/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报错dmesgadb shelldmesg|grep-E"camera|isp|csi|dvp|v4l2"

工具5:libcamera工具验证HAL可用性

adb shell libcamera-hello# 枚举摄像头能力adb shell libcamera-list

如果libcamera能枚举,说明HAL服务注册、V4L2驱动基本正常,问题在上层Framework参数适配。


五、高频常见问题 + 根因 + 解决方案

问题1:打开相机提示无法连接相机,App闪退,dumpsys看不到HAL实例

根因

  1. vintf manifest.xml AIDL hal name/version写错;
  2. init.rc权限不足(缺少camera/graphics用户组);
  3. Android.bp未添加vendor: true,编译进system分区,Treble拦截;
  4. HAL进程crash,logcat有SIGSEGV空指针。

解决

  1. 核对manifest AIDL格式,HIDL写法全部删掉(Android16不兼容);
  2. rc文件group添加camera、graphics、drmrpc;
  3. bp强制vendor:true,soc_specific:true;
  4. logcat定位崩溃栈,修复空指针(大概率openCameraDevice返回空设备)。

问题2:摄像头枚举成功,configureStreams失败,预览黑屏

根因

  1. stream配置的分辨率/像素格式V4L2内核不支持;
  2. Gralloc buffer DMA内存分配失败,HAL无法映射buffer到内核;
  3. V4L2_STREAMON启动失败,ISP时钟/CSI硬件未上电。

解决

  1. v4l2-ctl --list-formats只上报硬件支持的格式;
  2. 依赖libgralloc,使用dmabuf fd传递缓冲区,避免用户态拷贝;
  3. dmesg排查ISP上电、时钟树、MIPI CSI配置。

问题3:拍照CaptureRequest下发无回调,CaptureResult不返回

根因

  1. HAL层ICameraDeviceCallback AIDL回调未触发;
  2. V4L2 DQBUF取帧阻塞,死锁;
  3. Metadata Result未填充有效数据回调给Framework。

解决

  1. 出队V4L2 buffer后主动调用cb->notifyCaptureResult()
  2. V4L2 poll设置超时,防止无限阻塞;
  3. 必须填充ANDROID_SENSOR_TIMESTAMP等必填元数据。

问题4:预览卡顿、掉帧,Perfetto看到Binder耗时高

根因(Android16 AIDL HAL特有)

  1. CaptureRequest频繁大量AIDL Parcel序列化拷贝;
  2. HAL内同步阻塞ioctl占用Binder线程池;
  3. buffer频繁内存拷贝,未使用DMA零拷贝。

解决

  1. 耗时V4L2操作丢到独立工作线程,不占用Binder主线程;
  2. 使用dmabuf文件描述符跨进程传递buffer,零拷贝;
  3. 批量合并CaptureRequest,减少Binder事务次数。

问题5:Android16编译报错,提示HIDL接口找不到

根因

Android16完全移除HIDL库,旧项目依赖@3.5 HIDL接口直接编译失败。

解决

全部迁移为AIDL HAL,替换所有hidl-gen编译规则为aidl-gen,删除hwbinder依赖,全程使用标准binder。

问题6:前后摄切换卡死,CameraDevice关闭释放异常

根因

  1. V4L2文件句柄未close,fd泄漏;
  2. Binder强引用sp循环引用导致对象无法析构;
  3. buffer队列未flush,V4L2缓冲区未释放。

解决

  1. close接口中停止V4L2流、释放mmap buffer、close fd;
  2. 手动弱引用断开ICameraDeviceCallback;
  3. submit flush命令清空pending请求队列。

问题7:相机特性缺失(HDR、美颜、自动对焦App不显示)

根因

getCameraCharacteristicsmetadata关键字段未正确上报,Framework判定硬件不支持。

解决

对照AOSPcamera_metadata_tags.h,完整填充对焦模式、AE模式、可用流配置、动态范围能力。


六、进阶优化点(车载/智能座舱场景,HiCar适配常用)

  1. 多摄像头并发:CameraProvider管理多个ICameraDevice实例,线程池隔离;
  2. 低功耗:Idle状态关闭ISP/CSI时钟,降低功耗;
  3. 360全景拼接:HAL层多目同步曝光、时间戳对齐,输出拼接后大图;
  4. 安全权限:vendor sepolicy添加camera HAL对/dev/video、dmabuf、sysfs的访问权限(device/vendor/sepolicy);
  5. VNDK稳定性:所有对外接口使用NDK稳定库,禁止直接链接system私有库,避免大版本升级兼容断裂。

七、开源参考工程(直接对照仿写)

  1. AOSP默认参考HAL:hardware/google/camera/aidl/(Google官方AIDL Camera HAL最简实现)
  2. 第三方开源V4L2 Camera AIDL HAL:android-v4l2-camera-hal(github)
  3. 车载厂商参考:高通QCOM Camera HAL、瑞芯微RK Camera AIDL HAL(vendor目录下可扒逻辑)

如果你需要,我可以:

  1. 给你完整可直接编译的全套Android.bp + rc + manifest.xml文件;
  2. 或者给一份Perfetto抓取Camera AIDL Binder卡顿的pbtxt配置
  3. 或者拆解车载360全景摄像头HAL同步逻辑。