2. CameraDevice 接口基础:CameraManager、CameraCharacteristics、CameraDevice 的创建与生命周期
CameraDevice 接口是 Android Camera2 框架中应用层与底层硬件 HAL 交互的核心通道。要正确创建并管理 CameraDevice,必须首先理解其前置依赖:CameraManager(系统服务代理)与 CameraCharacteristics(设备静态能力描述)。本章将系统梳理这三个核心对象的创建流程、生命周期管理以及常见性能陷阱。
2.1 CameraManager:系统服务入口
CameraManager 是应用层访问相机子系统的唯一入口。它负责枚举可用摄像头、查询设备特性、以及建立与 CameraService 的 Binder 通信通道。
关键职责:
- 通过
getCameraIdList()获取当前设备上所有可用的摄像头 ID 列表。 - 通过
getCameraCharacteristics(cameraId)获取指定摄像头的静态能力信息。 - 通过
openCamera(cameraId, stateCallback, handler)创建 CameraDevice 实例。
获取 CameraManager 实例的标准方式:
// 从系统服务获取 CameraManager
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
if (manager == null) {
// 设备不支持相机功能
return;
}
性能提示:CameraManager 实例建议在 Application 或 Activity 初始化时获取一次并缓存复用,避免频繁通过
getSystemService() 创建新引用。该操作涉及跨进程 Binder 调用,重复获取会增加延迟。
2.2 CameraCharacteristics:设备能力画像
CameraCharacteristics 是一个只读的静态属性集合,描述了摄像头传感器的物理特性、支持的能力集、输出尺寸范围、帧率上限等关键参数。这些信息在创建 CameraDevice 和配置 CaptureSession 之前必须完成查询。
| 特性 Key | 数据类型 | 说明 | 性能影响 |
|---|---|---|---|
INFO_SUPPORTED_HARDWARE_LEVEL |
int | 硬件支持级别(LEGACY / LIMITED / FULL / LEVEL_3) | 决定 Pipeline 能力上限 |
SCALER_STREAM_CONFIGURATION_MAP |
StreamConfigurationMap | 支持的输出/输入格式、尺寸、最小帧持续时间 | 直接影响 Surface 配置与帧率 |
SENSOR_INFO_SENSITIVITY_RANGE |
Range<Integer> | ISO 感光度范围 | 影响低光场景曝光策略 |
CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES |
Range<Integer>[] | 自动曝光支持的目标帧率范围 | 决定帧率配置上限 |
REQUEST_PARTIAL_RESULT_COUNT |
int | 一次 Capture 返回的部分结果数量 | 影响回调时序与延迟分析 |
典型查询代码:
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
// 查询硬件支持级别
Integer level = characteristics.get(
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
if (level != null && level == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
// LEGACY 级别不支持某些高级特性
}
// 获取输出尺寸映射
StreamConfigurationMap configMap = characteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] outputSizes = configMap.getOutputSizes(ImageFormat.YUV_420_888);
避坑指南:CameraCharacteristics 的查询结果在摄像头设备生命周期内不会改变,但不同摄像头 ID 的特性可能差异巨大(例如前置与后置)。务必在
openCamera() 之前完成所有特性读取,不要在 Capture 回调中动态查询,以避免主线程阻塞。
2.3 CameraDevice 的创建流程
CameraDevice 的创建是一个异步过程,涉及应用层 → CameraService → HAL 驱动的完整链路。创建成功后,应用通过回调获得 CameraDevice 实例,进而创建 CaptureSession。
// 异步打开摄像头
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
// CameraDevice 创建成功,可以开始配置 CaptureSession
// 注意:此回调在 CameraManager 的 handler 线程中执行
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
// 摄像头被系统断开连接(例如被其他高优先级应用抢占)
camera.close();
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
// 创建失败或运行中发生致命错误
// error 码包括 ERROR_CAMERA_IN_USE、ERROR_MAX_CAMERAS_IN_USE 等
camera.close();
}
}, backgroundHandler);
创建流程关键步骤:
- 应用调用
manager.openCamera(),请求通过 Binder 发送至 CameraService。 - CameraService 检查权限、设备可用性、并发限制。
- CameraService 通知 HAL 打开指定摄像头设备。
- HAL 驱动初始化传感器与 ISP 硬件。
- CameraService 创建 CameraDevice 代理并返回给应用。
- 应用收到
onOpened()回调,获得 CameraDevice 实例。
2.4 CameraDevice 的生命周期管理
CameraDevice 是一个重量级系统资源,其生命周期必须严格管理。错误的生命周期控制会导致资源泄漏、摄像头被占用、甚至系统服务崩溃。
| 生命周期阶段 | 触发条件 | 应用行为 | 常见错误 |
|---|---|---|---|
| 创建 | openCamera() 调用成功 |
在 onOpened() 中保存 CameraDevice 引用 |
在回调外使用未初始化的引用 |
| 活跃 | CameraDevice 已打开,可创建 CaptureSession | 配置输出 Surface、创建 Session、发送 Capture 请求 | 未检查设备是否已断开就发送请求 |
| 断开 | 系统抢占、其他应用打开同一摄像头 | 立即调用 close(),释放所有关联资源 |
忽略 onDisconnected() 回调 |
| 错误 | 硬件故障、驱动崩溃、资源耗尽 | 调用 close(),尝试重新打开或降级处理 |
在 onError() 中继续使用 CameraDevice |
| 关闭 | 应用主动调用 cameraDevice.close() |
置空引用,通知上层状态变更 | 重复 close() 导致异常 |
最佳实践:CameraDevice 的
close() 方法必须在 onDisconnected() 和 onError() 回调中调用,同时在 Activity/Fragment 的 onPause() 或 onStop() 中主动释放。建议使用 AtomicBoolean 标记设备状态,防止重复关闭。
2.5 并发与资源竞争注意事项
CameraDevice 是独占资源。在同一时间,一个摄像头 ID 只能被一个应用进程打开。CameraManager 通过 CameraService 的权限管理和引用计数来保证互斥访问。
并发陷阱:
- 不要在主线程(UI 线程)中调用
openCamera(),Binder 调用可能阻塞数十毫秒。 - 多个摄像头 ID 可以同时打开(例如前置 + 后置),但受硬件并发能力限制。
- 在
onOpened()回调中不要执行耗时操作,尽快创建 CaptureSession。 - CameraDevice 实例不是线程安全的,所有操作应在同一 Handler 线程中串行执行。
2.6 性能调优切入点
从 CameraDevice 创建阶段开始,性能调优就已经介入。以下是本章涉及的三个关键调优方向:
| 调优维度 | 具体措施 | 预期收益 |
|---|---|---|
| 减少创建延迟 | 提前查询 CameraCharacteristics 并缓存;使用专用 HandlerThread 执行 openCamera | 创建耗时从 200ms 降至 80ms |
| 避免资源泄漏 | 严格遵循生命周期回调,在 onPause 中释放 CameraDevice | 防止摄像头被长时间占用导致其他应用失败 |
| 合理选择摄像头 | 根据 CameraCharacteristics 的硬件级别选择最优摄像头(优先 FULL 级别) | 获得更低的 Capture 延迟和更高的帧率 |
本章小结:CameraManager 是入口,CameraCharacteristics 是地图,CameraDevice 是引擎。三者的正确使用是构建高性能 Camera Pipeline 的基石。下一章将深入 CameraDevice 创建后的核心操作——CaptureSession 的配置与优化。