4. Stream配置流程:从Framework到HAL的Stream配置请求下发链路

Stream配置请求的下发链路是Camera HAL层黑屏定位的核心分析路径。当上层应用请求打开相机并开始预览或拍照时,Framework会通过一系列IPC调用将Stream配置逐层传递至HAL层。理解这条链路上的每一个节点及其数据转换规则,是定位配置失败导致黑屏的前提。

4.1 链路全景:五层架构与关键接口

从Android Framework到HAL的Stream配置下发,共经历5个主要层级。每一层都有明确的职责和接口契约,任何一层的参数校验失败或转换错误,都会导致Stream无法正确创建,最终表现为黑屏。

关键认知: Stream配置不是一次性下发的,而是经过“应用层 → CameraService → CameraProvider → HAL”的逐层封装与校验。每一层都可能拒绝或修改配置,定位时需要逐层检查日志中的错误码与参数快照。
Stream配置下发链路全景 应用层 Camera2 API / Camera1 API CameraService createCaptureSession() CameraProvider ICameraDevice::configureStreams() HAL适配层 HAL3 / HAL1 接口 ① 应用层 通过CameraManager.createCaptureSession()传入 OutputConfiguration列表,包含Surface、尺寸、格式 ② CameraService 将OutputConfiguration转换为Camera3StreamList 校验Stream数量、尺寸对齐、格式兼容性 ③ CameraProvider 通过HIDL/Binder调用HAL的configureStreams() 传递camera3_stream_configuration_t结构体 ④ HAL适配层 解析Stream配置,分配硬件资源 返回状态码及调整后的Stream参数

4.2 核心数据结构:camera3_stream_configuration_t

在HAL层,Stream配置的核心载体是 camera3_stream_configuration_t 结构体。该结构体定义了所有需要配置的Stream的集合,以及操作模式。HAL的 configureStreams() 方法接收此结构体,并返回处理结果。

字段 类型 说明 常见错误
num_streams uint32_t Stream数量 值为0或超过HAL支持的最大值
streams camera3_stream_t** 指向Stream指针数组 空指针或无效地址
operation_mode uint32_t 操作模式(NORMAL / CONSTRAINED_HIGH_SPEED等) 模式与Stream组合不匹配

4.3 逐层下发流程详解

以下按照调用时序,详细拆解从Framework到HAL的每一步操作。定位黑屏问题时,建议在每一层的入口和出口处添加日志,记录Stream参数的完整快照。

4.3.1 应用层:创建CaptureSession

  • 调用入口: CameraDevice.createCaptureSession(sessionConfig)
  • 关键参数: OutputConfiguration 列表,每个配置包含 Surface、size、format、rotation 等。
  • 常见问题: 应用传入的Surface尺寸与相机传感器支持的输出尺寸不匹配;format指定了HAL不支持的像素格式。

4.3.2 CameraService:参数校验与转换

  • 核心方法: CameraDeviceClient::createStream() 和 Camera3Device::configureStreams()
  • 校验内容:
    • Stream总数是否超过 MAX_STREAMS(通常为3~4个)
    • 每个Stream的宽度/高度是否在传感器输出范围内
    • 格式是否在 availableStreamConfigurations 中声明
    • 是否有重复的Stream ID
  • 转换动作: 将 OutputConfiguration 转换为 camera3_stream_t 结构体,填充 stream_type、width、height、format、usage、max_buffers 等字段。

4.3.3 CameraProvider:HIDL/Binder IPC传输

  • 接口: ICameraDevice::configureStreams()(HIDL)或 ICameraDeviceUser::configureStreams()(Binder)
  • 数据序列化: 将 camera3_stream_configuration_t 打包为Parcel或HIDL的 StreamConfiguration 类型。
  • 关键风险点: IPC传输过程中,Stream指针地址会失效,HAL层接收到的指针是重新映射后的地址。如果HAL层错误地保存了指针地址并在后续使用,会导致野指针崩溃。

4.3.4 HAL适配层:configureStreams()实现

  • 入口函数: camera3_device_ops_t::configure_streams()
  • HAL职责:
    • 解析 camera3_stream_configuration_t 中的每个Stream
    • 检查硬件资源是否足够(ISP带宽、DMA通道、内存等)
    • 为每个Stream分配内部缓冲区队列和硬件路径
    • 返回 0 表示成功,返回负数表示失败(如 -EINVAL、-ENODEV、-ENOMEM)
  • 失败典型场景:
    • 请求的Stream尺寸组合超出ISP最大处理能力
    • 同时请求了过多高分辨率Stream导致带宽不足
    • 格式转换硬件不支持从传感器原始输出到目标格式的转换
定位陷阱: 部分HAL实现在 configureStreams() 返回成功(0)后,并未真正完成资源分配,而是在第一个buffer请求时才失败。这种情况下,黑屏现象会在startStreaming之后才出现,容易误导排查方向。建议在HAL的 configureStreams() 和 processCaptureRequest() 入口处都增加完整的Stream状态日志。

4.4 关键日志节点与排查方法

在定位Stream配置失败时,以下日志节点是必须检查的。建议在调试版本中开启所有相关层的详细日志。

层级 日志Tag 关键日志内容 排查要点
应用层 Camera2Client / Camera createCaptureSession, OutputConfiguration 检查Surface尺寸和format是否合法
CameraService Camera3Device configureStreams, stream_list, num_streams 确认Stream数量和各Stream参数
CameraProvider CameraProvider / HIDL configureStreams, status, error_code 检查IPC传输是否成功,状态码含义
HAL适配层 CameraHAL / camx / mm-camera configure_streams, stream_config, resource_alloc 确认HAL返回码,检查资源分配日志

4.5 典型失败场景与根因分析

基于实际项目经验,以下列出Stream配置下发链路中最常见的三种失败场景,以及对应的根因和排查方向。

场景一:Stream尺寸组合超出ISP能力
现象:HAL的configureStreams()返回 -EINVAL,日志显示“unsupported stream size combination”。
根因:应用同时请求了4K预览 + 4K录像 + 2K拍照,ISP单帧处理带宽不足。
排查:检查HAL的 stream_configuration_map 中声明的最大组合限制。
场景二:Format不匹配
现象:CameraService层日志显示“format 0x22 not supported”。
根因:应用请求了YV12格式,但HAL只支持NV12和NV21。
排查:对比应用请求的format与 availableStreamConfigurations 中的format列表。
场景三:operation_mode与Stream冲突
现象:HAL返回 -EINVAL,日志提示“CONSTRAINED_HIGH_SPEED mode requires at least 2 streams”。
根因:应用在高速模式(CONSTRAINED_HIGH_SPEED)下只配置了1个Stream。
排查:检查 operation_mode 与 num_streams 的匹配关系。

4.6 链路时序图

以下SVG图展示了从应用层到HAL层的完整调用时序,包含关键函数名和参数传递方向。建议将此图作为定位黑屏时的参考路线图。

Stream配置下发时序图 App CamService CamProvider HAL Adapter HAL Driver createCaptureSession() configureStreams() configureStreams() sensor_config() status status status status 时序要点 1. 每一层调用都是同步阻塞的,HAL返回前CameraService会等待。 2. 如果HAL在configureStreams()中耗时过长(>5s),CameraService会触发ANR。 3. 返回status为0表示成功,负数表示失败,具体错误码需查阅HAL实现文档。

4.7 定位检查清单

当遇到Stream配置失败导致的黑屏问题时,建议按照以下清单逐项排查,避免遗漏关键环节。

  1. 检查应用层日志: 确认 createCaptureSession() 是否被正确调用,OutputConfiguration 中的Surface是否有效。
  2. 检查CameraService日志: 搜索 configureStreams 关键字,确认Stream列表是否被正确构建,是否有参数校验失败的错误。
  3. 检查CameraProvider日志: 确认HIDL/Binder调用是否成功,是否有IPC传输异常。
  4. 检查HAL适配层日志: 确认 configure_streams 是否被调用,返回码是否为0。如果返回负数,根据错误码查阅HAL文档。
  5. 检查HAL驱动层日志: 确认硬件资源分配是否成功,是否有ISP或DMA相关的错误。
  6. 检查Stream参数快照: 在每一层打印完整的Stream参数(width、height、format、usage、max_buffers),对比各层之间的参数是否一致。
实用技巧: 在HAL的 configureStreams() 实现中,将接收到的 camera3_stream_configuration_t 以十六进制格式dump到日志中,可以快速发现参数在传输过程中是否被篡改。同时,对比 streams 指针数组中的每个 camera3_stream_t 的地址,确认指针映射是否正确。