3. CTS Camera Test框架:Test Harness、CameraTestRule、CameraUtil工具类

CTS Camera 测试框架是连接测试用例与 Android Camera HAL 实现的桥梁。理解其核心组件——Test Harness、CameraTestRule 和 CameraUtil——是编写高效、可维护的 Camera CTS 用例的基础。本章将深入剖析这三个组件的职责、交互方式及典型使用模式。

3.1 框架总体架构

CTS Camera 测试框架采用分层设计,将测试逻辑、设备交互与结果验证解耦。下图展示了测试用例执行时各组件间的协作关系:

CTS Camera Test 框架组件协作图 CTS Camera Test 框架组件协作图 CameraTestRule Test Harness CameraUtil Camera HAL @Rule 注解注入 管理测试生命周期 参数化配置 结果收集与报告 打开/关闭 Camera 配置 Session/Stream HAL 接口实现 设备厂商适配 测试用例通过 @Rule 声明 CameraTestRule 实例 Test Harness 负责解析 测试参数与分发 CameraUtil 封装 Camera Manager 与 CameraDevice HAL 层实现具体 Camera 功能
关键设计原则:Test Harness 作为测试执行引擎,CameraTestRule 作为测试生命周期管理器,CameraUtil 作为底层 Camera API 的封装层。三者各司其职,共同构建了可扩展、可复用的测试框架。

3.2 Test Harness:测试执行引擎

Test Harness 是 CTS Camera 测试框架的核心调度组件,负责测试用例的加载、参数化配置、执行与结果收集。它运行在 Android 测试基础设施之上,与 Trade Federation (TF) 深度集成。

3.2.1 核心职责

  • 测试用例发现与加载:扫描指定测试类,识别带有 @Test 注解的方法。
  • 参数化配置:解析 @ParameterizedTest 或自定义注解,为每个测试方法注入不同的 Camera ID、分辨率、格式等参数组合。
  • 资源管理:协调 Camera 硬件资源的分配与释放,避免并发冲突。
  • 结果收集:捕获测试过程中的日志、性能指标、错误信息,生成结构化测试报告。

3.2.2 典型配置示例

在 CTS 测试配置 XML 文件中,Test Harness 通过以下方式定义:

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.hardware.camera2.cts" />
    <option name="runner" value="androidx.test.runner.AndroidJUnit4" />
    <option name="instrumentation-arg" key="camera_ids" value="0,1" />
    <option name="instrumentation-arg" key="test_timeout_ms" value="30000" />
</test>
实践建议:在调试特定 HAL 行为时,可通过 instrumentation-arg 动态调整 Test Harness 的参数,例如只测试后置 Camera 或特定分辨率,以缩短测试迭代周期。

3.3 CameraTestRule:测试生命周期管理器

CameraTestRule 是 JUnit 的 TestRule 实现,它封装了 Camera 测试的通用生命周期逻辑,包括 Camera 的打开、关闭、异常处理以及资源清理。测试用例通过 @Rule 注解声明 CameraTestRule 实例,从而自动获得这些能力。

3.3.1 生命周期钩子

钩子方法 触发时机 典型用途
before() 每个测试方法执行前 初始化 CameraManager、获取 Camera ID 列表、创建 CameraDevice
after() 每个测试方法执行后 关闭 CameraDevice、释放 CaptureSession、清理资源
onFailed() 测试方法抛出异常时 捕获异常上下文、保存关键日志、标记测试失败原因
onSkipped() 测试方法被跳过时 记录跳过原因(如硬件不支持、权限不足)

3.3.2 使用示例

public class CameraPreviewTest {
    @Rule
    public CameraTestRule mCameraRule = new CameraTestRule();

    @Test
    public void testPreviewStability() throws Exception {
        // CameraTestRule 已自动打开 Camera
        CameraDevice camera = mCameraRule.getCameraDevice();
        assertNotNull("CameraDevice should not be null", camera);

        // 创建预览请求
        CaptureRequest.Builder previewBuilder =
                camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        // ... 配置 Surface 并开始预览

        // 测试结束后,CameraTestRule 自动关闭 Camera
    }
}
注意事项:CameraTestRule 默认使用 Camera ID 0。如果测试需要操作多个 Camera 或特定 ID,必须在 @Test 注解或 Test Harness 配置中显式指定。忽略此点可能导致测试在双摄设备上误用错误的 Camera 单元。

3.4 CameraUtil:底层 Camera API 封装

