From 00925db485d853baf1c8c9765479cccc5c29a994 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Wed, 2 Sep 2026 23:46:12 +0200 Subject: [PATCH] Candidate 1: the rising edge of an authentication sends the touch event only Labelled baseline on the proven loop, quick taps only: enrolled finger 2 of 10, wrong finger 0 of 5. Every press was one frame. The rising-edge frame costs ~700 ms because it runs the matcher twice -- event 5 and event 7 on the same image, two verdicts back. A human tap is over before a second frame can exist at that cost. Keeping only the touch event keeps what every recorded match followed, halves the rising frame, and may be the difference between one frame per tap and two. It is a single variable against a labelled baseline; if the rate drops, it comes out. Also fixes fptrial.sh's latency column, which was all zero: busybox date has no %N, so it reads /proc/uptime instead. --- interfaces/Fingerprintd-Engine.cppm | 11 ++++++++++- packaging/fptrial.sh | 2 +- tests/Engine/main.cpp | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/interfaces/Fingerprintd-Engine.cppm b/interfaces/Fingerprintd-Engine.cppm index f97d65e..46e3870 100644 --- a/interfaces/Fingerprintd-Engine.cppm +++ b/interfaces/Fingerprintd-Engine.cppm @@ -109,7 +109,16 @@ export namespace fingerprintd::engine { bool falling = !finger && prev_; if (rising) out.push_back(Event::FingerTouched); - if (finger && mode == Mode::Authenticate) + // CANDIDATE 1, under measurement: on the rising edge of an + // authentication, the touch event alone. It does run the matcher + // here (the rising frame answered `MATCH MATCH` / `rej rej` with + // both events -- two verdicts from one image), and every recorded + // match followed a touch event, so this keeps what is known to + // matter and drops ~300 ms of duplicate work on the frame that + // decides every quick tap. Held frames still send image-ready. + // Labelled baseline before this change: 2/10 quick taps matched, + // 0/5 wrong-finger taps. If the rate drops, this comes out. + if (finger && mode == Mode::Authenticate && !rising) out.push_back(Event::ImageReady); if (falling) out.push_back(Event::FingerReleased); diff --git a/packaging/fptrial.sh b/packaging/fptrial.sh index 81eb405..d11bc28 100644 --- a/packaging/fptrial.sh +++ b/packaging/fptrial.sh @@ -9,7 +9,7 @@ # is the latency a user feels. Unlabelled runs cannot be turned into a rate. C=${1:-10}; W=${2:-5} OUT=/tmp/fptrial-$(date +%Y%m%d-%H%M%S).log -now() { date +%s%N; } +now() { awk '{gsub(/\./,""); print $1 "0000000"}' /proc/uptime; } run() { # $1 = label printf '\n>>> %s -- press and LIFT (quick tap) ... ' "$1" t0=$(now) diff --git a/tests/Engine/main.cpp b/tests/Engine/main.cpp index 693407c..e56b2cc 100644 --- a/tests/Engine/main.cpp +++ b/tests/Engine/main.cpp @@ -121,8 +121,8 @@ int main() { // its press. Not to be removed without a measurement isolating it. TouchTracker a; auto a1 = a.Observe(true, Mode::Authenticate); - Check(a1.size() == 2 && a1[0] == Event::FingerTouched && a1[1] == Event::ImageReady, - "auth: rising edge reports touched then image-ready"); + Check(a1.size() == 1 && a1[0] == Event::FingerTouched, + "auth: rising edge reports touched only (candidate 1: one matcher run)"); auto a2 = a.Observe(true, Mode::Authenticate); Check(a2.size() == 1 && a2[0] == Event::ImageReady, "auth: a held frame still reports image-ready"); auto a3 = a.Observe(false, Mode::Authenticate);