Camera Debug

Camera Debug日志速查手册

做Camera这些年,我有个体会:Camera问题十有八九不是靠看代码看出来的,而是靠日志"顺藤摸瓜"找到的。

但问题来了——一个Camera Bug的日志动辄上万行,一打开全是密密麻麻的英文,很多人第一反应是"算了,从头看吧"。结果看了半天,时间线对不上,关键字也没抓到,最后还是靠猜。

这篇文章把我这几年踩坑攒下来的7个核心日志场景整理出来。每个场景配了过滤命令、示例日志和我的解读思路。不是教程式的"知识点罗列",而是实战中真正会用到的东西。

建议先收藏,排查的时候直接翻到对应章节。

先说方法论:30秒定位法

在看具体场景之前,先说一个我自己总结的"30秒定位法"。拿到一份Camera日志,不要从头读,按这个顺序做:

第一步(5秒):grep "CameraServer::connect"
确认是哪个App在调用、调的是哪个cameraId、用的API1还是API2。这一步决定了你后面看哪一层。

第二步(10秒):grep "FindBestSensorMode"
看驱动选了哪组分辨率。如果选错了,后面所有分析都白费——因为数据源就不对。

第三步(10秒):grep "configure_str"
看配了几路流、format是什么。配流不对,预览和拍照肯定出问题。

第四步(5秒):grep "process_capture_request"和"ProcessCaptureResult"
看请求和返回是不是配对。如果请求多、返回少,说明中间卡住了。

四个步骤走完,基本能判断问题出在哪一层。然后再去对应层深入看。

踩坑提醒:
很多时候你拿到的是别人抓的日志,但对方可能忘了抓kernel日志。Camera问题如果是驱动层导致的,光看logcat根本找不到根因。所以抓日志的时候,logcat和dmesg一定要同时抓。 

场景一:到底是谁在调用相机?

 adb logcat | grep "CameraServer::connect" 

这看起来是最简单的一步,但在实际排查中经常被忽略。

举个例子:线上反馈"相机打不开",你第一反应是什么?去看CameraService的报错?其实你应该先确认——是不是有别的App已经占着Camera了。Android的Camera是独占资源,一个App不释放,另一个就打不开。

你会在日志里看到:

 CameraService: CameraService::connect call (pid 12345, cameraId 0, clientName com.android.camera)
CameraService: CameraService::connect X (client 0x7f8a1234, cameraId 0) 

这段信息量很大:
pid 12345:调用方进程号,ps -A | grep 12345就能知道是哪个App
cameraId 0:打开的是哪个摄像头(0是主摄,1是副摄,具体看dtsi配置)
clientName:包名,直接告诉你是谁在调

如果connect之后迟迟没有后续日志,大概率是权限被拒或者资源被占用。这时候去看CameraService的error日志,通常会有一行Device is busy之类的话。

实战经验:
多摄场景下,cameraId的编号不一定按物理位置排。有些平台0是主摄、1是超广角、2是长焦,有些平台反过来。查dtsi里的sensor顺序最靠谱,别凭经验猜。 

场景二:配流到底配了什么?

配流(Configure Streams)是Camera2 API的核心步骤。简单说就是App告诉HAL:"我要几路数据流、每路什么格式什么分辨率"。这一步出了问题,后面全废。

HAL层看什么

 adb logcat | grep "configure_str" 
 CamX: [INFO][CORE ] configure_streams: streams_num=3
CamX: [INFO][CORE ] configure_streams: stream[0] format=33 width=4000 height=3000
CamX: [INFO][CORE ] configure_streams: stream[1] format=34 width=1920 height=1080
CamX: [INFO][CORE ] configure_streams: stream[2] format=35 width=640 height=480 

format那几个数字很多人看不懂,其实对应的是Android的HAL_PIXEL_FORMAT定义。我整理了个对照:

format值
实际含义
你会在哪见到
33
IMPLEMENTATION_DEFINED
拍照流,格式由HAL自己决定
34
YCbCr_420_888
预览流,最常见
35
RAW_OPAQUE
YUV分析流,调试用

排查思路:App申请了3路但日志只显示2路,说明有一路没配上去。先去App侧查Surface有没有正确创建,再去HAL查usecase有没有覆盖这个组合。

踩坑提醒:
format=33(IMPLEMENTATION_DEFINED)是最容易出问题的。因为这个格式"由HAL决定",不同平台实际用的buffer格式可能完全不同。如果要做YUV dump分析,一定要确认HAL实际给的是什么格式,别拿format值去判断。 

