3、logcat日志分析:Camera关键log标签与实战技巧

做Camera HAL层调试,说白了就是跟logcat打交道。我刚开始带项目那会儿,每天盯着几十万行log找问题,眼睛都快瞎了。后来慢慢摸出门道,发现只要抓住几个关键标签,效率能翻好几倍。

今天我就把这套方法拆开揉碎了讲给你听。你想想看,如果连log都不会看,那调试就像蒙着眼睛走路,对吧?

3.1 必须记住的三个核心log标签

Android Camera HAL层调试,你只需要盯住三个标签。其他的可以暂时忽略,等出了问题再回头查。

标签名 所属模块 典型用途
CAM_HAL HAL层通用 HAL接口调用、参数传递、错误码
CamX Qualcomm平台 Pipeline配置、Sensor控制、ISP处理
CHI Qualcomm平台 Usecase切换、Node图构建、XML解析

CAM_HAL 是通用标签,所有HAL层的核心流程都会打这个标签。我习惯先过滤这个,看整体流程是否走通。

CamX 和 CHI 是Qualcomm平台特有的。如果你用MTK平台,对应的是 MtkCam 和 MtkCam3。道理是一样的,只是名字不同。

我的经验: 遇到预览黑屏问题,先看CAM_HAL有没有返回错误。如果CAM_HAL一切正常,再切到CamX看Sensor有没有出图。我曾经有个案子,CAM_HAL显示正常,但CamX报了个Sensor初始化超时,折腾了两天才发现是MCLK频率配错了。

3.2 log等级设置:别让垃圾信息淹了你

默认的log等级是 INFO,但调试HAL层时,这个等级远远不够。你需要把等级降到 DEBUG 甚至 VERBOSE。

怎么设置?两种方法:

  1. adb命令临时设置(推荐,重启后失效)
  2. 修改prop文件永久设置(需要root权限)
// 临时设置,只对当前adb会话有效
adb shell setprop persist.vendor.camera.debug.logs 1
adb shell setprop persist.vendor.camera.debug.meta 1

// 设置单个标签的log等级
adb shell setprop log.tag.CAM_HAL VERBOSE
adb shell setprop log.tag.CamX VERBOSE
adb shell setprop log.tag.CHI VERBOSE

// 重启cameraserver让设置生效
adb shell killall cameraserver

小技巧: 我习惯写个脚本,一键设置所有需要的log等级。不然每次手动敲太累了。脚本里加上 adb root 和 adb remount,省得每次都要输密码。

为什么要设成VERBOSE?因为很多关键信息只在VERBOSE等级输出。比如Sensor的帧率、曝光时间、增益值,这些在DEBUG等级是看不到的。

注意: 生产环境千万别开VERBOSE。log量会暴增,影响性能。我见过有人把VERBOSE开了一整天,结果log文件撑爆了/data分区,手机直接变砖。

3.3 过滤与抓取技巧:精准定位问题

logcat默认会输出所有进程的log,信息量太大。你需要学会过滤。

最基本的过滤方法:

// 只显示CAM_HAL标签的log
adb logcat -s CAM_HAL

// 同时显示多个标签
adb logcat -s CAM_HAL CamX CHI

// 显示某个进程的log(比如cameraserver)
adb logcat --pid=$(adb shell pidof cameraserver)

// 保存到文件,方便后续分析
adb logcat -s CAM_HAL CamX CHI > camera_log.txt

我个人最常用的是 -s 参数加时间戳:

adb logcat -v time -s CAM_HAL CamX CHI

这样每条log前面都有时间戳,方便看时序。比如Sensor配置和Stream配置之间的时间差,一眼就能看出来。

还有一个技巧:用 grep 做二次过滤。比如我只想看错误相关的log:

adb logcat -s CAM_HAL | grep -i "error\|fail\|fatal"

