3. HAL 接口详解:ICameraProvider、ICameraDevice、ICameraDeviceSession 核心接口分析

在 Android Camera HAL 架构中,ICameraProvider、ICameraDevice 和 ICameraDeviceSession 是三个最核心的接口,它们构成了 HAL 层与 Camera Framework 之间的通信骨架。理解这三个接口的职责、生命周期以及关键方法,是实现自定义美颜与滤镜算法的基础。本章将逐一剖析每个接口的核心方法、调用时序以及典型实现模式。

架构概览: 这三个接口遵循严格的层级关系:Provider 管理设备发现与生命周期,Device 代表单个物理或逻辑相机设备,Session 负责处理具体的图像捕获与请求流。美颜与滤镜算法主要在 Session 层的 processCaptureRequest 中注入。
Camera HAL 三层接口架构图 ICameraProvider 设备发现 / 生命周期管理 ICameraDevice 单个相机设备 / 配置流 ICameraDeviceSession 请求处理 / 图像捕获 / 美颜滤镜注入 美颜与滤镜算法主要在 Session 层的 processCaptureRequest 中实现

3.1 ICameraProvider 接口:设备发现与生命周期管理

ICameraProvider 是 HAL 层暴露给 Camera Framework 的入口点。它负责枚举系统中可用的相机设备,并管理这些设备的生命周期。在 Treble 架构下,Provider 运行在独立的 HAL 进程中,通过 HIDL / AIDL 与 Framework 通信。

3.1.1 核心方法

方法名 返回值 描述
getCameraIdList() std::vector<std::string> 返回所有可用相机设备的 ID 列表,如 ["0", "1", "2"]
getCameraDeviceInterface() ICameraDevice 根据 cameraId 返回对应的 ICameraDevice 实例
setCallback() Status 注册 ICameraProviderCallback,用于通知 Framework 设备状态变化
isSetTorchModeSupported() bool 查询是否支持手电筒模式

3.1.2 典型实现模式

// ICameraProvider 典型实现片段
Return<Status> CameraProvider::getCameraDeviceInterface(
    const std::string& cameraId,
    sp<ICameraDevice>* device) {
    // 1. 校验 cameraId 是否合法
    if (cameraId != "0" && cameraId != "1") {
        return Status::ILLEGAL_ARGUMENT;
    }
    // 2. 创建或返回已有的 ICameraDevice 实例
    *device = new CameraDevice(cameraId);
    return Status::OK;
}

Return<Status> CameraProvider::setCallback(
    const sp<ICameraProviderCallback>& callback) {
    // 保存回调,用于设备热插拔通知
    mCallback = callback;
    return Status::OK;
}
美颜开发要点: 在 Provider 层不需要实现任何图像处理逻辑。但如果你需要支持多摄像头(如前置美颜 + 后置滤镜),需要在 getCameraIdList() 中正确枚举所有物理和逻辑相机 ID。

3.2 ICameraDevice 接口:相机设备配置与流管理

ICameraDevice 代表一个具体的相机设备(物理或逻辑)。它负责提供相机静态信息、配置输出流,并创建用于实际捕获的 ICameraDeviceSession。美颜与滤镜算法所需的图像尺寸、格式配置都在此阶段确定。

3.2.1 核心方法

方法名 返回值 描述
getResourceCost() CameraResourceCost 返回相机设备的资源消耗信息,用于多摄像头协同
getCameraCharacteristics() CameraMetadata 返回相机静态元数据,如传感器尺寸、支持的分辨率、AE/AWB 范围等
open() Status 打开相机设备,返回 ICameraDeviceSession 实例
dumpState() void 导出调试状态信息

3.2.2 流配置与 Session 创建

open() 方法是 Device 层最关键的调用。Framework 在调用 open() 之前,会先通过 getCameraCharacteristics() 获取设备能力,然后配置输出流(如预览流、拍照流、视频流)。open() 的实现需要根据这些流配置创建对应的 Session。

// ICameraDevice::open() 典型实现
Return<Status> CameraDevice::open(
    const sp<ICameraDeviceCallback>& callback,
    sp<ICameraDeviceSession>* session) {
    // 1. 检查设备是否已被占用
    if (mIsOpened) {
        return Status::CAMERA_IN_USE;
    }
    // 2. 创建 Session,传入回调用于通知 Framework 捕获结果
    *session = new CameraDeviceSession(callback, mCameraId);
    mIsOpened = true;
    return Status::OK;
}
ICameraDevice → ICameraDeviceSession 流配置流程 getCharacteristics() 配置输出流 open() 创建 Session ICameraDeviceSession 就绪,等待请求 美颜滤镜所需的输出尺寸、格式在“配置输出流”阶段确定,需与 Session 协商一致
常见陷阱: 在 open() 中不要执行耗时操作(如初始化美颜模型)。Session 创建应轻量快速,真正的资源初始化应延迟到 Session 的 processCaptureRequest 第一次调用时进行。

3.3 ICameraDeviceSession 接口:请求处理与图像捕获核心

ICameraDeviceSession 是美颜与滤镜算法实现的主战场。它负责接收来自 Framework 的捕获请求(CaptureRequest),处理图像数据,并通过回调返回结果。所有像素级的处理逻辑都在此接口的方法中实现。

