USB 相机设置页 ANR 修复方案
1. 方案状态
- 日期:2026-07-23
- 目标版本:
fix_camera_config 当前工作区
- 状态:已落地并完成真机回归
- 设备:FY-3576SE
2. 问题与根因
设备在 2026-07-23 13:43:33 进入相机设置页时发生输入分发超时,2026-07-21 曾出现相同调用链。
SettingsCameraFragment.refreshResolutionSpinner → CameraUsbUtils.getCamaraSize → CameraHelper.getSupportedSizeList → CameraConnectionService.getCamera → 等待 USB 权限/相机服务。
这是同步硬件查询占用主线程造成的 ANR,不是 CPU 或内存不足。其后的 WorkManager、MQTT 超时属于主线程失去响应后的伴随现象。
3. 修复设计
3.1 主线程只读缓存
- 设置页刷新分辨率时只读取不可变快照副本,不再直接访问 UVC 服务。
- 相机能力列表由专用单线程执行器读取。
- 新任务取消或淘汰旧任务;相机切换、释放或页面退出后,过期结果不得回写当前相机。
3.2 两阶段相机启动
- USB 设备打开后先启动相机,避免在主线程等待能力列表。
- 相机真正打开后,在后台查询支持的分辨率并更新缓存。
- 实际分辨率与已保存分辨率不同时,完整重建一次相机助手,并用缓存中的目标
Size 打开。
- 同一“相机 ID + 已保存分辨率”最多自动重试一次,防止设备拒绝目标分辨率时形成重连循环。
3.3 生命周期保护
- 相机助手释放时取消未完成的能力查询。
- 切换相机、修改分辨率和停止相机时清理对应快照或重试标记。
- 查询前后均核对相机助手实例、USB 设备及当前相机 ID。
4. 代码范围
CameraUsbUtils.javaCameraSizeSnapshot.java
LatestCameraTaskRunner.javaSettingsCameraFragment.java
CameraSizeSnapshotTest.javaLatestCameraTaskRunnerTest.java
5. 验收标准与结果
- 单元测试覆盖快照隔离、后台延迟执行、最新任务生效和任务失效:通过。
:app:testDebugUnitTest:通过。:app:assembleDebug:通过。
- 真机能力列表读取:成功,读取到 10 个分辨率条目。
- 真机保存分辨率恢复:相机助手重建一次后,实际预览从
3840x2160 切换为 2048x1536。
- 相机设置页连续交互 10 秒:进程保持不变、页面保持前台、无新增 ANR、无重复重连。
6. 风险与回退
- 个别 UVC 设备不接受已保存分辨率时,保留设备实际分辨率并停止自动重试,不影响界面响应。
- 回退时应整体回退异步能力查询、快照读取和一次性重启保护,不能只恢复设置页同步查询。