diff --git a/implementations/main.cpp b/implementations/main.cpp index 607e764..189967f 100644 --- a/implementations/main.cpp +++ b/implementations/main.cpp @@ -81,6 +81,15 @@ std::string g_logDir = "/var/log/fingerprintd"; std::string g_stateDir = "/var/lib/fingerprintd"; int g_rescan = -1; // -1 = leave the config's value alone +// What a press that ends with no terminal verdict means. At the stock rescan +// budget a wrong finger answers "not identified yet" on every frame and never +// yields a terminal frame, so its press is undecided at lift -- and the only +// way a client ever hears verify-no-match is to treat that as one. The cost is +// on the correct finger: a press that ran out of frames before the matcher +// reached a verdict is also reported as no-match. Under rescan=0 this cannot +// arise (every frame is terminal), so the knob only matters with a budget. +bool g_undecidedIsNoMatch = false; + // The namespace key the trustlet hashes into the SFS group's directory name. // It defaults to Android's because that is what this device's existing store // was written under. It does NOT isolate anything -- SET_ACTIVE_GROUP's path @@ -1297,12 +1306,13 @@ public: inPress = false; if (pressMatched) { out.decided = true; out.matched = true; out.fid = pressFid; - } else if (pressRejected) { + } else if (pressRejected || (g_undecidedIsNoMatch && pressFrames > 0)) { out.decided = true; out.matched = false; } std::println(" press {}: {} frames, {} rescans -> {}", out.presses, pressFrames, rescans, pressMatched ? std::format("MATCH fid={}", pressFid) - : pressRejected ? "NO MATCH" : "undecided"); + : pressRejected ? "NO MATCH" + : out.decided ? "NO MATCH (undecided at lift)" : "undecided"); } } if (finger) pressFrames++; @@ -2060,6 +2070,7 @@ int main(int argc, char** argv) { if (a == "--cal-save") { doCalSave = true; probe = true; g_verbose = true; } if (a.starts_with("--frames=")) frames = std::stoi(std::string(a.substr(9))); if (a.starts_with("--frame-gap=")) g_frameGapMs = std::stoi(std::string(a.substr(12))); + if (a == "--undecided=nomatch") g_undecidedIsNoMatch = true; if (a.starts_with("--log-dir=")) g_logDir = a.substr(10); if (a.starts_with("--state-dir=")) g_stateDir = a.substr(12); if (a.starts_with("--rescan=")) g_rescan = std::stoi(std::string(a.substr(9)));