3. 黑屏问题根因分析框架:从上层APP到HAL层的调用链路排查方法论
黑屏问题(Preview Black Screen / No Frame)是Camera HAL层最常见的故障现象之一。其根因可能散布在从上层APP发起预览请求,到HAL层驱动输出第一帧数据的整条调用链路上。本章建立一套分层排查框架,帮助工程师按“APP → Framework → Camera Service → HAL → Driver”的路径逐层定位。
3.1 调用链路全景图
下图展示了Android Camera预览启动时的核心调用链路,以及每个环节可能引发黑屏的典型故障点:
3.2 分层排查方法论
黑屏问题的排查应遵循“自上而下、逐层验证”的原则。每一层都有独立的验证手段和典型故障模式。以下表格总结了各层的排查重点:
| 层级 | 排查对象 | 验证手段 | 典型黑屏根因 |
|---|---|---|---|
| APP 层 | Surface / TextureView / SurfaceView | logcat 搜索 “Surface is not valid” / “onSurfaceTextureDestroyed” | Surface 未创建或已被销毁;权限未动态申请 |
| Framework 层 | CameraManager / CameraDevice | dumpsys media.camera / logcat 搜索 “connectDevice” / “openSession” | Camera ID 不存在;Service 进程异常重启 |
| Camera Service | CameraProvider / Session / Stream | dumpsys media.camera -v / logcat 搜索 “configureStreams” 返回值 | Stream 配置参数冲突(分辨率/格式不匹配);Session 创建失败 |
| HAL 层 | configureStreams / processCaptureRequest / buffer_handle | HAL dump / logcat 搜索 “HAL” / “buffer” / “error” | Buffer 分配失败(内存泄漏);死锁导致 request 未处理;Gralloc 异常 |
| Driver / Sensor | MIPI / ISP / Sensor 初始化 | kernel log / dmesg / cat /sys/kernel/debug/... | MIPI 信号丢失;Sensor 上电时序错误;I2C 通信失败 |
3.3 逐层排查步骤与关键日志
3.3.1 APP 层:确认 Surface 与权限
黑屏问题中约 30% 的根因在 APP 层。首先确认 Surface 是否已就绪,以及 Camera 权限是否被授予。
- 检查 Surface 状态:在 logcat 中搜索
Surface is not valid或onSurfaceTextureDestroyed。如果 Surface 在 startPreview 之前已被销毁,APP 层需要修复生命周期管理。 - 检查权限:搜索
Permission Denial或CAMERA权限相关日志。Android 6.0+ 需要动态申请权限。
快速验证: 使用
adb shell dumpsys media.camera 查看当前 Camera 客户端列表。如果 APP 未出现在列表中,说明 APP 层未成功连接到 Camera Service。
3.3.2 Framework 层:确认 Camera ID 与 Service 状态
APP 层确认无误后,检查 Framework 层是否正确创建了 CameraDevice 和 Session。
- 检查 Camera ID:搜索
connectDevice日志,确认使用的 Camera ID(0/1/2)是否在设备支持的列表中。 - 检查 Service 状态:搜索
CameraService::connect或CameraService::disconnect。如果 Service 频繁重启,可能是 HAL 层崩溃导致。
// 典型 Framework 层正常日志示例
I CameraService: CameraService::connect call (PID -1, camera1)
I Camera2Client: Camera2Client::initialize (camera ID 0) success
I CameraDeviceClient: CameraDeviceClient::initialize (camera ID 0) success
3.3.3 Camera Service 层:检查 Stream 配置
Stream 配置是黑屏的高发区。HAL 层如果返回 INVALID_OPERATION 或 BUFFER_ERROR,会导致预览无数据。
- 检查 configureStreams 返回值:搜索
configureStreams和status。正常返回OK (0)。 - 检查 Stream 参数:确认分辨率、格式(NV21/YUV420/IMPLEMENTATION_DEFINED)是否被 HAL 支持。
// 典型 Stream 配置失败日志
E Camera3-Device: configureStreams: 0x... failed, status: INVALID_OPERATION
E Camera3-Device: Stream 0: width=1920 height=1080 format=0x23
// 0x23 = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,需确认 HAL 是否支持
3.3.4 HAL 层:核心排查区(内存泄漏与死锁)
HAL 层是黑屏问题最复杂的排查区域。内存泄漏和死锁是两大主要根因。
重点提示: 如果 HAL 层存在内存泄漏,通常不会立即导致黑屏,而是随着预览次数增加,buffer 分配逐渐失败,最终出现黑屏。死锁则会导致所有 request 被阻塞,logcat 中看不到任何错误日志,只有超时。
HAL 层排查清单:
- 检查 buffer 分配:搜索
allocateBuffer/dequeueBuffer/buffer_handle_t。如果返回NO_MEMORY,说明存在内存泄漏。 - 检查 request 处理超时:搜索
processCaptureRequest耗时。如果超过 1 秒仍未返回,可能是死锁或驱动阻塞。 - 检查 HAL dump:使用
adb shell dumpsys media.camera -v查看 HAL 内部状态,包括 buffer 池使用量、pending request 数量。 - 检查 Gralloc:搜索
gralloc/alloc/free。Gralloc 泄漏是 HAL 层内存泄漏的常见来源。
// HAL 层内存泄漏典型日志
E Camera3-Stream: allocateBuffers: failed to allocate 1 buffers, total allocated=64, max=64
E Camera3-Device: processCaptureRequest: buffer handle is NULL for stream 0
// 说明 buffer 池已耗尽,存在泄漏
3.3.5 Driver / Sensor 层:硬件信号验证
如果 HAL 层日志正常,但依然黑屏,问题可能出在底层驱动或硬件。
- 检查 MIPI 信号:使用
dmesg搜索mipi/csi/lane。如果出现CRC error或lane sync error,说明物理链路异常。 - 检查 Sensor 初始化:搜索
sensor/power on/i2c。如果 I2C 通信失败,Sensor 无法输出数据。
// 驱动层 MIPI 异常日志
[ 1234.5678] mipi_csi: CSI2_ERR_CRC: 0x00000001, lane 0
[ 1234.5679] mipi_csi: CSI2_ERR_ECC: 0x00000002, lane 1
// 需要检查硬件连接或时钟配置
3.4 排查流程总结
以下流程图总结了黑屏问题的完整排查路径:
3.5 关键工具与命令速查表
| 工具/命令 | 用途 | 排查层级 |
|---|---|---|
logcat -s CameraService |
查看 Camera Service 连接与配置日志 | Framework / Service |
logcat -s Camera3-Device |
查看 HAL 层 Stream 配置与 request 处理日志 | HAL |
adb shell dumpsys media.camera -v |
查看 Camera 整体状态,包括 HAL dump | Service / HAL |
adb shell dmesg | grep -i mipi |
查看 MIPI 物理层错误 | Driver |
adb shell cat /sys/kernel/debug/... |
查看 Sensor 寄存器状态(需 root) | Driver / Sensor |
systrace --app=com.android.camera |
分析 Camera 线程调度与死锁 | HAL / Framework |
核心原则: 黑屏排查不要跳跃。每层使用对应的工具验证通过后,再进入下一层。HAL 层是排查耗时最长的区域,建议优先检查 buffer 分配和死锁,再深入驱动层。