场景三:驱动到底选了哪组分辨率?

这个场景高通和MTK的关键字不一样。

高通平台:

 adb logcat | grep "FindBestSensorMode" 

MTK平台:

 adb logcat | grep -i "sensor mode|setSensorMode|ConfigSensor" 
 CamX: [INFO][SENSOR] FindBestSensorMode: sensorMode selected=2
CamX: [INFO][SENSOR] sensorMode[2]: width=4000 height=3000 fps=30 

为什么要关注这个?因为Sensor一般会注册多组分辨率模式,HAL根据App的需求"挑"一个最合适的。但"最合适"不一定是对的。

举个真实案例:有次用户反馈预览卡顿,查了半天发现App只要了1920x1080的预览,但HAL选了4000x3000的sensor mode(因为它"最接近"),然后再缩放到1080P。大分辨率缩放不仅浪费带宽,还增加了处理延迟,预览自然卡。

这种情况怎么排查?看FindBestSensorMode选了哪个mode,再对比App实际需要的分辨率,差距太大就是问题。

实战经验:
如果你在改sensor driver,注册SensorMode的时候注意一下fps配置。有些sensor的高分辨率模式只支持15fps,如果HAL选了这个模式,预览帧率会被拖到15fps,用户一看就知道有问题。 

场景四:帧的请求和返回,到底卡在哪一步?

这是排查黑屏、卡顿、帧率低的核心场景。Camera数据流的本质就是一个循环:App请求帧→驱动出帧→HAL处理→返回给App。任何一步断了,现象都不同。

我用一张链路图来说明:

 process_capture_request  →  CSLMessageHandler  →  ProcessCaptureResult  →  returnBuffer
    (App发请求)             (驱动回帧给HAL)          (HAL回帧给FW)          (FW给Surface显示) 

1. process_capture_request不出现 → App侧没发请求。查App的CaptureSession.Builder有没有正确配置,或者是不是生命周期没走完就被打断了。

2. CSLMessageHandler不出现(高通平台)→ 驱动没出帧。这时候必须看kernel日志,查ISP有没有报错、CSI有没有数据。MTK平台对应的关键字不太一样,搜handleMessage或ISP相关的回调。

3. CSLMessageHandler有但ProcessCaptureResult不出现 → 帧到了HAL但HAL没处理完。这种情况通常是HAL内部的pipeline某个node卡住了,搜node相关的error日志。

4. ProcessCaptureResult有但returnBuffer不出现 → Framework的buffer管理有问题。这种比较少见,通常和bufferqueue的slot分配有关。

踩坑提醒:
还有一种隐蔽的情况——日志里频繁出现frameMessage:requestId=0。这表示驱动已经开始丢帧了。requestId一直是0不是正常的,正常情况下requestId应该递增。出现这种情况说明buffer supply跟不上了,可能的原因是preview buffer数量太少或者处理太慢。 

场景五:Tuning参数生效了没有?

 adb logcat | grep "FillTuningModeData" 
 CamX: [INFO][TUNING] FillTuningModeData: sensorMode=0, feature1=3, feature2=6 

这个场景在什么情况下用到?用户反馈"拍照效果差"、"颜色不对"、"太暗了"——这些都可能和Tuning参数有关。

sensorMode=0:当前用的第0组分辨率模式
feature1=3, feature2=6:当前生效的feature组合

如果feature组合不对(比如该开HDR的时候没开),效果自然差。这种情况需要去查usecase的feature selection逻辑,或者Tuning XML配置文件。

实战经验:
Tuning参数的调试和芯片平台强相关。高通的Camx用XML配置,MTK用的是另一套体系。如果是跨平台调试,别用高通的思路直接套MTK,参数结构完全不同。 

场景六:dumpsys media.camera——被忽视的神器

很多人排查Camera问题只用logcat,但其实dumpsys media.camera输出的信息比logcat全面得多。

 adb shell dumpsys media.camera > camera_dump.txt 

这个命令输出的是Camera系统的"快照"——当前有哪些App在用Camera、配了什么流、session状态如何。

1. 搜availableStreamConfigurations → 看sensor注册了哪些分辨率。排查"App要的分辨率不支持"类问题时第一个看这个。

2. 搜Active Camera Client → 看当前谁在占用Camera。排查"Camera被占用打不开"时直接定位到是哪个App。

