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(单次打开)
实战经验:在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层容易在
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重新分配的健壮性。
测试循环设计:
- 初始化:打开摄像头,配置4K(3840×2160)预览流
- 稳定运行5秒,采集基线帧率
- 切换至1080p(1920×1080),等待3秒
- 切换至VGA(640×480),等待3秒
- 返回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裁剪模式 |
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层稳定性问题。