4. Camera AIDL 接口设计原则:接口粒度、回调设计、版本管理策略
在 Camera HAL 从 HIDL 向 AIDL 迁移的过程中,接口设计是决定架构可扩展性、跨进程性能以及长期维护成本的核心环节。本章围绕 接口粒度、回调设计 与 版本管理策略 三大原则展开,为后续具体接口定义提供设计依据。
核心观点:AIDL 接口设计应遵循“高内聚、低耦合、单向回调、语义化版本”四大准则,避免过度抽象或过于碎片化的接口定义。
4.1 接口粒度设计原则
接口粒度直接影响跨进程调用的次数与数据吞吐量。粒度过细会导致频繁 Binder 交互,增加延迟;粒度过粗则降低复用性,难以适配多厂商扩展需求。
4.1.1 粒度分级策略
| 粒度级别 | 典型场景 | Binder 调用次数 | 推荐度 |
|---|---|---|---|
| 粗粒度(Batch) | 批量配置参数、批量获取结果 | 1 次 / 批 | 高(核心路径) |
| 中粒度(Group) | 按功能模块分组(如 3A、ISP) | 1 次 / 组 | 中(模块边界) |
| 细粒度(Single) | 单个属性 get/set | N 次 / 属性 | 低(仅调试用) |
设计建议:核心数据流(如 Request/Result)采用粗粒度批量接口;厂商扩展功能使用中粒度分组接口;仅调试与诊断场景保留细粒度单属性接口。
4.1.2 接口聚合模式
推荐使用 Bundle 模式 将多个相关参数打包为单一 AIDL 结构体,减少跨进程序列化开销。例如将 CaptureRequest 中的所有控制参数聚合为一个 RequestSettings 对象:
// 推荐:聚合接口
interface ICameraDevice {
void submitRequest(in RequestSettings settings, in OutputConfiguration output);
}
// 不推荐:分散接口
interface ICameraDevice {
void setExposureTime(long ns);
void setSensitivity(int iso);
void setOutputSurface(in Surface surface);
void submit();
}
注意:聚合粒度不宜过大,避免单个结构体包含超过 50 个字段,否则将增加序列化/反序列化耗时,并降低缓存友好性。
4.2 回调设计原则
回调是 Camera HAL 向 Framework 异步通知事件(如帧完成、错误、3A 收敛)的核心机制。AIDL 回调设计需遵循 单向(oneway)、轻量、可取消 三大原则。
4.2.1 单向回调(Oneway)
所有回调接口必须声明为 oneway,避免回调线程阻塞 HAL 的异步处理流程:
// 正确:oneway 回调
interface ICameraDeviceCallback {
oneway void onCaptureCompleted(in CaptureResult result);
oneway void onError(in ErrorCode code, in String message);
}
// 错误:同步回调可能导致死锁
interface ICameraDeviceCallback {
void onCaptureCompleted(in CaptureResult result); // 可能阻塞 HAL
}
4.2.2 回调注册与生命周期管理
回调必须支持动态注册与注销,防止内存泄漏或野指针。设计模式如下:
- 注册:Framework 通过
setCallback()传入回调对象 - 注销:Framework 通过
clearCallback()或传递 null 解除绑定 - 死亡通知:HAL 端监听 Binder 死亡通知,自动清理回调引用
interface ICameraDevice {
void setCallback(in ICameraDeviceCallback callback);
void clearCallback();
}
4.2.3 回调频率控制
高频回调(如预览帧回调)必须支持 节流(Throttling) 或 批量上报,避免 Binder 通道拥塞:
| 回调类型 | 频率上限 | 推荐策略 |
|---|---|---|
| 预览帧回调 | 30 fps | 批量上报(每帧携带多个结果) |
| 3A 状态回调 | 10 Hz | 变化触发(仅状态变化时上报) |
| 错误回调 | 不限 | 立即上报(高优先级) |
最佳实践:在回调接口中增加
sequenceId 字段,帮助 Framework 端识别回调顺序与丢帧情况。
4.3 版本管理策略
AIDL 接口的版本管理直接决定 HAL 与 Framework 的兼容性。Camera HAL 采用 语义化版本 + 接口冻结 策略,确保向前兼容。
4.3.1 版本号定义规范
| 版本段 | 含义 | 变更示例 | 兼容性 |
|---|---|---|---|
| MAJOR | 不兼容的 API 变更 | 删除接口、修改方法签名 | 不兼容 |
| MINOR | 向下兼容的功能新增 | 新增接口、新增枚举值 | 向前兼容 |
| PATCH | 向下兼容的缺陷修复 | 修复序列化 bug、优化性能 | 完全兼容 |
4.3.2 接口冻结与扩展机制
已发布的 MAJOR 版本接口必须 冻结,不允许修改已有方法签名。扩展功能通过以下方式实现:
- 新增接口:在
ICameraDevice中追加@VendorExtension注解的方法 - 新增枚举值:Framework 端使用
default分支处理未知枚举 - 新增回调:通过
ICameraDeviceCallbackV2继承扩展,不修改原始回调接口
// 版本扩展示例:V2 回调继承 V1
interface ICameraDeviceCallbackV2 extends ICameraDeviceCallback {
oneway void onCaptureProgressed(in CaptureResult result); // V2 新增
}
4.3.3 版本协商流程
Framework 与 HAL 在初始化阶段通过 getInterfaceVersion() 进行版本协商:
- Framework 调用
getInterfaceVersion()获取 HAL 支持的版本 - Framework 根据自身支持的版本范围,选择最高兼容版本
- 若版本不匹配,Framework 降级使用基础功能或报错
版本兼容矩阵:Framework 1.x 兼容 HAL 1.x 和 2.x(降级使用 1.x 功能);Framework 2.x 仅兼容 HAL 2.x 及以上。
4.4 接口设计全景图
以下 SVG 图展示了 Camera AIDL 接口设计中粒度、回调与版本管理的整体关系:
4.5 设计原则总结
| 原则 | 关键决策点 | 常见反模式 | 推荐做法 |
|---|---|---|---|
| 接口粒度 | 核心路径 vs 扩展路径 | 每个属性一个接口方法 | Bundle 聚合 + 分组接口 |
| 回调设计 | 同步 vs 异步、频率控制 | 同步回调导致 HAL 阻塞 | Oneway + 批量上报 |
| 版本管理 | 兼容性策略、扩展方式 | 修改已发布接口签名 | 语义化版本 + 接口冻结 |
架构决策记录:Camera AIDL 接口设计将采用“粗粒度核心接口 + 中粒度扩展接口 + 细粒度调试接口”三级粒度体系,回调全部使用 oneway 模式,版本管理遵循 MAJOR.MINOR.PATCH 语义化规范,确保 HAL 与 Framework 的长期兼容性。