2. HAL3接口定义:ICameraDevice.hal与ICameraDeviceSession.hal的核心接口方法
在Android Camera HAL3架构中,ICameraDevice.hal和ICameraDeviceSession.hal是连接Framework与HAL实现的核心契约。前者负责设备级别的生命周期管理与流配置,后者负责具体Capture请求的提交与结果回调。理解这两个接口的核心方法,是掌握Camera3Device初始化流程的关键前提。
关键认知:ICameraDevice相当于“相机设备管理器”,ICameraDeviceSession相当于“一次拍照会话的工作引擎”。Framework通过ICameraDevice打开设备并创建Session,之后所有拍照操作都通过ICameraDeviceSession完成。
2.1 ICameraDevice.hal 核心接口方法
ICameraDevice.hal定义了Camera HAL设备对外暴露的入口方法,主要包括设备打开、资源销毁、流配置协商以及Session创建。下表列出了其核心方法及语义:
| 方法名 | 输入参数 | 返回值 | 核心语义 |
|---|---|---|---|
open() |
ICameraDeviceCallback callback | Status | 打开相机设备,注册Framework回调接口,用于上报设备状态与错误 |
close() |
无 | Status | 关闭相机设备,释放所有HAL侧资源,终止所有活跃Session |
getResourceCost() |
无 | ResourceCost | 返回设备资源消耗信息(如内存、ISP带宽),供CameraService做资源调度 |
getCameraInfo() |
无 | CameraInfo | 返回设备静态信息(朝向、是否支持闪光灯、传感器方向等) |
isSessionConfigurationSupported() |
StreamConfiguration config | bool | 查询给定的流配置组合是否被HAL支持,用于Framework预检 |
createDefaultRequest() |
RequestTemplate type | CaptureRequest | 根据模板类型(PREVIEW/STILL_CAPTURE等)生成默认CaptureRequest |
createSession() |
StreamConfiguration config, ICameraDeviceSessionCallback cb | Status + ICameraDeviceSession | 创建新的Camera Session,返回Session接口实例,是初始化流程的终点 |
实现要点:
createSession()是ICameraDevice中最复杂的方法。HAL实现需要在此方法中完成Stream的分配、ISP管线的预配置、BufferQueue的绑定,并返回一个可用的ICameraDeviceSession实例。Framework会在此方法返回后立即开始下发Capture请求。
下面通过SVG图展示ICameraDevice.hal接口在Camera3Device初始化流程中的调用关系:
2.2 ICameraDeviceSession.hal 核心接口方法
ICameraDeviceSession.hal是实际执行拍照任务的接口。一旦Session创建成功,Framework便通过此接口下发Capture请求、回收Buffer、处理结果。其核心方法如下:
| 方法名 | 输入参数 | 返回值 | 核心语义 |
|---|---|---|---|
processCaptureRequest() |
CaptureRequest[] requests, BufferCache[] caches | Status | 提交一组Capture请求,HAL按序处理并返回结果 |
flush() |
无 | Status | 清空所有待处理请求,立即结束当前所有正在执行的Capture |
close() |
无 | Status | 关闭Session,释放所有流资源和内部管线 |
configureStreams() |
StreamConfiguration config | Status | (部分HAL版本)动态重新配置流,用于Session内切换分辨率或格式 |
signalStreamFlush() |
Stream[] streams, int flushType | Status | 通知HAL指定流即将被停止,HAL需完成当前帧后不再输出 |
switchToOffline() |
Stream[] streamsToKeep | Status + IOfflineSession | 将指定流切换到离线模式,释放Camera管线资源但仍可输出已捕获帧 |
常见实现陷阱:
processCaptureRequest()必须支持批量提交(数组形式),HAL实现需要维护一个请求队列。如果HAL在processCaptureRequest()中同步阻塞,会导致Framework ANR。正确的做法是:立即返回Status::OK,通过ICameraDeviceSessionCallback异步上报结果。
下面通过SVG图展示ICameraDeviceSession.hal接口在Capture阶段的工作流程:
2.3 两个接口的职责边界与协作关系
ICameraDevice与ICameraDeviceSession的职责边界非常清晰,理解这一点有助于正确实现HAL:
- 生命周期归属:ICameraDevice管理设备级别的生命周期(open/close),ICameraDeviceSession管理会话级别的生命周期(process/flush/close)。一个ICameraDevice可以依次创建多个Session,但同一时间只能有一个活跃Session。
- 流配置归属:流配置(StreamConfiguration)的协商在ICameraDevice侧完成(isSessionConfigurationSupported),但流的实际创建和绑定在ICameraDeviceSession的createSession(或configureStreams)中执行。
- 数据路径归属:所有Capture请求、结果回调、Buffer操作全部通过ICameraDeviceSession完成。ICameraDevice不参与任何帧处理。
- 错误上报归属:设备级别的致命错误(如硬件断开)通过ICameraDeviceCallback上报;会话级别的错误(如某个Stream超时)通过ICameraDeviceSessionCallback上报。
设计原则:HAL实现中,ICameraDevice应当是一个轻量级的工厂类,只负责设备打开、信息查询和Session创建。所有重量级的资源分配、ISP配置、Buffer管理都应当封装在ICameraDeviceSession的实现类中。这样当Session关闭时,可以彻底释放资源而不影响设备对象。
2.4 接口方法在HAL实现中的典型代码骨架
以下是一个简化的HAL实现骨架,展示ICameraDevice和ICameraDeviceSession核心方法的实现模式:
// ICameraDevice HAL 实现片段
Return<Status> CameraDeviceImpl::open(
const sp<ICameraDeviceCallback>& callback) {
// 1. 保存Framework回调
mCallback = callback;
// 2. 初始化硬件资源(电源、时钟、I2C)
// 3. 启动传感器预览流(可选)
mSensor = new CameraSensor();
mSensor->powerOn();
return Status::OK;
}
Return<Status, sp<ICameraDeviceSession>>
CameraDeviceImpl::createSession(
const StreamConfiguration& config,
const sp<ICameraDeviceSessionCallback>& cb) {
// 1. 验证流配置合法性
for (auto& stream : config.streams) {
if (!isStreamFormatSupported(stream.format)) {
return {Status::BAD_VALUE, nullptr};
}
}
// 2. 创建Session实现
sp<CameraSessionImpl> session = new CameraSessionImpl(mSensor, config, cb);
// 3. 初始化ISP管线、分配Buffer
session->initializePipeline();
// 4. 返回Session接口
return {Status::OK, session};
}
// ICameraDeviceSession HAL 实现片段
Return<Status> CameraSessionImpl::processCaptureRequest(
const hidl_vec<CaptureRequest>& requests,
const hidl_vec<BufferCache>& caches) {
for (auto& req : requests) {
// 1. 将请求加入内部队列
mRequestQueue.push_back(req);
// 2. 触发硬件处理(非阻塞)
mSensor->triggerCapture(req);
// 3. 通过回调异步上报结果
// mCallback->processCaptureResult(result);
}
return Status::OK;
}
Return<Status> CameraSessionImpl::flush() {
// 1. 清空请求队列
mRequestQueue.clear();
// 2. 终止当前正在执行的Capture
mSensor->abortCapture();
// 3. 通知Framework所有未完成的请求已丢弃
return Status::OK;
}
代码风格建议:HAL实现中,所有可能阻塞的操作(如硬件寄存器读写、Buffer分配)都应当放在工作线程中执行,避免在Binder调用线程中直接阻塞。
processCaptureRequest()的返回值仅表示请求是否被成功接收,不代表Capture已经完成。
2.5 接口版本演进与兼容性说明
Android Camera HAL3接口经历了多次小版本迭代,不同Android版本对接口方法的要求有所不同:
| Android版本 | HAL版本 | 新增/变更方法 | 兼容性说明 |
|---|---|---|---|
| Android 8.0 | HAL3.2 | 基础接口稳定 | 所有方法必须实现 |
| Android 9.0 | HAL3.3 | 新增signalStreamFlush() |
可选实现,Framework会检查HAL是否支持 |
| Android 10.0 | HAL3.4 | 新增switchToOffline() |
可选实现,用于多摄像头并发场景 |
| Android 11+ | HAL3.5+ | 优化Buffer管理接口 | 向后兼容,新增方法通过capability标志位查询 |
兼容性风险:如果HAL实现未实现某个可选方法(如
switchToOffline()),Framework会在调用前通过ICameraDevice::isSessionConfigurationSupported()或设备能力查询来避免调用。但如果HAL声明支持了某个能力却未正确实现对应方法,会导致运行时崩溃或死锁。