Revert the two verify-loop changes: zero matches in four runs
Two changes went in together and the next four runs matched nothing, including a held press. They cannot be separated after the fact, so both come out and the loop returns to the shape that has matched every time it was asked to. One is definitely broken. The rising-edge recapture assumed a frame 50 ms after detection would show a settled finger; on a quick tap the finger was already gone, the recapture read the idle floor -- metric 133, still flagged FINGER from the first capture -- and an empty image went to the matcher. A guaranteed miss on exactly the case it was meant to fix. The other is probably wrong. Dropping event 5 as a duplicate rested on observing that event 7 alone produces a verdict -- but every such observation was a held frame that followed an event 5 on the same press. Whether the touch event initialises the press in the trustlet is not known, and five finger frames with no match is not the evidence to remove it on. The process error is the one worth writing down: two variables changed at once, on a live user's finger, with no way to attribute the result. One at a time from here.
This commit is contained in:
parent
9790381e72
commit
06459a8e73
3 changed files with 31 additions and 28 deletions
|
|
@ -1280,20 +1280,19 @@ public:
|
|||
out.frames++;
|
||||
|
||||
std::string note;
|
||||
bool rising = finger && !inPress;
|
||||
if (rising) {
|
||||
// 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++;
|
||||
// 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"; }
|
||||
}
|
||||
for (ta::Event ev : tracker.Observe(finger, en::Mode::Authenticate)) {
|
||||
std::vector<std::byte> evbuf(ta::EventContextSize);
|
||||
ta::BuildEventContext(evbuf, { .event = ev });
|
||||
// A zero-initialised buffer cannot tell "the matcher never
|
||||
|
|
|
|||
|
|
@ -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<Event> 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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue