人脸识别运行时与会话重构变更记录
背景与问题
本次按 Android 人脸识别架构技能重新整理 SellWeight 的激活、初始化和识别启动链路。真机故障日志显示,选择人脸支付后应用并非正常返回首页,而是在百度人脸 native 库的 FaceAbilityTrack 链路发生 SIGSEGV,进程被系统重建后显示首页。故障前同时出现本地人脸数量为 0、搜索引擎未就绪,以及识别弹框重复初始化模型、数据库和内存索引的现象。
旧实现的问题包括:多个页面分别初始化人脸能力;弹框未等待索引就绪便打开摄像头;失败后启动首页并杀进程;连续帧可能并发进入 track 和活体/检索线程;索引 push 与 search 可能并发;弹框恢复和业务启动入口不统一。
新架构
1. 进程级 Runtime
新增 FaceRecognitionRuntime 与 FaceRuntimeCoordinator,按“在线激活(离线跳过)→业务模型→注册模型→本地数据库→1:N 内存索引”顺序初始化。Runtime 使用 UNINITIALIZED、INITIALIZING、READY、FAILED 四态,合并并发初始化,支持等待者取消与代际过滤,只保存 Application Context。
启动页只订阅 Runtime 最终结果;设置页激活、MQTT 和人员同步后的索引刷新也统一进入 Runtime,连续刷新通知会合并。
2. 单次识别 Session
新增 FaceRecognitionSession 与 FaceRecognitionSessionController。每个弹框的一次识别会话独立持有 Runtime 等待、摄像头、倒计时、代际、单帧门闩、单次终态和幂等释放。
Runtime 未就绪时不打开摄像头;本地人脸数量为 0 时提示先同步人员,不进入 native 识别。相机帧在异步使用前复制,旧会话和已销毁页面的迟到回调不会进入支付。
3. Native 调用串行化
FaceSDKManager.submitDetectCheck 在 track 或完整活体/检索链仍运行时拒绝下一帧。索引 push 不再中断正在执行的 native 更新;push 与 search 使用同一个 FaceSearch 锁,避免边检索边修改索引。
4. UI 与统一 Launcher
新增 FaceRecognitionLauncher,统一服务 MainActivity、WeightActivity、CookedFoodActivity,拦截状态已保存和重复弹框。
两个弹框仅渲染和转发用户操作,删除模型/数据库初始化与失败杀进程;在 onPause/onDestroyView 释放会话;增加无参恢复;Runtime 或人脸数据不可用时返回明确错误而不是误报超时。支付、订单、金额、人员 ID 和导航仍保留在 Activity。
自动化验证
- Runtime 测试覆盖并发初始化、等待者取消、旧代回调和失败重试,并先确认实现前编译红灯。
- Session 测试覆盖单帧门闩、旧代回调、单次终态和幂等释放。
- Launcher 测试覆盖重复启动与 Fragment 状态保存。
- Amazon Corretto 8 下执行
:app:testDebugUnitTest:37 个测试通过,失败 0,错误 0。 - 执行
:app:assembleDebug:BUILD SUCCESSFUL。 git diff --check与目标静态扫描通过。
真机验收边界
- 有本地人脸数据时,称重和熟食均可识别并进入原支付流程。
- 人脸数据为空时显示先同步人员,不打开识别链,不退出或返回首页。
- 连续进入、退出、重试时不崩溃、不重复弹框、旧结果不串入新订单。
- MQTT 人员变化触发索引刷新,刷新期间不崩溃,完成后可识别最新人员。
- 已初始化设备无网时复用本地授权、模型和人脸库。
- 主屏与客屏均正确关闭预览和提示。
本次未执行 Git 暂存、提交、推送、分支切换,也未在终端安装 APK。