CameraUtil 是 CTS Camera 测试框架中的工具类集合,它封装了 Android Camera2 API 的复杂调用逻辑,为测试用例提供简洁、稳定的接口。CameraUtil 的核心目标是减少测试代码中的样板代码,并统一错误处理策略。

3.4.1 核心功能模块

  • Camera 打开与关闭:封装 CameraManager.openCamera() 的异步回调,提供同步等待机制。
  • Session 管理:简化 CameraDevice.createCaptureSession() 的配置流程,支持输出配置列表的快速构建。
  • 请求构造:提供 createCaptureRequest() 的便捷方法,自动填充默认模板参数。
  • 特性查询:封装 CameraCharacteristics 的读取逻辑,提供类型安全的查询接口。

3.4.2 关键工具方法

方法签名 功能描述 返回类型
openCamera(String cameraId) 同步打开指定 Camera,超时默认 5 秒 CameraDevice
createCaptureSession(CameraDevice, List<Surface>) 基于输出 Surface 列表创建 CaptureSession CameraCaptureSession
getCharacteristics(String cameraId) 获取 Camera 特性集合 CameraCharacteristics
isFeatureSupported(String cameraId, Key<?> key) 检查指定 Camera 是否支持某特性 boolean
waitForIdle(CameraCaptureSession) 等待 Session 进入空闲状态 void

3.4.3 典型使用模式

public class CameraUtilDemoTest {
    @Rule
    public CameraTestRule mCameraRule = new CameraTestRule();

    @Test
    public void testCameraOpenAndCharacteristics() throws Exception {
        // 使用 CameraUtil 打开 Camera
        CameraDevice camera = CameraUtil.openCamera("0");
        assertNotNull("Camera should be opened", camera);

        // 查询 Camera 特性
        CameraCharacteristics chars = CameraUtil.getCharacteristics("0");
        Integer[] availableFpsRanges = chars.get(
                CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
        assertNotNull("FPS ranges should not be null", availableFpsRanges);

        // 检查是否支持 HDR+
        boolean hdrSupported = CameraUtil.isFeatureSupported("0",
                CameraCharacteristics.CONTROL_AE_MODE_AVAILABLE_HDR);
        assertTrue("HDR+ should be supported", hdrSupported);

        // 关闭 Camera
        CameraUtil.closeCamera(camera);
    }
}
最佳实践:在编写 CTS 测试用例时,优先使用 CameraUtil 提供的方法,而不是直接调用 Camera2 API。这不仅能减少代码量,还能确保错误处理逻辑与 CTS 框架保持一致,避免因底层 API 调用方式差异导致的测试不稳定。

3.5 组件交互流程

以下 SVG 图展示了从测试用例启动到 HAL 调用的完整交互流程:

CTS Camera Test 组件交互时序图 组件交互时序图 测试用例 CameraTestRule CameraUtil Camera HAL 1. 执行 @Before 2. openCamera(id) 3. HAL open() 4. CameraDevice 5. CameraDevice 6. 注入 CameraDevice 7. @Test 执行 8. createCaptureSession() 9. HAL configureStreams() 10. CaptureSession 11. @After 清理

3.6 常见问题与避坑指南

问题场景 根因分析 解决方案
CameraTestRule 未正确初始化 @Rule 注解未使用 public 字段,或 Test Harness 未正确加载 确保 @Rule 字段为 public 且非 static;检查测试配置 XML 中的 runner 配置
CameraUtil.openCamera() 超时 HAL 层 open() 实现耗时过长,或 Camera 被其他进程占用 增加超时时间(通过 Test Harness 参数);检查设备上其他 Camera 应用是否已关闭
Session 创建失败 输出 Surface 配置与 HAL 支持的流格式不匹配 使用 CameraUtil.getCharacteristics() 查询支持的输出配置,确保 Surface 格式、尺寸在支持列表中
测试结果不稳定(Flaky) 资源未正确释放,导致后续测试受前序测试状态影响 检查 CameraTestRule 的 after() 方法是否完整释放所有资源;使用 @Before 重置全局状态
重要提醒:在 CTS 测试中,CameraTestRule 和 CameraUtil 的版本必须与 Android 平台版本匹配。使用不匹配的版本可能导致 API 行为差异,进而产生误报或漏报。建议在构建测试时,通过 Gradle 依赖管理锁定框架版本。

3.7 小结

本章详细介绍了 CTS Camera Test 框架的三个核心组件:

  • Test Harness 作为测试执行引擎,负责参数化配置与结果收集。
  • CameraTestRule 作为生命周期管理器,自动化 Camera 资源的打开与关闭。
  • CameraUtil 作为底层 API 封装,简化 Camera2 API 的调用复杂度。