diff --git a/implementations/main.cpp b/implementations/main.cpp index 2b31548..55a79d5 100644 --- a/implementations/main.cpp +++ b/implementations/main.cpp @@ -1280,20 +1280,19 @@ public: out.frames++; std::string note; - bool rising = finger && !inPress; - if (rising) { - inPress = true; pressMatched = false; pressRejected = false; - pressFrames = 0; rescans = 0; pressFid = 0; - out.presses++; - // The frame that detected the finger is the finger LANDING -- - // partial contact, and the frame that rejects most often. - // Capture once more now that it has settled, so the image the - // matcher sees on the first report is a real one. One capture, - // ~50 ms, on the frame that decides every quick tap. - auto c2 = SendCommand(app_, ta::Cmd::CaptureImage, cap); - if (c2.invoked) { c = c2; note += " recap"; } - } + // No recapture on the rising edge. It was tried, on the theory that + // the detecting frame is the finger landing and a frame 50 ms later + // would be a settled one. On a quick tap the finger was already + // gone 50 ms later: the recapture read the idle floor (metric 133, + // still flagged FINGER from the first capture) and an empty image + // was reported to the matcher. A guaranteed miss on exactly the + // case it was meant to fix. for (ta::Event ev : tracker.Observe(finger, en::Mode::Authenticate)) { + if (ev == ta::Event::FingerTouched) { + inPress = true; pressMatched = false; pressRejected = false; + pressFrames = 0; rescans = 0; pressFid = 0; + out.presses++; + } std::vector evbuf(ta::EventContextSize); ta::BuildEventContext(evbuf, { .event = ev }); // A zero-initialised buffer cannot tell "the matcher never diff --git a/interfaces/Fingerprintd-Engine.cppm b/interfaces/Fingerprintd-Engine.cppm index fb3bdc6..f97d65e 100644 --- a/interfaces/Fingerprintd-Engine.cppm +++ b/interfaces/Fingerprintd-Engine.cppm @@ -88,14 +88,18 @@ export namespace fingerprintd::engine { // trace. Sending event 7 on every held frame instead feeds the algorithm // near-duplicate images from a single press. // - // Authentication wants event 7, which reaches the matcher unconditionally, - // and ONLY event 7. Event 5 reaches it too (when device+0x10a8 is 1 or 2, - // which it is here): measured on the daemon, the rising-edge frame sent - // both and got two verdicts back from one image -- `rej rej`, `-11 -11`, - // `MATCH MATCH`. Each REPORT_EVENT that runs the matcher costs 250-300 ms, - // so the second one is a third of a second of redundant work on every - // press, on the frame where speed matters most. Enrolment keeps event 5: - // there it is the sample trigger, not a duplicate. + // Authentication does want event 7, which reaches the matcher + // unconditionally; event 5 only reaches it when device+0x10a8 is 1 or 2. + // + // Both are sent on the rising edge, and that is deliberate. On this device + // event 5 ALSO runs the matcher, so the rising frame produces two verdicts + // from one image (`rej rej`, `MATCH MATCH`) at ~300 ms each -- and an + // attempt to drop event 5 as redundant produced a run with zero matches + // across five finger frames, including a held press. Every match ever + // recorded came after an event 5 on the same press; "event 7 alone + // matches" had only ever been observed on held frames that followed one. + // Whether the touch event initialises the press in the trustlet is not + // known. It is not to be removed without a measurement that isolates it. class TouchTracker { public: // Returns the events to report for this frame, in order. @@ -103,7 +107,7 @@ export namespace fingerprintd::engine { std::vector out; bool rising = finger && !prev_; bool falling = !finger && prev_; - if (rising && mode == Mode::Enrol) + if (rising) out.push_back(Event::FingerTouched); if (finger && mode == Mode::Authenticate) out.push_back(Event::ImageReady); diff --git a/tests/Engine/main.cpp b/tests/Engine/main.cpp index 993af56..693407c 100644 --- a/tests/Engine/main.cpp +++ b/tests/Engine/main.cpp @@ -115,14 +115,14 @@ int main() { auto e4 = t.Observe(false, Mode::Enrol); Check(e4.empty(), "enrol: idle reports nothing"); - // Authentication: every frame with a finger reaches the matcher, ONCE. - // Event 5 also runs the matcher here, so sending it on the rising edge - // produced two verdicts from one image and cost ~300 ms extra on the - // frame where speed matters most. + // Authentication: touch then image-ready on the rising edge. Dropping + // the touch event as "redundant" (it does also run the matcher) gave a + // run with zero matches; every recorded match followed an event 5 on + // its press. Not to be removed without a measurement isolating it. TouchTracker a; auto a1 = a.Observe(true, Mode::Authenticate); - Check(a1.size() == 1 && a1[0] == Event::ImageReady, - "auth: rising edge reports image-ready only -- one matcher run, not two"); + Check(a1.size() == 2 && a1[0] == Event::FingerTouched && a1[1] == Event::ImageReady, + "auth: rising edge reports touched then image-ready"); 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);