4. 摄像头ID与朝向枚举:CameraCharacteristics.LENS_FACING、前后摄区分、逻辑摄像头与物理摄像头

4.1 核心概念与枚举定义

在 Android Camera CTS 测试中,摄像头 ID 是标识每个摄像头的唯一字符串,而朝向(Facing)则通过 CameraCharacteristics.LENS_FACING 静态信息枚举。HAL 层必须正确上报这些信息,否则 CTS 用例将直接失败。

枚举值 常量名 含义 典型应用场景
0 LENS_FACING_FRONT 前置摄像头,屏幕同侧 自拍、视频通话
1 LENS_FACING_BACK 后置摄像头,屏幕异侧 拍照、录像、扫码
2 LENS_FACING_EXTERNAL 外接摄像头(USB/UVC) 外接相机、工业检测
CTS 验证要点: 测试框架通过 CameraManager.getCameraIdList() 获取所有 ID,再对每个 ID 调用 getCameraCharacteristics() 读取 LENS_FACING。若返回非法值或与物理布局矛盾,则判定为 HAL 实现缺陷。

4.2 前后摄区分与 CTS 验证逻辑

CTS 通过以下步骤严格区分前后摄:

  1. 枚举所有摄像头 ID,构建 ID 列表。
  2. 对每个 ID 读取 CameraCharacteristics.LENS_FACING。
  3. 验证前置摄像头数量 ≤ 后置摄像头数量(非强制但常见)。
  4. 检查 LENS_FACING_EXTERNAL 设备是否支持热插拔事件。
常见失败场景: 部分 OEM 将前置摄像头错误上报为 LENS_FACING_BACK,导致 CTS 用例 testCameraFacing 失败。HAL 开发者应核对 sensor 物理安装方向与枚举值的一致性。
前后摄 CTS 验证流程 CameraManager getCameraIdList() getCameraCharacteristics() 读取 LENS_FACING 枚举值 0/1/2 前置/后置/外接分类 验证数量与朝向一致性 CTS 断言 通过/失败

4.3 逻辑摄像头与物理摄像头

Android 10(API 29)引入逻辑摄像头(Logical Camera)概念,用于多摄系统。逻辑摄像头对应一个虚拟 ID,内部聚合多个物理摄像头(Physical Camera)。

特性 逻辑摄像头 物理摄像头
ID 类型 虚拟 ID,对外暴露 物理 ID,通过 getPhysicalCameraIds() 获取
LENS_FACING 继承自主物理摄像头 各自独立朝向
典型场景 广角+超广角融合 单个 sensor 独立工作
CTS 验证 检查 REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA 验证物理 ID 存在且可打开
HAL 实现警告: 逻辑摄像头必须至少包含 2 个物理摄像头,且所有物理摄像头的 LENS_FACING 必须相同。若混合前置与后置物理摄像头,CTS 将直接报错。

4.4 逻辑摄像头架构与 CTS 枚举

CTS 通过以下步骤验证逻辑摄像头:

  • 调用 CameraCharacteristics.getPhysicalCameraIds() 获取物理 ID 集合。
  • 若集合非空,则检查 REQUEST_AVAILABLE_CAPABILITIES 是否包含 LOGICAL_MULTI_CAMERA。
  • 遍历每个物理 ID,读取其 LENS_FACING,确保与逻辑摄像头一致。
  • 验证物理摄像头可独立打开并输出数据流。
逻辑摄像头与物理摄像头关系 逻辑摄像头 ID: 0 LENS_FACING_BACK 物理摄像头 ID: 1 LENS_FACING_BACK 物理摄像头 ID: 2 LENS_FACING_BACK Sensor 1 (广角) 物理独立输出 Sensor 2 (超广角) 物理独立输出

4.5 CTS 测试用例示例

以下代码片段展示 CTS 如何枚举摄像头 ID 并验证朝向:

// 获取 CameraManager
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String[] ids = manager.getCameraIdList();

for (String id : ids) {
    CameraCharacteristics chars = manager.getCameraCharacteristics(id);
    Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
    
    // 验证朝向枚举值合法
    assertNotNull(facing);
    assertTrue(facing == CameraCharacteristics.LENS_FACING_FRONT ||
               facing == CameraCharacteristics.LENS_FACING_BACK ||
               facing == CameraCharacteristics.LENS_FACING_EXTERNAL);
    
    // 验证逻辑摄像头物理 ID 朝向一致性
    Set<String> physicalIds = chars.getPhysicalCameraIds();
    if (physicalIds != null && !physicalIds.isEmpty()) {
        for (String physId : physicalIds) {
            CameraCharacteristics physChars = manager.getCameraCharacteristics(physId);
            Integer physFacing = physChars.get(CameraCharacteristics.LENS_FACING);
            assertEquals(facing, physFacing);
        }
    }
}
CTS 测试项对照: android.hardware.camera2.cts.CameraCharacteristicsTest#testLensFacing 和 testLogicalMultiCamera 是本章核心用例。HAL 开发者应确保所有摄像头 ID 的 LENS_FACING 与物理布局严格匹配,逻辑摄像头物理 ID 朝向必须统一。

4.6 常见问题与避坑指南

  • ID 重复或缺失: HAL 返回的 ID 列表必须连续且唯一,CTS 会检查 ID 数量与 getCameraIdList() 一致性。
  • 朝向与旋转矛盾: LENS_FACING_FRONT 的摄像头通常需要镜像输出,若 HAL 未正确设置 SCALER_CROP_REGION 或 JPEG_ORIENTATION,CTS 图像测试会失败。
  • 外接摄像头热插拔: 对于 LENS_FACING_EXTERNAL,CTS 要求支持 CameraManager.AvailabilityCallback 回调,HAL 必须正确触发 onCameraAvailable 和 onCameraUnavailable。
  • 逻辑摄像头物理 ID 不可打开: 部分 HAL 将物理 ID 注册为逻辑摄像头的子设备,但未实现独立 open() 路径,导致 CTS 打开物理摄像头失败。
调试建议: 使用 dumpsys media.camera 查看当前系统所有摄像头 ID、朝向和逻辑/物理关系。对比 CTS 日志中的 getCameraIdList 输出与 HAL 实现,快速定位枚举不一致问题。