第1章:相机调试三板斧——Systrace、Camera2测试工具与dumpsys
做Android相机开发,最头疼的是什么?
不是API不会调,而是出了问题不知道从哪查。我刚开始接触相机开发那会儿,经常遇到预览卡顿、拍照延迟、对焦不准这类问题。那时候我只会对着代码一遍遍看,结果往往是浪费时间。
后来一位老前辈跟我说了一句话,我到现在都记得:「别猜,用工具说话」。
今天我就把这套「三板斧」教给你。它们分别是:Systrace、Camera2 API测试工具、以及adb shell dumpsys media.camera。这三样东西用熟了,相机调试对你来说就不再是玄学。
1.1 Systrace:相机性能分析的「显微镜」
1.1.1 为什么需要Systrace?
你想想看,相机预览卡顿,到底是CPU不够快?还是GPU渲染跟不上?还是驱动层丢帧了?
普通日志只能告诉你「发生了什么」,但Systrace能告诉你「每一毫秒发生了什么」。
我个人习惯,只要遇到相机性能问题,第一件事就是抓一份Systrace。它能把系统里所有线程的活动按时间轴展示出来,哪个阶段耗时多、哪个线程在空转,一眼就能看出来。
1.1.2 怎么抓Systrace?
其实很简单。老版本用atrace,新版本用Perfetto。我推荐直接用Perfetto,因为它更现代,UI也更友好。
命令行方式(适合自动化):
# 抓取10秒的trace,包含相机相关标签
adb shell perfetto -t 10s -o /data/misc/perfetto-traces/trace.perfetto \
--categories camera,hal,graphics,audio,input
# 拉取到本地
adb pull /data/misc/perfetto-traces/trace.perfetto .
图形化方式(适合日常调试):
- 打开浏览器访问
ui.perfetto.dev - 点击「Record new trace」
- 在「Categories」中勾选
camera、hal、graphics - 点击「Start recording」,然后操作手机相机
- 点击「Stop」,自动下载trace文件
1.1.3 怎么看Systrace?
打开trace文件后,你会看到一堆彩色条带。别慌,我教你重点看三个地方:
| 关注点 | 怎么看 | 常见问题 |
|---|---|---|
| SurfaceFlinger | 看是否有掉帧(红色标记) | GPU渲染超时 |
| Camera HAL | 看processCaptureRequest耗时 | HAL层处理太慢 |
| App主线程 | 看是否有长时间阻塞 | UI线程做了耗时操作 |
举个例子。我曾经遇到一个预览卡顿问题,查代码怎么也找不到原因。抓了Systrace一看,发现Camera HAL线程每隔几帧就有一个明显的空档期——原来是驱动层在某个分辨率下没有做好流水线处理。后来换了预览尺寸,问题就解决了。
Trace.beginSection("mySection")。
1.2 Camera2 API测试工具:快速验证你的相机逻辑
1.2.1 官方测试工具
Google其实提供了一个非常好用的测试工具,叫「Camera2 API Test」。它藏在CTS测试包里,但你可以单独拿出来用。
我个人习惯在开发新功能时,先用这个工具跑一遍,看看设备支持哪些能力。比如:
- 是否支持
RAW输出? - 支持哪些
AE(自动曝光)模式? - 最大预览尺寸是多少?
安装方式很简单:
# 从CTS包中提取
unzip android-cts-*.zip
cd android-cts/testcases/
adb install CtsCameraTestCases.apk
然后打开应用,选择对应的测试项。它会自动验证你的Camera2实现是否符合规范。
1.2.2 自己写测试工具
当然,官方工具只能测通用场景。我建议你针对自己的业务,写一套自动化测试脚本。
核心思路是这样的:
// 伪代码示例
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
String[] cameraIds = manager.getCameraIdList();
for (String id : cameraIds) {
CameraCharacteristics chars = manager.getCameraCharacteristics(id);
// 检查是否支持闪光灯
Boolean flashAvailable = chars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
// 检查支持的AE模式
int[] aeModes = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES);
// 检查最大预览尺寸
StreamConfigurationMap map = chars.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] previewSizes = map.getOutputSizes(ImageFormat.YUV_420_888);
Log.d("CameraTest", "Camera " + id + " preview sizes: " +
Arrays.toString(previewSizes));
}
CONTROL_AE_MODE_ON,但实际拍照时AE根本不工作。后来用这个测试工具一跑,发现是驱动层实现有bug。所以,不要完全相信参数列表,一定要实际验证。
1.3 adb shell dumpsys media.camera:相机状态的「体检报告」
1.3.1 这个命令能干什么?
说白了,dumpsys media.camera就是把你手机里相机相关的所有状态,一股脑打印出来。包括:
- 当前打开的相机ID
- 当前的预览尺寸、拍照尺寸
- 当前的AE/AWB/AF状态
- HAL层的版本信息
- 是否有异常错误
我遇到相机打不开的问题时,第一反应就是跑这个命令。它往往能直接告诉我问题出在哪。
1.3.2 怎么用?
# 查看所有相机信息
adb shell dumpsys media.camera
# 只看某个特定相机(比如ID为0的后置相机)
adb shell dumpsys media.camera -c 0
# 只看HAL层信息
adb shell dumpsys media.camera -v hal
1.3.3 实战案例
有一次,用户反馈说「相机打开后黑屏」。我远程连上他的手机,跑了dumpsys media.camera,发现输出中有这么一行:
Camera 0: State: ERROR (3)
Error: 3 (CAMERA_ERROR_SERVER_DIED)
看到CAMERA_ERROR_SERVER_DIED,我立刻明白了——是Camera Service进程崩溃了。后来查下来,是因为某个三方应用占用了太多内存,导致系统杀掉了Camera Service。
你看,如果没有这个命令,我可能还在傻傻地看代码。
dumpsys的输出非常长,建议用grep过滤关键信息。比如:adb shell dumpsys media.camera | grep -i error。
1.4 本章知识体系
下面这张图,帮你把今天讲的三板斧串起来:
1.5 总结
今天这三样工具,说白了就是:
- Systrace——看性能,找卡顿根源
- Camera2测试工具——验功能,确认设备能力
- dumpsys media.camera——查状态,快速定位问题
我个人的工作流是这样的:遇到问题,先跑dumpsys看有没有明显错误;没有的话,抓Systrace分析性能;最后用测试工具验证猜想。这套流程帮我解决过至少80%的相机问题。
嗯,工具就介绍到这里。下一章我们开始动手写代码,从打开相机预览开始。