4.3 KiB
人脸支付前置检查与启动准备
原先的提示在做什么
收银弹框 _dispatchFace 显示“正在检查人脸库与摄像头状态”后,依次执行:
- Floor 查询本地人脸表总行数,空库进入就地注册引导。
- 读取本地设备人脸参数和 SDK 授权文件,必要时初始化 FaceServer。
- 原生 SQLite 扫描所有有效样本编号,再获取 SDK 内存库中的样本编号,比较两个集合是否一致。
- 申请相机权限,再创建业务识别会话。
这段检查不下载人脸,也不在线重新激活 SDK。提示期间尚未实际打开摄像头;真正的识别引擎和 Camera 启动由后续原生会话执行。RGB/IR 色度探测只在设置页枚举摄像头时运行。
虽然原生集合查询只返回 sampleId,SQL 中判断有效特征的 TRIM(COALESCE(faceModel, '')) 仍需访问所有记录的特征 JSON。因此磁盘读取、页缓存和同时运行的人脸任务会影响耗时。状态查询还与其他人脸操作共用单线程执行器,可能等待队列。现场 1 秒和 3–4 秒的具体占比需要分段日志确认。
当前流程
- Load 完成激活、整库装载和残缺行清理后,进行一次完整核对并保存当前进程的健康准备结果,同时提前申请相机权限并检查是否枚举到摄像头。
- 正常支付复用准备结果,不再重复执行 Floor 计数和原生整库集合比较。
- 同步、删除、重建、SDK 激活会使结果失效。操作覆盖数据库、SDK 和失败补偿的整个边界,最外层收尾后统一核对;批量删除也只在整批结束时核对。
- 配置变化和原生启动异常使结果失效。占线、异常或不健康结果不会长期缓存;旧查询不能覆盖新一代结果。
- 设置页诊断仍然实时读取完整状态。
- 每次会话继续读取相机权限和处理真实开相机失败;硬件状态不永久缓存。
Load 的摄像头检查是权限与设备枚举,不预开 Camera。原生原有的 Camera/识别引擎 20 分钟热保持继续使用;首次识别、长时间空闲释放、相机配置切换等情况仍需冷启动。
识别成功后立即继续
原先虹软比对通过后,要等 Java 的 1.5 秒提示清空定时器才通知会话;Flutter 收到结果后又固定展示成功画面 1 秒,合计约 2.5 秒。
现在成功结果直接投递主线程,不再等待提示展示。原生仍先保存成功帧现场图片,再向 Flutter 回传结果;Flutter 收到结果后立即结束当前原生会话,完成后再通知收银业务读取人员与钱包信息。
结果锁、会话代次校验、过期回调拦截和关闭界面后的回调保护均保留。失败提示保留时间与失败重试间隔不变。正常成功流程不再使用固定展示延迟,但现场图片处理、会话收尾及后续业务接口仍有实际耗时。
排查日志
FacePaymentPerf:
readinessMs、cacheHit:支付准备耗时和是否复用结果。cameraPermissionMs:当前会话读取/申请相机权限的耗时。
FaceStatusPerf:
queueMs:完整核对在原生执行器中的排队时间。authInitMs:授权文件读取和 FaceServer 初始化。sqliteScanMs:有效样本编号扫描。sdkCompareMs:SDK 数量、内存编号集合读取和集合比较。totalMs:完整原生核对耗时,不包含队列等待。
FaceSessionManager 原有日志继续记录识别引擎初始化及 Camera.open 耗时。上述新增日志只包含计时、计数或状态,不记录激活密钥和人脸特征。
验证边界
2026-10-23:69 项 Flutter 测试通过,包含缓存并发/失效、数量不变的样本替换、同步失败回滚,以及成功后不推进时间即可继续、必须等待会话结束、取消/销毁保护和结果幂等。17 项 Android JVM 单元测试通过,覆盖成功立即调度、失败提示保持 1.5 秒、旧通知替换与切换会话后的通知取消。静态分析没有 error,仍有项目已有的 warning/info;本次修改涉及的 Dart 文件单独分析无问题。
包含本次成功延迟移除的 Debug 和 Release 均编译通过,最新 Release 安装包为 build/app/outputs/flutter-apk/app-release.apk。
尚未把本次改动安装到现场设备,未声称真机支付耗时或真人活体识别已验证。