避坑指南: 我曾经在调试双摄时,发现log里一直报错,但就是找不到原因。后来才发现是grep过滤太严格,把关键信息漏掉了。所以我的习惯是:先抓全量log,再用grep过滤。全量log留着,万一需要回溯呢?

3.4 常见错误log解读:看到这些别慌

下面是我总结的几个高频错误log,你遇到时可以直接对照排查。

错误log内容 可能原因 排查方向
CAM_HAL: configureStreams failed: -38 Stream配置参数不合法 检查分辨率、格式、buffer数是否匹配
CamX: Sensor power up failed Sensor上电时序异常 检查MCLK、AVDD、DVDD、IOVDD电压
CHI: Usecase switch timeout Usecase切换超时 检查XML配置,确认Node图是否完整
CAM_HAL: processCaptureRequest timeout Capture请求处理超时 检查ISP处理时间,确认是否帧率过高
CamX: Buffer queue full Buffer队列满了 检查Consumer端是否及时释放buffer

举个例子,configureStreams failed: -38 这个错误我遇到过不下十次。错误码-38对应的是 EINVAL,意思是参数无效。但具体是哪个参数无效?

我的排查步骤:

  1. 先看log里打印的Stream配置信息,确认分辨率、格式是否正确
  2. 再看App层请求的Stream数量和HAL层支持的最大数量是否一致
  3. 最后检查是否有重复的Stream ID

有一次我排查了半天,最后发现是App层传了一个 YUV420_888 格式,但Sensor只支持 NV12。这种问题,不看log根本想不到。

我的习惯: 遇到错误log,先看错误码。每个错误码都有对应的含义,比如-22是 EINVAL,-12是 ENOMEM。记住几个常见的,排查速度能快很多。

3.5 实战:用log定位预览黑屏问题

我拿一个真实案例给你演示一下。某次项目,预览黑屏,但拍照正常。

第一步,抓log:

adb logcat -v time -s CAM_HAL CamX CHI > preview_black.log

第二步,看CAM_HAL:

// 发现configureStreams正常返回0
// 但processCaptureRequest返回了-22
// 错误码-22 = EINVAL,参数无效

第三步,看CamX:

// 发现Sensor输出正常,帧率稳定在30fps
// 但ISP处理时,报了一个"Invalid buffer format"

第四步,看CHI:

// 发现Usecase配置里,Preview Node的输出格式是NV21
// 但App请求的是YUV420_888
// 格式不匹配,导致ISP无法处理

问题找到了:XML里Preview Node的格式配错了。改成NV12后,预览正常。

总结一下: 看log就像破案,要有步骤。先看整体流程(CAM_HAL),再看具体模块(CamX/CHI),最后定位到具体参数。别一上来就扎进细节,容易迷失方向。

3.6 本章知识体系

下面这张图是我自己画的,把本章的核心逻辑串起来了。你保存下来,调试时对照着看。

Camera HAL层logcat调试知识体系 三个核心标签 log等级设置 过滤与抓取 CAM_HAL HAL接口调用 参数传递 错误码返回 CamX Pipeline配置 Sensor控制 ISP处理 CHI Usecase/Node/XML 等级设置方法 adb setprop临时设置 prop文件永久设置 推荐VERBOSE等级 注意事项 生产环境不开VERBOSE 重启cameraserver生效 脚本化一键设置 过滤方法 -s 标签过滤 --pid 进程过滤 grep 二次过滤 抓取技巧 加时间戳 -v time 保存到文件 > log.txt 先抓全量再过滤 常见错误log解读 configureStreams失败 | Sensor上电失败 | Usecase超时 | Buffer满

这张图把三个核心标签、log等级设置、过滤抓取技巧、常见错误解读串在了一起。你调试时,按这个流程走,基本不会漏掉关键信息。

好了,logcat分析这块就讲这么多。记住一句话:log是死的,人是活的。多练、多总结,你也能成为log分析高手。

可可精品资料库