3.3.1 核心方法

方法名 返回值 描述
processCaptureRequest() Status 处理单个捕获请求,包含输出缓冲区、元数据、物理相机设置
flush() Status 清空所有待处理的请求队列,用于快速关闭或切换模式
close() Status 关闭 Session,释放所有资源
configureStreams() Status 配置输入/输出流,包括分辨率、格式、使用场景(预览/拍照/录像)
signalStreamFlush() Status 通知特定流需要刷新缓冲区

3.3.2 processCaptureRequest 深度解析

processCaptureRequest 是 HAL 层最核心的方法,也是美颜与滤镜算法的注入点。它的输入参数包含:

  • CaptureRequest:包含请求 ID、输出缓冲区列表、输入缓冲区(ZSL 模式)、元数据(AE/AWB/AF 设置、3A 状态等)
  • BufferRequest:描述每个输出流的缓冲区句柄、宽度、高度、格式、使用场景
  • PhysicalCameraSettings:逻辑相机模式下,每个物理相机的单独设置
// processCaptureRequest 典型实现骨架
Return<Status> CameraDeviceSession::processCaptureRequest(
    const std::vector<CaptureRequest>& requests,
    const std::vector<BufferRequest>& bufRequests,
    /* 其他参数 */) {

    for (size_t i = 0; i < requests.size(); i++) {
        const auto& request = requests[i];
        const auto& bufReq = bufRequests[i];

        // 1. 获取输出缓冲区
        sp<GraphicBuffer> outBuffer = bufReq.outputBuffers[0].buffer;

        // 2. 获取输入图像数据(来自 Sensor)
        //    实际项目中需要从 DMA 或 GPU 纹理中读取

        // 3. 【美颜/滤镜算法注入点】
        //    对图像数据执行美颜处理(磨皮、美白、瘦脸等)
        //    或滤镜处理(色彩矩阵变换、LUT 映射等)
        applyBeautyFilter(inputData, outputData, request.settings);

        // 4. 填充结果元数据
        CameraMetadata resultMetadata;
        resultMetadata.update(ANDROID_SENSOR_TIMESTAMP, timestamp);
        resultMetadata.update(ANDROID_CONTROL_AE_STATE, AE_STATE_CONVERGED);

        // 5. 通过回调返回结果
        mCallback->processCaptureResult({
            .frameNumber = request.frameNumber,
            .result = std::move(resultMetadata),
            .outputBuffers = { {outBuffer, /* status */ OK} }
        });
    }
    return Status::OK;
}

3.3.3 美颜算法在 Session 中的生命周期

美颜算法在 ICameraDeviceSession 中的处理流程 接收 CaptureRequest 解析元数据 获取图像缓冲区 执行美颜/滤镜算法 填充结果元数据 回调返回结果 美颜算法执行时需注意帧率稳定性,建议使用 GPU 或 DSP 加速,避免阻塞 processCaptureRequest

3.4 三个接口的协作时序

理解三个接口的协作时序对于正确实现 HAL 至关重要。以下是一个典型的相机打开 → 预览 → 拍照 → 关闭的完整时序:

  1. Framework 调用 ICameraProvider::getCameraIdList() 获取可用设备列表
  2. Framework 调用 ICameraProvider::getCameraDeviceInterface("0") 获取 Device 实例
  3. Framework 调用 ICameraDevice::getCameraCharacteristics() 获取设备能力
  4. Framework 配置输出流(预览 1080p、拍照 4K)
  5. Framework 调用 ICameraDevice::open() 创建 Session
  6. Session 调用 configureStreams() 确认流配置
  7. Framework 持续调用 processCaptureRequest() 发送预览请求
  8. Session 在 processCaptureRequest() 中执行美颜/滤镜 并返回结果
  9. Framework 调用 flush() 清空请求队列
  10. Framework 调用 close() 关闭 Session 和 Device
性能关键点: 美颜算法应尽量在 processCaptureRequest 的同步路径中完成,避免引入额外的线程切换开销。如果算法耗时较长(如 > 16ms 导致预览掉帧),应考虑使用 HAL 层的 requestStreamBuffers 机制进行异步处理。

3.5 接口实现注意事项

接口 注意事项 美颜/滤镜相关
ICameraProvider 必须正确处理设备热插拔;返回的 cameraId 必须与 getCameraCharacteristics 一致 多摄像头场景下需正确枚举逻辑相机与物理相机
ICameraDevice open() 必须幂等;getCameraCharacteristics 返回的元数据必须准确 在元数据中声明支持的美颜/滤镜能力(如 ANDROID_REQUEST_AVAILABLE_CAPABILITIES)
ICameraDeviceSession processCaptureRequest 必须线程安全;flush() 必须快速返回 美颜参数可通过 CaptureRequest 的元数据传递(如自定义 vendor tag)
重要提醒: 在实现自定义美颜与滤镜算法时,不要修改 ICameraProvider 和 ICameraDevice 的接口定义。所有算法逻辑应封装在 ICameraDeviceSession 内部,通过标准的 processCaptureRequest 接口与 Framework 交互。这样可以保证 HAL 的兼容性和可维护性。