3. 搜Session → 看当前session的pipeline配置。排查"配流和预期不符"时对比这里的配置和App侧的申请。

踩坑提醒:
dumpsys输出的是"执行那一刻"的状态。如果你的问题是偶发的,要在问题复现的瞬间抓dumpsys。可以写个小脚本轮询抓取,或者用watch -n 1 'dumpsys media.camera | grep Active'持续监控。 

场景七:Kernel日志——驱动层问题的终极武器

当HAL层日志看不出问题时,Kernel日志是最后的希望。很多Camera硬件层的故障(I2C通信失败、CSI丢包、上电时序错误)只会在Kernel日志里体现。

怎么抓

 # 实时监控(推荐)
adb shell dmesg -w > dmesg.txt

# 抓取全部历史
adb shell cat /proc/kmsg > kmsg.txt 

第一步:搜sensor名称确认probe是否成功

 dmesg | grep -i "probe|sensor" 
 # 正常情况
[ 3.215678] gc08a3_front_camera_sensor probe success, sensor_id=0x08a3
[ 3.218901] imgsensor 0-0010: sensor name: gc08a3_mipi_raw

# Probe失败
[ 7.009427] imgsensor 0-0010: Read sensor id fail, write id: 0x20, id: 0x0
[ 7.011459] imgsensor 0-0010: i2c transfer failed (-6) 

看到i2c transfer failed,基本就是I2C通信有问题。常见原因:上电时序不对、I2C地址错误、GPIO冲突。

第二步:搜CSI相关错误

 dmesg | grep -i "csi|mipi|d-phy" 

CSI(MIPI CSI-2)是sensor和ISP之间的数据通道。如果这里报错,数据根本传不过来,表现就是黑屏或者花屏。

踩坑提醒:
Kernel日志的时间戳是从开机开始算的秒数,和logcat的时间戳不一样。要把两个日志的事件对上,需要找一个共同的时间点(比如App打开Camera的那条日志),然后算时间差。 

速查表(建议截图保存)

场景
关键字
平台
确认谁在调用
CameraServer::connect
通用
HAL配流
configure_str
高通
FW配流
createStream
通用
Sensor选模式
FindBestSensorMode
高通
App请求帧
process_capture_request
通用
驱动回帧
CSLMessageHandler
高通
HAL回帧给FW
ProcessCaptureResult
通用
丢帧信号
frameMessage:requestId=0
高通
Tuning参数
FillTuningModeData
高通
Camera全景
dumpsys media.camera
通用
Probe确认
probe / sensor
通用
CSI错误
csi / mipi
通用
 # 一条命令搞定全链路
adb logcat | grep -E "CameraServer::connect|configure_str|FindBestSensorMode|process_capture_request|ProcessCaptureResult|CSLMessageHandler|returnBuffer" 

我的调试习惯

最后说几点个人经验,不是方法论,就是习惯:

1. 抓日志先清缓存。adb logcat -c清掉旧日志,然后复现问题。否则一堆历史日志干扰判断。

2. logcat和dmesg同时抓。Camera问题经常跨层,只抓一个很容易漏掉关键信息。

3. dumpsys别忘了用。排查分辨率和配置类问题时,dumpsys比logcat直觉得多。

4. 抓完整buffer。adb logcat -b all抓所有buffer(main+system+crash),有些crash日志不在main buffer里。

5. 时间戳对齐。一份日志里可能有多个时间线(logcat时间、kernel时间、uptime),先搞清楚每个时间线是什么基准,再对齐。


以上就是我这几年排查Camera问题总结的7个核心场景。这些关键字不是背出来的,是踩出来的。每个关键字背后都对应着一类问题,多查几次就记住了。

如果你在做Camera开发,遇到具体问题拿不准怎么排查,欢迎在评论区留言交流。


关注公众号「小驰行动派」

回复「Camera日志」获取本文速查手册PDF版 + 高清排查流程图

更多Camera开发实战内容

欢迎加入知识星球「小驰成长圈」

欢迎扫码关注「小驰行动派」公众号 10 年Camera开发 | Camera技术干货 | 行业洞察 | Camera实战分享
小驰行动派公众号 扫一扫关注
分享到: 复制链接
← 上一篇 Camera开发实用调试工具箱 下一篇 → Android 17 相机 API 更新,实战手册

相关文章

推荐课程

想系统学习 Camera 开发?看看这些课程

评论 (0)

暂无评论,快来抢沙发吧