android: fix launchMode (singleTask) root cause of reconnect storm; drop SET_CONFIGURATION reset; fix analysis temp units, NUC block size, viewer back keys

This commit is contained in:
ZXCLI
2026-09-12 02:30:05 +08:00
parent 4cb6e69ea4
commit 376b8389ea
12 changed files with 527 additions and 36 deletions
+67
View File
@@ -489,6 +489,73 @@
"未连接"分支显示,正常出图时用户看不到任何反馈)。
- [x] 单测 66 → **76 项全绿**debug + release(R8) 双构建通过;APK 已更新。
## 用户反馈修复 第二十一轮(2026-09-12,无线 adb 真机调试:根因是 launchMode
**本轮最大的发现**:前几轮反复出现的"连接风暴/重连循环/相机每 2 秒重枚举"
(设备号 060→093 一路涨、CPU 136%、状态在 streaming/no_device 间抖动)
**根因是 `MainActivity` 少了 `android:launchMode="singleTask"`**
- Manifest 给 MainActivity 声明了 `USB_DEVICE_ATTACHED` intent-filter,而
**MIUI 在相机插着时会持续重复广播该事件**。默认 `standard` 启动模式下,
每次广播都创建一个**新的 MainActivity 实例**——真机 `dumpsys` 实测同时存在
**2 个实例**,各自持有自己的 ViewModel、IrSession、广播接收器,全部争抢同一台
相机;谁被挤掉谁就重新握手,于是相机被反复复位→重枚举。
- 官方 App 的 manifest 正是 `launchMode=2 (singleTask)`aapt 实测)。
- 加上 `singleTask` 后实测:Activity 实例 1 个、**设备号 65 恒定 40 秒不变**、
状态稳定 streaming、fps 15.1、CPU 归零。
- 排查过程中曾按症状加过多层防御(connect 互斥锁、代际守卫、attach 去重、
失败退避+自动重试、stream 循环退避)。这些**已一并保留**:它们各自修掉了
真实存在的小问题(见下),但都不是那个根因;根因只有 launchMode 一处。
**本轮真机(小米 22041211AC / Android 12 / MIUI)实测通过的功能**
- [x] 出流:冷启动一次成功,15fps、ref=true、timeouts=0
- [x] **拍照**`capture: nuc=yes rot=90 saved=true`;文件入 `DCIM/MAG160C/`
- [x] **照片含正确温度数据**NUC 块 153600B / 76800 样本(照片分辨率 1:1)、
零空洞、温度 22.6~32.9℃(均值 25.9℃)——不再有 -161℃/145℃
- [x] **录像**:开始→停止**不闪退**MP4 2.2MB / 134 帧,`moov` box 完整可播
- [x] **分析页温度正确**`min=22.606 max=32.877 center=24.683`
与文件真值**逐位吻合**
- [x] **分析页加测温点 + 另存新照片**:生成 `_edit.jpg`,含 PROBES 块
`116,102,Pt1,24674` / `150,169,Pt2,24838`,数值合理)+ NUC 块保留
- [x] **相册**:列出 4 张 → 点开全屏查看器(返回/删除)→ 返回键回列表 →
删除确认对话框 → 删除后文件 4→3、列表同步
- [x] **分析 tab 只列可测温照片**(旧的无 NUC 照片被过滤,符合设计)
**本轮顺带修掉的真实缺陷**(都在真机上复现过):
1. `UsbTransport.open()``claimInterface` 之后发 **SET_CONFIGURATION**——
这是设备级复位,会让相机立刻重新枚举。官方代码从不发(仅 claimInterface)。
**已删除**。(实测:app 停止时相机 30 秒稳定不动,启动后设备号立刻开始爬升。)
2. 分析页 `_minTempC.value = mn / 1000f`——`mn` 是 NUC **counts** 却被当温度,
显示 9.2/10.4℃(centre 走了正确路径所以是对的)。已改为过温度曲线。
3. `Mdt.compose` 只接受 `nucPixels.size == 38400`,而真实块是照片分辨率
153600)→ **静默丢弃**,而 capture 日志仍打 `nuc=yes` 掩盖了它。
已改为按尺寸下限校验。
4. 三个全屏查看器(相册查看器、分析查看器)**都没有 BackHandler**——
返回键直接退出 app。已补。
5. USB attach 广播未校验 VID,任何 USB 事件都会触发 `connect()`MIUI 重复
广播时把健康会话的状态覆盖成 `no_device`(画面在跑却显示"未检测到热像仪")。
已改为只认 0x833C 且已有会话时忽略。
6. `streamLoop` 在端点 halt 后 `bulkTransfer` **立即返回失败**(不等超时),
循环以约 1000 次/秒空转、每次两次控制传输——实测 28000 条失败日志、
**CPU 136%**。已加三级退避(0/20/250ms)+ 日志静默 + 死链约 1 分钟后收尾。
7. `connect()` 失败后无人重试(backoff 只拦截、不重发),UI 会永远停在
`no_handshake`。已加单实例自动重试。
8. `Mp4Recorder.stop()` 的收尾 drain 异常现在被记录说明(`file kept`),
不再让人误以为文件没生成;实测该异常下 MP4 仍完整可播。
**调试方法记录**(供后续排查):
- 设备端日志:`/sdcard/Download/MAG160C/debug_*.log.txt`DCIM 被 MIUI 拒收
text/plain,自动回退到 Download),可 `adb pull` 取回
- MIUI 禁止 adb 注入输入(`INJECT_EVENTS`),但设备有 **Magisk root**
`adb shell su -c 'input tap X Y'` 可以,`uiautomator dump` 配合读控件坐标
- 相机是否在重枚举:`dumpsys usb | grep -oE 'bus/usb/002/[0-9]+'` 连续采样看
设备号是否变化——这是判断"是硬件问题还是我们代码问题"的最快手段
(app 停止时稳定、启动后爬升 = 我们的代码在复位设备)
- Activity 实例数:`dumpsys activity activities | grep 'Activities=\['`
出现两个 MainActivity = launchMode 问题
## 用户反馈修复 第二十轮(2026-09-11,第三轮真机:分析测温/标注/相册/界面)
用户第三轮实机测试(含截图)报出以下问题,本轮全部处理: