PC681 称体接收缓存竞态修复方案

日期:2026-07-31
状态:已实施,待实机压力验收

结论

在无法修改 DeviceSDK-80.1.10.12.20260129.aar 的前提下,主页进入后台时不再停止或重建 SDK 接收线程,也不再直接修改 SDK 的 mReadThreadmCacheLenisListening。应用只解绑业务监听器,返回主页时重新绑定监听器并复用原接收线程。

该方案从应用侧移除了导致 mCacheLen 被并发改成 -29 的写入路径,同时保留设置页通过现有串口输出流发送红外命令的能力。

问题背景

目标版本为 2.3.5,设备为 Android 11、arm64-v8a。核心崩溃为:

ArrayIndexOutOfBoundsException: dstPos=-29 length=1024
PC681ScaleManager.addDataToCache(...)

约束

决策

  1. HomeActivity.onStop() 继续调用封装层 pause()
  2. pause() 只将 hardwareListener 置空。
  3. SDK 监听标记、接收线程、缓存长度和串口流保持不变。
  4. 回调发现监听为空时立即返回。
  5. 返回主页后重新绑定业务监听,并复用原 SDK 线程。

hardwareListener 增加 volatile,保证跨线程绑定和解绑的可见性。

替代方案

实现范围

未修改 AAR、主页业务流程、设置页命令协议或资源文件。

测试与验证

回归测试在旧实现上先失败,失败点为旧 pause() 修改了 SDK 监听状态;修改后同一定向测试通过。

JAVA_HOME=$(/usr/libexec/java_home -v 1.8) \
./gradlew --no-daemon :app:testDebugUnitTest :app:assembleDebug --console=plain

结果:BUILD SUCCESSFUL in 38s。本地单元测试 13 项,0 失败、0 错误、0 跳过;Debug APK 已生成。

风险与边界

实机验收

  1. 保持秤体 50ms 或 100ms 连续输出,主页与设置页连续切换至少 100 次。
  2. 覆盖快速切换、Home 键前后台切换和息屏恢复。
  3. 确认不再出现 dstPos=-29 崩溃。
  4. 确认红外命令仍可发送,返回主页后称重和扫码正常且无重复回调。

验收结果

代码回归测试、全量单元测试和 Debug 构建已通过。硬件并发时序无法由本地 JVM 完整模拟,最终结论需实机压力测试确认。