4. Stream配置流程:从Framework到HAL的Stream配置请求下发链路
Stream配置请求的下发链路是Camera HAL层黑屏定位的核心分析路径。当上层应用请求打开相机并开始预览或拍照时,Framework会通过一系列IPC调用将Stream配置逐层传递至HAL层。理解这条链路上的每一个节点及其数据转换规则,是定位配置失败导致黑屏的前提。
4.1 链路全景:五层架构与关键接口
从Android Framework到HAL的Stream配置下发,共经历5个主要层级。每一层都有明确的职责和接口契约,任何一层的参数校验失败或转换错误,都会导致Stream无法正确创建,最终表现为黑屏。
关键认知: Stream配置不是一次性下发的,而是经过“应用层 → CameraService → CameraProvider → HAL”的逐层封装与校验。每一层都可能拒绝或修改配置,定位时需要逐层检查日志中的错误码与参数快照。
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
- Stream总数是否超过
- 转换动作: 将
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的
现象: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与
现象: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。
排查:检查
现象:HAL返回 -EINVAL,日志提示“CONSTRAINED_HIGH_SPEED mode requires at least 2 streams”。
根因:应用在高速模式(CONSTRAINED_HIGH_SPEED)下只配置了1个Stream。
排查:检查
operation_mode 与 num_streams 的匹配关系。
4.6 链路时序图
以下SVG图展示了从应用层到HAL层的完整调用时序,包含关键函数名和参数传递方向。建议将此图作为定位黑屏时的参考路线图。
4.7 定位检查清单
当遇到Stream配置失败导致的黑屏问题时,建议按照以下清单逐项排查,避免遗漏关键环节。
- 检查应用层日志: 确认
createCaptureSession()是否被正确调用,OutputConfiguration中的Surface是否有效。 - 检查CameraService日志: 搜索
configureStreams关键字,确认Stream列表是否被正确构建,是否有参数校验失败的错误。 - 检查CameraProvider日志: 确认HIDL/Binder调用是否成功,是否有IPC传输异常。
- 检查HAL适配层日志: 确认
configure_streams是否被调用,返回码是否为0。如果返回负数,根据错误码查阅HAL文档。 - 检查HAL驱动层日志: 确认硬件资源分配是否成功,是否有ISP或DMA相关的错误。
- 检查Stream参数快照: 在每一层打印完整的Stream参数(width、height、format、usage、max_buffers),对比各层之间的参数是否一致。
实用技巧: 在HAL的
configureStreams() 实现中,将接收到的 camera3_stream_configuration_t 以十六进制格式dump到日志中,可以快速发现参数在传输过程中是否被篡改。同时,对比 streams 指针数组中的每个 camera3_stream_t 的地址,确认指针映射是否正确。