312.Camera HAL3 接口层源码解析:createSession 与 configureStreams 全流程剖析
Camera HAL3 接口层源码解析:createSession 与 configureStreams 全流程剖析
关键词:
Camera HAL3、createSession、configureStreams、Session 接口、流配置、设备适配、AIDL/HIDL、CameraDeviceSession、实际调用链
摘要:
Camera HAL3 是 Android 图像系统中连接 Framework 与底层硬件的关键桥梁。无论是 AIDL 还是 HIDL 模式,App 的一次 openCamera 实际上最终都会调用到 HAL3 接口中的 createSession() 与 configureStreams(),完成 CameraDeviceSession 的构建与流的初始化。本篇将基于 AOSP 最新主线版本,结合典型厂商实现,深入拆解 Camera HAL3 接口调用链、流配置过程、结构体构成与平台差异,帮助工程师理解调试路径与稳定性优化的核心关键点。
目录
一、Camera HAL3 接口结构总览:从 ICameraDevice → HALModule → HAL3Wrapper 架构解读
二、createSession 调用路径解析:如何构建 CameraDeviceSession 并与 Framework 接口对齐
三、CameraDeviceSession 的核心职责:HAL 会话持久化、请求调度与通知传导
四、configureStreams 接口结构详解:CameraStreamConfiguration 的字段构成与 stream 映射机制
五、Stream ID、方向、格式、usage 与 bufferQueue 的绑定逻辑
六、厂商自定义行为分析:configure 中的延迟初始化、动态资源绑定与私有流支持
七、常见失败场景解析:createSession 返回错误、configure 崩溃、stream 配置不一致
八、调试建议与验证路径:logcat、atrace、dumpsys camera + HAL 层 log 的联合分析技巧
一、Camera HAL3 接口结构总览:从 ICameraDevice → HALModule → HAL3Wrapper 架构解读
在 Android Camera 框架中,HAL3(Camera Hardware Abstraction Layer v3)是 Framework 与硬件驱动的直接桥梁,主要负责 会话创建、流配置、请求处理与结果回调。该接口设计遵循模块化与面向对象原则,通过 ICameraDevice 接口与上层对接,并通过 HALModule 与 HAL3Wrapper 将最终调用分派至厂商自定义实现。
1.1 HAL3 接口的核心对象
-
ICameraDevice
定义在hardware/interfaces/camera/device下,负责管理单个 Camera 设备的生命周期及会话创建。 -
Camera HAL Module (camera_module_t)
位于/hardware/libhardware/include/hardware/camera_common.h,是 HAL 的模块入口。
其中open方法用于打开 Camera 设备并返回camera3_device_t。 -
camera3_device_t 与 camera3_device_ops
camera3_device_t代表底层 Camera 设备的实例,内部包含指向 HAL3 操作集合camera3_device_ops的指针,例如:struct camera3_device_ops { int (*initialize)(...); int (*configure_streams)(...); int (*process_capture_request)(...); ... }; -
HAL3Wrapper
在部分平台中,Framework 会通过 HAL3Wrapper 层封装对 HAL3 的调用,以便实现兼容性、调试插桩或多 HAL 合并。
1.2 HAL3 接口初始化与绑定链路
调用链从 App 发起 CameraManager.openCamera() 开始,经由以下流程进入 HAL3:
CameraManager → CameraService → CameraProvider → ICameraDevice
→ Camera HAL Module (camera_module_t)
→ HAL3Wrapper (可选)
→ Vendor Camera3 HAL (camera3_device_ops)
关键动作:
- CameraService 从 Provider 获取
ICameraDevice实例; - 调用
ICameraDevice::open()打开 HAL 设备; - HAL3Wrapper 初始化并包装底层
camera3_device_t; - 等待上层发起
createSession()及configureStreams()。
二、createSession 调用路径解析:如何构建 CameraDeviceSession 并与 Framework 接口对齐
createSession() 是 HAL3 中连接 Framework 与 HAL 的核心接口,用于构建一个 CameraDeviceSession 实例。该实例承载 流配置(Stream Configuration)、请求下发(processCaptureRequest)、结果回调(processCaptureResult) 等操作。
2.1 调用链分解
-
应用层发起连接
CameraManager.openCamera(cameraId, stateCallback, handler)内部通过 AIDL 调用 CameraService。
-
CameraService 建立 Client
CameraService::connectDevice() → CameraDeviceClient::initialize() -
Provider 调用 createSession
ICameraDevice::createSession()这是 HAL3 接口的入口点,由厂商 HAL 实现。
-
返回 CameraDeviceSession
createSession 完成后返回ICameraDeviceSession接口,Framework 将通过该接口调用configureStreams()、processCaptureRequest()等方法。
2.2 createSession 的核心职责
- 分配 HAL 会话资源:包括硬件队列、ISP pipeline 和 buffer 池;
- 绑定回调接口:Framework 提供
ICameraDeviceCallback,用于 HAL 向上报送帧完成、错误状态等事件; - 初始化静态信息:在会话创建时读取 sensor 能力、可用 stream 格式等信息并缓存。
2.3 createSession 在源码中的关键逻辑
在 AIDL 模式下,createSession 定义于:
hardware/interfaces/camera/device/aidl/ICameraDevice.aidl
典型厂商实现伪代码:
Status CameraDevice::createSession(
const shared_ptr<ICameraDeviceCallback>& callback,
shared_ptr<ICameraDeviceSession>* session) {
mSession = ndk::SharedRefBase::make<CameraDeviceSession>(callback);
*session = mSession;
return Status::ok();
}
2.4 调试与验证建议
- 使用
logcat -s CameraProvider CameraService查看 createSession 是否成功; - 若 createSession 阻塞,需检查 HAL 初始化逻辑是否存在硬件 I/O 等耗时操作;
- 使用
dumpsys media.camera确认 Session 是否已注册到 CameraService。
三、CameraDeviceSession 的核心职责:HAL 会话持久化、请求调度与通知传导
在 HAL3 架构下,CameraDeviceSession 是 Framework 与 HAL 通信的核心工作单元。自 createSession() 调用成功后,系统便创建出一个独立的 HAL 会话实例,在整个相机生命周期内维持该会话对象的有效性,直到 App 释放或系统回收。
3.1 会话的职责边界
- 请求处理入口
接收上层 Framework 下发的processCaptureRequest()请求,完成参数解析、流匹配、Buffer 准备与驱动下发。 - 结果回调传导
从底层驱动接收帧完成信号后,封装成CaptureResult向ICameraDeviceCallback汇报。 - 流管理与资源释放
对生命周期内的所有流(Preview、JPEG、Metadata 等)统一管理,包括创建、关闭、异常恢复。 - 错误回调与状态维护
在设备失联、流失败等场景下触发notify()回调,保障系统稳定性。
3.2 Session 的典型结构(以 AIDL 实现为例)
class CameraDeviceSession : public BnCameraDeviceSession {
public:
Status configureStreams(...);
Status processCaptureRequest(...);
void notify(const NotifyMsg&);
...
private:
std::map<int, HalStream> mStreams;
std::shared_ptr<CallbackInterface> mCallback;
};
3.3 生命周期与同步要求
- 每个 Session 对象只服务一个 CameraId;
- 不支持多客户端并发连接(通过 Binder UID 限制);
- 调用
close()会触发 stream 销毁与内存释放,需完整对齐上层状态。
四、configureStreams 接口结构详解:CameraStreamConfiguration 的字段构成与 stream 映射机制
configureStreams() 是 HAL 与上层协商流能力、格式支持与 Buffer 管理策略的关键接口。无论是首次 openCamera 还是切换分辨率、变更 OutputSurface,最终都将调用该接口重新配置流链路。
4.1 configureStreams 的定义与调用链
- 上层触发时机:首次 open、切换分辨率、增加 OutputSurface;
- 下发路径:
CameraDeviceClient→CameraDeviceSession::configureStreams()→ Vendor HAL
配置对象结构(AIDL):
struct Stream {
int id;
int width;
int height;
PixelFormat format;
StreamType streamType; // OUTPUT, BIDIRECTIONAL
Usage usage; // CPU_READ, GPU_TEXTURE, etc.
...
};
struct CameraStreamConfiguration {
std::vector<Stream> streams;
OperationMode operationMode;
StreamConfigurationMode streamConfigMode;
};
4.2 HAL 内部流映射结构
厂商 HAL 需将 Stream 映射为硬件资源,如 ISP 路径、DMA 输出通道等:
std::map<int /* stream id */, HalStream> mStreamMap;
struct HalStream {
buffer_handle_t bufferPool;
int maxBuffers;
int physicalCameraId;
// Format translation, rotation, etc.
};
4.3 配置成功与否判断标准
- 返回状态必须为 OK;
- 每个 stream 都需映射到一个合法的输出路径;
- 若不支持组合,需返回
Status::ILLEGAL_ARGUMENT,上层重新配置。
4.4 实战问题典型场景
- stream id 重复:多个 Preview 使用同 id;
- 不支持的格式:如 YUV_420_888 不被平台支持;
- 高分辨率流失败:超过 ISP 或 DMA 带宽;
- Jpeg 与 Video 混用崩溃:部分平台不支持异构流并发。
4.5 调试建议
- 打印 HAL 层 stream config 接口的 format/size,确认与上层一致;
- 使用
dumpsys media.camera查看当前流状态; - 加入
ATRACE_CALL()统计configureStreams()时间,判断耗时瓶颈; - 开启 vendor logcat(如
vendor.camera.hal)确认流映射异常点。
五、Stream ID、方向、格式、usage 与 bufferQueue 的绑定逻辑
在 HAL3 的 configureStreams() 流程中,每个 Stream 配置项都需要映射到底层硬件资源,这一过程涉及 Stream ID、方向(输入/输出)、格式、使用场景(usage)与 BufferQueue 的准确绑定。这个过程是 HAL 对上层能力宣称的核心体现,也是实现 Preview、Video、Snapshot 等功能稳定性的基础。
5.1 Stream ID 与内部资源映射
-
每个
Stream会在 Framework 分配一个唯一的streamId,HAL 层需根据该 ID 建立与内部结构的映射关系。 -
HAL 可使用 map 或 vector 保存流结构,例如:
std::unordered_map<int, HalStream> mStreamMap;
5.2 StreamType 与方向约定
StreamType::OUTPUT是主流方向(Preview、Video、Jpeg)StreamType::INPUT一般用于 Reprocessing(如 Zero Shutter Lag)StreamType::BIDIRECTIONAL适用于 Camera2 legacy HAL
方向关系影响 BufferQueue 的建立与访问策略(如 CPU 写 vs GPU 读)。
5.3 格式匹配与转换策略
上层传入格式类型为 HAL PixelFormat 枚举,如:
| 上层 Format (PixelFormat) | HAL 内部格式映射 |
|---|---|
| YUV_420_888 | NV12 / NV21 / FLEXIBLE_YUV |
| JPEG | BLOB + EXIF 封装 |
| RAW10 / RAW_SENSOR | MIPI RAW + ISP Pass-through |
厂商 HAL 通常会定义内部 format 类型,进行一次 format adapter 转换。
5.4 Usage 语义与 Buffer 属性
Usage 决定了 Buffer 的申请属性,常见组合:
CPU_READ | GPU_TEXTURE:Preview 流,SurfaceView + GPU 后处理VIDEO_ENCODER:MediaCodec 对接时的硬编码流CPU_READ_OFTEN:App 端直接访问 buffer 内容(风险大)ZSL_INPUT | HW_CAMERA_ZSL:Zero Shutter Lag 输入流
使用 gralloc 申请时,这些 usage 会传递给 buffer allocator,用于决定 buffer flags。
5.5 bufferQueue 与 Stream 的绑定流程
- 上层将 Surface 封装为
ANativeWindow,调用 CameraDevice → setRepeatingRequest - CameraService 通过 HAL session 的
configureStreams,为每个 stream 绑定其对应的 buffer queue - HAL 实现调用
GraphicBufferAllocator或BufferHub分配对应的 buffer pool - stream ID 被映射为 hardware_pipe_id × usage_flags × format 的组合逻辑
// 典型 HAL 实现示例
for (const Stream& s : config.streams) {
halStream.id = s.id;
halStream.format = ConvertFormat(s.format);
halStream.usage = ConvertUsage(s.usage);
halStream.bufferQueue = CreateGrallocQueue(halStream.usage, halStream.format);
}
六、厂商自定义行为分析:configure 中的延迟初始化、动态资源绑定与私有流支持
在实际平台实现中,不同厂商对 configureStreams() 的处理存在较大差异,除了标准流程外,很多 HAL 实现引入了延迟初始化、动态资源绑定以及对私有流(Private Stream Type)的特殊支持逻辑。
6.1 延迟初始化策略
出于性能优化或硬件资源保护目的,部分平台将如下动作推迟执行:
- Sensor pipeline 初始化
- ISP 通道激活
- Stream buffer queue 实体创建
这些动作在 configureStreams() 中记录,但不立即执行,等到 processCaptureRequest() 或 requestStreamBuffers() 时再触发实际分配。
优点:冷启动快、资源只在使用时激活
风险:首次请求会卡顿或时序异常
6.2 动态资源绑定逻辑
当平台拥有多个 ISP / DMA / Pipe 资源通道时,可能在 configureStreams() 中根据需求进行如下行为:
- 流类型与目标分辨率匹配最优 pipeline
- 根据场景(人像、HDR、夜景)启用不同 Sensor Mode
- 动态构建
sensor_output → ISP → memory_node路径
部分高端平台使用 DSL(描述式配置表)定义每类 stream 的绑定策略。
6.3 私有流类型与扩展机制
有些厂商引入了自定义的 stream type,用于特定用途:
- Meta Dump 流:输出调试用 metadata
- IR 辅助流:用于夜拍 / 安防模式的红外图像
- Sensor Statistics 流:专用于 AE/AWB/AF 的调试与学习
- HDR Fusion Raw 流:只对内部算法开放的多帧原始数据
私有流通过 vendor tag 或 vendor usage flag 实现,通常不会暴露在标准 getCameraCharacteristics() 接口中。
6.4 工程调试建议
- 使用
dumpsys media.camera查看 configure 时流结构是否生效; - 使用
atrace --async_start -c gfx view camera捕捉首次请求过程中的延迟; - 查看
vendor.camera.hallog,确认是否存在延迟 buffer allocate 行为; - 注意 check
frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp中stream->isConfigurable()与maybeClose()的状态流转。
七、常见失败场景解析:createSession 返回错误、configure 崩溃、stream 配置不一致
在 Camera HAL3 实际工程中,createSession() 与 configureStreams() 常被视为系统最敏感、最易失败的路径之一。由于该阶段涉及 HAL 模块初始化、buffer 映射、Sensor 通路开启等多个底层资源协同,一旦配置异常,将直接导致摄像头不可用或系统 crash。以下总结开发者常见的失败模式及其排查建议:
7.1 createSession 返回错误码
- 返回
STATUS_INTERNAL_ERROR或STATUS_INVALID_OPERATION:- HAL 实现未成功构造
CameraDeviceSessionImpl实例; - HAL 与 CameraService 的接口签名不一致,导致 binder 交互失败;
- camera HAL 进程 crash 后重启未完成,导致 session 创建失败;
- 建议排查:
logcat | grep CameraProvider+dmesg | grep camera;- 检查 HAL 中
new CameraDeviceSession()是否有异常逻辑分支。
- HAL 实现未成功构造
7.2 configureStreams 阶段直接崩溃或挂死
-
现象: 调用 configure 时 ANR、HAL SIGSEGV、线程卡住;
-
典型根因:
- stream array 中格式 / usage 不在 HAL 支持列表;
- HAL 内部资源未准备完毕(未能绑定 Sensor/ISP 节点);
- 多线程竞争资源锁,导致死锁;
- Stream 重复配置或 ID 冲突(特别是在 rapid switch 场景中);
-
案例:
E Camera3Device: configureStreamsLocked: Stream 3 failed to create. E Camera3Device: configureStreamsLocked: HAL returned error 1- 表示某一 stream 创建失败,HAL 返回失败码。
7.3 Stream 配置不一致导致上层异常
- 错误表现:
- configure 成功,但后续下发 request 时提示 stream invalid;
- App 层报错:
CameraAccessException: Illegal stream combination;
- 常见原因:
- HAL 未正确返回 streamConfiguration 的最终格式 / usage;
- HAL 只部分创建流结构,CameraService 判断不一致;
- App 使用了重复 Surface(同一个 Surface 绑定多个用途);
- 建议:
- 关注
configureStreams()返回的StreamConfiguration::streams与原始请求是否一致; - 加入 HAL 层对每个 stream 的 ID、格式、大小的 log 输出,方便核对。
- 关注
7.4 其他失败典型场景
| 现象 | 根因示例 | 调试建议 |
|---|---|---|
| createSession 成功但后续无法下发请求 | HAL Session 构造成功但未初始化流管理器 | 检查 HAL 中初始化流程是否完整 |
| configure 成功但 App 黑屏无预览 | HAL 分配了 buffer 但未触发 preview 输出 | 检查 HAL 是否触发 request loop |
| configure 成功后调用 disconnect 崩溃 | stream 清理顺序不当,bufferPool 被提前释放 | 增加 HAL 中 clear/flush 守护逻辑 |
八、调试建议与验证路径:logcat、atrace、dumpsys camera + HAL 层 log 的联合分析技巧
由于 HAL 层源码难以全部掌控,工程调试过程需要利用系统提供的各类可观测路径。以下是调试 Camera HAL 初始化链路的建议组合方式:
8.1 logcat:首选日志通路
重点关注模块:
CameraProviderLifecycle:设备服务状态变化CameraService:服务创建 / Client 创建 / configure 日志Camera3Device:configure 流程与 request 提交CamX/QCamera3HWI(高通)或mHal/ImxCamera(MTK)等厂商 HAL log tag
建议命令:
logcat | grep -E "Camera|HAL3|CameraService"
8.2 dumpsys camera:查看当前状态与上一次错误信息
常用命令:
dumpsys media.camera
重点字段:
Number of camera devices: N:是否识别完整设备Camera ID下的stream configuration区块:每个 stream 的 format、size、usageLast error: <timestamp>:CameraService 记录的最后一个错误Disconnected clients::最近一次挂起连接的 UID 和调用栈
8.3 atrace:全路径时序分析
场景:调试冷启动慢、首次 request 卡顿、configure 后长时间无响应
使用方式:
atrace --async_start -c gfx view camera hal camera_provider
# 重现问题后
atrace --async_stop -o trace_camera.html
可视化打开后,重点观察:
CameraService::connectDevice→createSession→configureStreams→submitRequest- HAL 中对应线程是否存在长时间阻塞(红块)
8.4 HAL 层 log 与 debug trace(厂商自定义)
- 高通平台:开启
persist.vendor.camera.debug.logfile=1并抓取/data/vendor/camera/hal.log - MTK 平台:查看
/dev/log/camera_log或 logcat 中mHal输出 - 建议将每次
createSession和configure的关键参数打印完整,包含 stream count、format、size、usage。
8.5 工程建议总结
| 调试目标 | 推荐工具组合 |
|---|---|
| HAL 初始化失败 | logcat + dmesg + dumpsys camera |
| configure 卡顿 | atrace + vendor HAL log |
| Stream 映射错误 | HAL log 中打印 format/size/usage + dumpsys 对比 |
| App 黑屏无预览 | dumpsys + dumpsys SurfaceFlinger + logcat |
| Session 不释放/死锁 | logcat 死亡监听打印 + binder 调用跟踪 |
312.Camera HAL3 接口层源码解析:createSession 与 configureStreams 全流程剖析
http://114.132.213.38:6250/archives/1754201638242
评论