3.1 压力测试场景设计:多Camera并发与高帧率连拍

压力测试是验证Camera HAL在极限负载下稳定性的核心手段。本章聚焦三个最具代表性的压力场景:多Camera并发(前后摄同时打开)、高帧率连拍(30fps持续1小时)、分辨率切换(4K→1080p→VGA循环)。这些场景直接暴露HAL层在资源竞争、内存泄漏、状态机异常等方面的脆弱点。

3.1.1 多Camera并发(前后摄同时打开)

多Camera并发测试模拟双摄或多摄同时工作的场景,例如视频通话中同时使用前置和后置摄像头。该场景主要验证HAL对ISP管线、内存带宽、同步锁的并发处理能力。

关键测试指标:
  • 前后摄同时打开成功率(≥99.9%)
  • 并发预览帧率不低于单摄的80%
  • 无ANR(Application Not Responding)或Crash
  • 内存增量不超过20MB(单次打开)
多Camera并发HAL架构图 Camera App (前后摄) Camera Framework Camera HAL (并发调度) Kernel Driver (V4L2/CSI) ISP / MIPI / DDR 资源竞争 内存带宽争抢 同步锁死锁 ISP管线冲突 常见故障现象 • 预览画面卡顿/撕裂 • 摄像头打开超时 • 内存泄漏导致OOM
实战经验:在MTK平台测试中发现,前后摄同时打开时,若HAL未正确释放上一会话的MIPI CSI时钟,会导致第二路摄像头初始化失败。建议在configure_streams()中增加资源预留检查。

3.1.2 高帧率连拍(30fps持续1小时)

高帧率连拍测试模拟连续抓拍场景,例如运动模式或高速连拍。该场景重点验证HAL的帧处理管线、buffer管理、内存回收在长时间高负载下的稳定性。

测试参数 规格要求 HAL层关注点
帧率 30fps ± 2fps request/result 调度延迟
持续时间 1小时(108000帧) 内存泄漏累积
分辨率 1920×1080 ISP管线吞吐量
输出格式 NV12 / JPEG 编码器稳定性
高帧率连拍HAL管线流程 App发起连拍 HAL创建Session 配置Stream 循环Submit Request 返回Result 循环108000次(1小时) 内存监控:每1000帧检查heap增量 帧率监控:实时统计fps抖动
常见陷阱:高帧率连拍测试中,HAL层容易在process_capture_result()回调中累积pending buffer。若未及时释放已处理的buffer,1小时后内存占用可能膨胀至初始值的3-5倍,最终触发LMK(Low Memory Killer)。

3.1.3 分辨率切换(4K→1080p→VGA循环)

分辨率切换测试模拟相机应用在不同场景间切换,例如从4K录像切换到1080p预览再切换到VGA拍照。该场景主要验证HAL的Stream配置重建、ISP参数重载、buffer重新分配的健壮性。

测试循环设计:
  1. 初始化:打开摄像头,配置4K(3840×2160)预览流
  2. 稳定运行5秒,采集基线帧率
  3. 切换至1080p(1920×1080),等待3秒
  4. 切换至VGA(640×480),等待3秒
  5. 返回4K,重复步骤2-4,共循环500次
分辨率 像素数 带宽需求(30fps) HAL层切换动作
4K (3840×2160) 8.3MP ~1.2 GB/s 重新分配大buffer,ISP全分辨率处理
1080p (1920×1080) 2.1MP ~0.3 GB/s 缩小buffer,ISP降采样
VGA (640×480) 0.3MP ~0.05 GB/s 最小buffer,ISP裁剪模式
分辨率切换状态机与故障点 4K (3840×2160) 状态A 1080p (1920×1080) 状态B VGA (640×480) 状态C 分辨率切换常见故障点 ① Stream配置重建失败:HAL未正确处理configure_streams()的重复调用 ② Buffer泄漏:旧分辨率buffer未释放,新buffer又分配,导致内存碎片 ③ ISP状态残留:前一分辨率的ISP参数未清空,导致新分辨率画面异常

3.1.4 压力测试自动化脚本示例

以下是一个基于Camera2 API的压力测试脚本片段,用于执行分辨率切换循环测试:

// 分辨率切换压力测试核心逻辑 (Java)
private void runResolutionSwitchTest(CameraDevice device, int loopCount) {
    List<Size> resolutions = Arrays.asList(
        new Size(3840, 2160),  // 4K
        new Size(1920, 1080),  // 1080p
        new Size(640, 480)     // VGA
    );
    
    for (int i = 0; i < loopCount; i++) {
        for (Size size : resolutions) {
            // 1. 关闭当前Session
            if (captureSession != null) {
                captureSession.close();
                captureSession = null;
            }
            
            // 2. 创建新的配置
            List<Surface> outputSurfaces = new ArrayList<>();
            SurfaceTexture texture = new SurfaceTexture(TEXTURE_ID);
            texture.setDefaultBufferSize(size.getWidth(), size.getHeight());
            Surface surface = new Surface(texture);
            outputSurfaces.add(surface);
            
            // 3. 重新configure Streams
            device.createCaptureSession(outputSurfaces, 
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        captureSession = session;
                        // 4. 发送3秒预览请求
                        startPreview(session, surface);
                    }
                    
                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) {
                        Log.e(TAG, "配置失败: " + size);
                        failureCount++;
                    }
                }, null);
            
            // 5. 等待3秒
            Thread.sleep(3000);
        }
    }
}
测试结果判定标准:
  • 500次循环中,配置失败次数为0
  • 每次切换后帧率恢复时间 < 500ms
  • 内存增量 < 50MB(全程)
  • 无Crash、ANR、SELinux denial

3.1.5 压力测试故障排查清单

故障现象 可能原因 排查手段
并发打开失败 MIPI CSI时钟冲突 检查dmesg中CSI相关错误
连拍帧率下降 buffer泄漏导致分配延迟 使用dumpsy meminfo跟踪native heap
分辨率切换卡顿 ISP参数重载超时 抓取HAL层configure_streams耗时日志
内存持续增长 pending buffer未释放 检查process_capture_result回调中buffer引用计数

以上三个压力场景覆盖了Camera HAL稳定性测试的核心维度。在实际项目中,建议将这三个场景组合成一个综合压力测试用例,在夜间自动化运行,并配合logcat、systrace、perfetto等工具采集性能数据,以便快速定位HAL层稳定性问题。