• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "FakeFingerprintEngine.h"
18 #include <regex>
19 #include "Fingerprint.h"
20 
21 #include <android-base/logging.h>
22 #include <android-base/parseint.h>
23 
24 #include <fingerprint.sysprop.h>
25 
26 #include "util/CancellationSignal.h"
27 #include "util/Util.h"
28 
29 using namespace ::android::fingerprint::virt;
30 using ::android::base::ParseInt;
31 
32 namespace aidl::android::hardware::biometrics::fingerprint {
33 
FakeFingerprintEngine()34 FakeFingerprintEngine::FakeFingerprintEngine()
35     : mRandom(std::mt19937::default_seed),
36       mWorkMode(WorkMode::kIdle),
37       isLockoutTimerSupported(true) {}
38 
generateChallengeImpl(ISessionCallback * cb)39 void FakeFingerprintEngine::generateChallengeImpl(ISessionCallback* cb) {
40     BEGIN_OP(0);
41     std::uniform_int_distribution<int64_t> dist;
42     auto challenge = dist(mRandom);
43     Fingerprint::cfg().set<std::int64_t>("challenge", challenge);
44     cb->onChallengeGenerated(challenge);
45 }
46 
revokeChallengeImpl(ISessionCallback * cb,int64_t challenge)47 void FakeFingerprintEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
48     BEGIN_OP(0);
49     Fingerprint::cfg().setopt<OptInt64>("challenge", std::nullopt);
50     cb->onChallengeRevoked(challenge);
51 }
52 
enrollImpl(ISessionCallback * cb,const keymaster::HardwareAuthToken & hat,const std::future<void> & cancel)53 void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
54                                        const keymaster::HardwareAuthToken& hat,
55                                        const std::future<void>& cancel) {
56     BEGIN_OP(0);
57 
58     // Do proper HAT verification in the real implementation.
59     if (hat.mac.empty()) {
60         LOG(ERROR) << "Fail: hat";
61         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
62         return;
63     }
64 
65     waitForFingerDown(cb, cancel);
66 
67     updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
68 }
69 
authenticateImpl(ISessionCallback * cb,int64_t operationId,const std::future<void> & cancel)70 void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t operationId,
71                                              const std::future<void>& cancel) {
72     BEGIN_OP(0);
73 
74     waitForFingerDown(cb, cancel);
75 
76     updateContext(WorkMode::kAuthenticate, cb, const_cast<std::future<void>&>(cancel), operationId,
77                   keymaster::HardwareAuthToken());
78 }
79 
detectInteractionImpl(ISessionCallback * cb,const std::future<void> & cancel)80 void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
81                                                   const std::future<void>& cancel) {
82     BEGIN_OP(0);
83 
84     auto detectInteractionSupported = Fingerprint::cfg().get<bool>("detect_interaction");
85     if (!detectInteractionSupported) {
86         LOG(ERROR) << "Detect interaction is not supported";
87         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
88         return;
89     }
90 
91     waitForFingerDown(cb, cancel);
92 
93     updateContext(WorkMode::kDetectInteract, cb, const_cast<std::future<void>&>(cancel), 0,
94                   keymaster::HardwareAuthToken());
95 }
96 
updateContext(WorkMode mode,ISessionCallback * cb,std::future<void> & cancel,int64_t operationId,const keymaster::HardwareAuthToken & hat)97 void FakeFingerprintEngine::updateContext(WorkMode mode, ISessionCallback* cb,
98                                           std::future<void>& cancel, int64_t operationId,
99                                           const keymaster::HardwareAuthToken& hat) {
100     mCancel = std::move(cancel);
101     mWorkMode = mode;
102     mCb = cb;
103     mOperationId = operationId;
104     mHat = hat;
105 }
106 
fingerDownAction()107 void FakeFingerprintEngine::fingerDownAction() {
108     bool isTerminal = false;
109     LOG(INFO) << __func__;
110     switch (mWorkMode) {
111         case WorkMode::kAuthenticate:
112             isTerminal = onAuthenticateFingerDown(mCb, mOperationId, mCancel);
113             break;
114         case WorkMode::kEnroll:
115             isTerminal = onEnrollFingerDown(mCb, mHat, mCancel);
116             break;
117         case WorkMode::kDetectInteract:
118             isTerminal = onDetectInteractFingerDown(mCb, mCancel);
119             break;
120         default:
121             LOG(WARNING) << "unexpected mode: on fingerDownAction(), " << (int)mWorkMode;
122             break;
123     }
124 
125     if (isTerminal) {
126         mWorkMode = WorkMode::kIdle;
127     }
128 }
129 
onEnrollFingerDown(ISessionCallback * cb,const keymaster::HardwareAuthToken &,const std::future<void> & cancel)130 bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb,
131                                                const keymaster::HardwareAuthToken&,
132                                                const std::future<void>& cancel) {
133     BEGIN_OP(getLatency(Fingerprint::cfg().getopt<OptIntVec>("operation_enroll_latency")));
134 
135     // Force error-out
136     auto err = Fingerprint::cfg().get<std::int32_t>("operation_enroll_error");
137     if (err != 0) {
138         LOG(ERROR) << "Fail: operation_enroll_error";
139         auto ec = convertError(err);
140         cb->onError(ec.first, ec.second);
141         return true;
142     }
143 
144     // Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
145     auto nextEnroll = Fingerprint::cfg().get<std::string>("next_enrollment");
146     auto parts = Util::split(nextEnroll, ":");
147     if (parts.size() != 3) {
148         LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
149         cb->onError(Error::VENDOR, 0 /* vendorError */);
150         return true;
151     }
152     auto enrollmentId = std::stoi(parts[0]);
153     auto progress = Util::parseEnrollmentCapture(parts[1]);
154     for (size_t i = 0; i < progress.size(); i += 2) {
155         auto left = (progress.size() - i) / 2 - 1;
156         auto duration = progress[i][0];
157         auto acquired = progress[i + 1];
158         auto N = acquired.size();
159 
160         for (int j = 0; j < N; j++) {
161             SLEEP_MS(duration / N);
162 
163             if (shouldCancel(cancel)) {
164                 LOG(ERROR) << "Fail: cancel";
165                 cb->onError(Error::CANCELED, 0 /* vendorCode */);
166                 return true;
167             }
168             auto ac = convertAcquiredInfo(acquired[j]);
169             cb->onAcquired(ac.first, ac.second);
170         }
171 
172         if (left == 0 && !IS_TRUE(parts[2])) {  // end and failed
173             LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
174             Fingerprint::cfg().set<std::string>("next_enrollment", "");
175             cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
176         } else {  // progress and update props if last time
177             LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
178             if (left == 0) {
179                 auto enrollments = Fingerprint::cfg().getopt<OptIntVec>("enrollments");
180                 enrollments.emplace_back(enrollmentId);
181                 Fingerprint::cfg().setopt<OptIntVec>("enrollments", enrollments);
182                 Fingerprint::cfg().setopt<OptString>("next_enrollment", std::nullopt);
183                 // change authenticatorId after new enrollment
184                 auto id = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
185                 auto newId = id + 1;
186                 Fingerprint::cfg().set<std::int64_t>("authenticator_id", newId);
187                 LOG(INFO) << "Enrolled: " << enrollmentId;
188             }
189             cb->onEnrollmentProgress(enrollmentId, left);
190         }
191     }
192 
193     return true;
194 }
195 
onAuthenticateFingerDown(ISessionCallback * cb,int64_t,const std::future<void> & cancel)196 bool FakeFingerprintEngine::onAuthenticateFingerDown(ISessionCallback* cb,
197                                                      int64_t /* operationId */,
198                                                      const std::future<void>& cancel) {
199     BEGIN_OP(getLatency(Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_latency")));
200 
201     int64_t now = Util::getSystemNanoTime();
202     int64_t duration = Fingerprint::cfg().get<std::int32_t>("operation_authenticate_duration");
203     auto acquired = Fingerprint::cfg().get<std::string>("operation_authenticate_acquired");
204     auto acquiredInfos = Util::parseIntSequence(acquired);
205     int N = acquiredInfos.size();
206 
207     if (N == 0) {
208         LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
209         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
210         return true;
211     }
212 
213     // got lockout?
214     if (checkSensorLockout(cb)) {
215         return FakeLockoutTracker::LockoutMode::kPermanent == mLockoutTracker.getMode();
216     }
217 
218     int i = 0;
219     do {
220         if (Fingerprint::cfg().get<bool>("operation_authenticate_fails")) {
221             LOG(ERROR) << "Fail: operation_authenticate_fails";
222             mLockoutTracker.addFailedAttempt();
223             cb->onAuthenticationFailed();
224             return false;
225         }
226 
227         auto err = Fingerprint::cfg().get<std::int32_t>("operation_authenticate_error");
228         if (err != 0) {
229             LOG(ERROR) << "Fail: operation_authenticate_error";
230             auto ec = convertError(err);
231             cb->onError(ec.first, ec.second);
232             return true; /* simply terminating current operation for any user inserted error,
233                             revisit if tests need*/
234         }
235 
236         if (Fingerprint::cfg().get<bool>("lockout")) {
237             LOG(ERROR) << "Fail: lockout";
238             cb->onLockoutPermanent();
239             cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
240             return true;
241         }
242 
243         if (shouldCancel(cancel)) {
244             LOG(ERROR) << "Fail: cancel";
245             cb->onError(Error::CANCELED, 0 /* vendorCode */);
246             return true;
247         }
248 
249         if (i < N) {
250             auto ac = convertAcquiredInfo(acquiredInfos[i]);
251             cb->onAcquired(ac.first, ac.second);
252             i++;
253         }
254 
255         SLEEP_MS(duration / N);
256     } while (!Util::hasElapsed(now, duration));
257 
258     auto id = Fingerprint::cfg().get<std::int32_t>("enrollment_hit");
259     auto enrolls = Fingerprint::cfg().getopt<OptIntVec>("enrollments");
260     auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
261     if (id > 0 && isEnrolled) {
262         cb->onAuthenticationSucceeded(id, {} /* hat */);
263         mLockoutTracker.reset();
264         return true;
265     } else {
266         LOG(ERROR) << "Fail: fingerprint not enrolled";
267         cb->onAuthenticationFailed();
268         mLockoutTracker.addFailedAttempt();
269         checkSensorLockout(cb);
270         return false;
271     }
272 }
273 
onDetectInteractFingerDown(ISessionCallback * cb,const std::future<void> & cancel)274 bool FakeFingerprintEngine::onDetectInteractFingerDown(ISessionCallback* cb,
275                                                        const std::future<void>& cancel) {
276     BEGIN_OP(getLatency(
277             Fingerprint::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
278 
279     int32_t duration =
280             Fingerprint::cfg().get<std::int32_t>("operation_detect_interaction_duration");
281 
282     auto acquired = Fingerprint::cfg().get<std::string>("operation_detect_interaction_acquired");
283     auto acquiredInfos = Util::parseIntSequence(acquired);
284     int N = acquiredInfos.size();
285     int64_t now = Util::getSystemNanoTime();
286 
287     if (N == 0) {
288         LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired;
289         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
290         return true;
291     }
292 
293     int i = 0;
294     do {
295         auto err = Fingerprint::cfg().get<std::int32_t>("operation_detect_interaction_error");
296         if (err != 0) {
297             LOG(ERROR) << "Fail: operation_detect_interaction_error";
298             auto ec = convertError(err);
299             cb->onError(ec.first, ec.second);
300             return true;
301         }
302 
303         if (shouldCancel(cancel)) {
304             LOG(ERROR) << "Fail: cancel";
305             cb->onError(Error::CANCELED, 0 /* vendorCode */);
306             return true;
307         }
308 
309         if (i < N) {
310             auto ac = convertAcquiredInfo(acquiredInfos[i]);
311             cb->onAcquired(ac.first, ac.second);
312             i++;
313         }
314         SLEEP_MS(duration / N);
315     } while (!Util::hasElapsed(now, duration));
316 
317     cb->onInteractionDetected();
318 
319     return true;
320 }
321 
enumerateEnrollmentsImpl(ISessionCallback * cb)322 void FakeFingerprintEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
323     BEGIN_OP(0);
324 
325     std::vector<int32_t> ids;
326     for (auto& enrollment : Fingerprint::cfg().getopt<OptIntVec>("enrollments")) {
327         auto id = enrollment.value_or(0);
328         if (id > 0) {
329             ids.push_back(id);
330         }
331     }
332 
333     cb->onEnrollmentsEnumerated(ids);
334 }
335 
removeEnrollmentsImpl(ISessionCallback * cb,const std::vector<int32_t> & enrollmentIds)336 void FakeFingerprintEngine::removeEnrollmentsImpl(ISessionCallback* cb,
337                                                   const std::vector<int32_t>& enrollmentIds) {
338     BEGIN_OP(0);
339 
340     std::vector<std::optional<int32_t>> newEnrollments;
341     std::vector<int32_t> removed;
342     for (auto& enrollment : Fingerprint::cfg().getopt<OptIntVec>("enrollments")) {
343         auto id = enrollment.value_or(0);
344         if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) != enrollmentIds.end()) {
345             removed.push_back(id);
346         } else if (id > 0) {
347             newEnrollments.emplace_back(id);
348         }
349     }
350     Fingerprint::cfg().setopt<OptIntVec>("enrollments", newEnrollments);
351 
352     cb->onEnrollmentsRemoved(enrollmentIds);
353 }
354 
getAuthenticatorIdImpl(ISessionCallback * cb)355 void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
356     BEGIN_OP(0);
357     int64_t authenticatorId;
358     if (Fingerprint::cfg().getopt<OptIntVec>("enrollments").size() == 0) {
359         authenticatorId = 0;
360     } else {
361         authenticatorId = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
362         if (authenticatorId == 0) authenticatorId = 1;
363     }
364     cb->onAuthenticatorIdRetrieved(authenticatorId);
365 }
366 
invalidateAuthenticatorIdImpl(ISessionCallback * cb)367 void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
368     BEGIN_OP(0);
369     int64_t newId;
370     if (Fingerprint::cfg().getopt<OptIntVec>("enrollments").size() == 0) {
371         newId = 0;
372     } else {
373         auto id = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
374         newId = id + 1;
375     }
376     Fingerprint::cfg().set<std::int64_t>("authenticator_id", newId);
377     cb->onAuthenticatorIdInvalidated(newId);
378 }
379 
resetLockoutImpl(ISessionCallback * cb,const keymaster::HardwareAuthToken & hat)380 void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
381                                              const keymaster::HardwareAuthToken& hat) {
382     BEGIN_OP(0);
383     if (hat.mac.empty()) {
384         LOG(ERROR) << "Fail: hat in resetLockout()";
385         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
386         return;
387     }
388     clearLockout(cb);
389     if (isLockoutTimerStarted) isLockoutTimerAborted = true;
390 }
391 
clearLockout(ISessionCallback * cb,bool dueToTimeout)392 void FakeFingerprintEngine::clearLockout(ISessionCallback* cb, bool dueToTimeout) {
393     Fingerprint::cfg().set<bool>("lockout", false);
394     cb->onLockoutCleared();
395     mLockoutTracker.reset(dueToTimeout);
396 }
397 
onPointerDownImpl(int32_t,int32_t,int32_t,float,float)398 ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
399                                                             int32_t /*y*/, float /*minor*/,
400                                                             float /*major*/) {
401     BEGIN_OP(0);
402     fingerDownAction();
403     return ndk::ScopedAStatus::ok();
404 }
405 
onPointerUpImpl(int32_t)406 ndk::ScopedAStatus FakeFingerprintEngine::onPointerUpImpl(int32_t /*pointerId*/) {
407     BEGIN_OP(0);
408     mFingerIsDown = false;
409     return ndk::ScopedAStatus::ok();
410 }
411 
onUiReadyImpl()412 ndk::ScopedAStatus FakeFingerprintEngine::onUiReadyImpl() {
413     BEGIN_OP(0);
414     return ndk::ScopedAStatus::ok();
415 }
416 
getSensorLocationConfig(std::vector<SensorLocation> & out)417 bool FakeFingerprintEngine::getSensorLocationConfig(std::vector<SensorLocation>& out) {
418     auto locStr = Fingerprint::cfg().get<std::string>("sensor_location");
419     auto isValidStr = false;
420 
421     // sensor_location format: x:y:r:d,x:y:r:d,...
422     //   x: x location in pixel, y: y location in pixel, r: radus in pixel, d:display in string
423     auto locations = Util::split(locStr, ",");
424     for (int i = 0; i < locations.size(); i++) {
425         auto loc = locations[i];
426 
427         // expect loc in the format: x:y:r  or x:y:d:r
428         auto dim = Util::split(loc, ":");
429 
430         if (dim.size() < 3) {
431             if (!loc.empty()) LOG(WARNING) << "Invalid sensor location input (x:y:radius):" + loc;
432             out.clear();
433             return false;
434         } else {
435             int32_t x, y, r;
436             std::string d = "";
437             if (dim.size() >= 3) {
438                 isValidStr = ParseInt(dim[0], &x) && ParseInt(dim[1], &y) && ParseInt(dim[2], &r);
439             }
440             if (dim.size() >= 4) {
441                 for (int i = 3; i < dim.size(); i++) {
442                     if (i > 3) d += ':';
443                     d += dim[i];
444                 }
445             }
446             if (isValidStr) {
447                 out.push_back(SensorLocation{.sensorLocationX = x,
448                                              .sensorLocationY = y,
449                                              .sensorRadius = r,
450                                              .display = d});
451             }
452         }
453     }
454 
455     LOG(INFO) << "getSensorLocationConfig: isValidStr=" << isValidStr << " locStr=" << locStr;
456     if (isValidStr) {
457         for (auto loc : out) {
458             LOG(INFO) << loc.toString();
459         }
460     } else {
461         out.clear();
462     }
463 
464     return isValidStr;
465 }
466 
getSensorLocation(std::vector<SensorLocation> & location)467 void FakeFingerprintEngine::getSensorLocation(std::vector<SensorLocation>& location) {
468     if (!getSensorLocationConfig(location)) {
469         getDefaultSensorLocation(location);
470     }
471 }
472 
convertAcquiredInfo(int32_t code)473 std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
474     std::pair<AcquiredInfo, int32_t> res;
475     if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
476         res.first = AcquiredInfo::VENDOR;
477         res.second = code - FINGERPRINT_ACQUIRED_VENDOR_BASE;
478     } else {
479         res.first = (AcquiredInfo)code;
480         res.second = 0;
481     }
482     return res;
483 }
484 
convertError(int32_t code)485 std::pair<Error, int32_t> FakeFingerprintEngine::convertError(int32_t code) {
486     std::pair<Error, int32_t> res;
487     if (code > FINGERPRINT_ERROR_VENDOR_BASE) {
488         res.first = Error::VENDOR;
489         res.second = code - FINGERPRINT_ERROR_VENDOR_BASE;
490     } else {
491         res.first = (Error)code;
492         res.second = 0;
493     }
494     return res;
495 }
496 
getLatency(const std::vector<std::optional<std::int32_t>> & latencyIn)497 int32_t FakeFingerprintEngine::getLatency(
498         const std::vector<std::optional<std::int32_t>>& latencyIn) {
499     int32_t res = DEFAULT_LATENCY;
500 
501     std::vector<int32_t> latency;
502     for (auto x : latencyIn)
503         if (x.has_value()) latency.push_back(*x);
504 
505     switch (latency.size()) {
506         case 0:
507             break;
508         case 1:
509             res = latency[0];
510             break;
511         case 2:
512             res = getRandomInRange(latency[0], latency[1]);
513             break;
514         default:
515             LOG(ERROR) << "ERROR: unexpected input of size " << latency.size();
516             break;
517     }
518 
519     return res;
520 }
521 
getRandomInRange(int32_t bound1,int32_t bound2)522 int32_t FakeFingerprintEngine::getRandomInRange(int32_t bound1, int32_t bound2) {
523     std::uniform_int_distribution<int32_t> dist(std::min(bound1, bound2), std::max(bound1, bound2));
524     return dist(mRandom);
525 }
526 
checkSensorLockout(ISessionCallback * cb)527 bool FakeFingerprintEngine::checkSensorLockout(ISessionCallback* cb) {
528     FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
529     if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
530         LOG(ERROR) << "Fail: lockout permanent";
531         cb->onLockoutPermanent();
532         isLockoutTimerAborted = true;
533         return true;
534     } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
535         int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
536         LOG(ERROR) << "Fail: lockout timed " << timeLeft;
537         cb->onLockoutTimed(timeLeft);
538         if (isLockoutTimerSupported && !isLockoutTimerStarted) startLockoutTimer(timeLeft, cb);
539         return true;
540     }
541     return false;
542 }
543 
startLockoutTimer(int64_t timeout,ISessionCallback * cb)544 void FakeFingerprintEngine::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
545     BEGIN_OP(0);
546     std::function<void(ISessionCallback*)> action =
547             std::bind(&FakeFingerprintEngine::lockoutTimerExpired, this, std::placeholders::_1);
548     std::thread([timeout, action, cb]() {
549         std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
550         action(cb);
551     }).detach();
552 
553     isLockoutTimerStarted = true;
554 }
lockoutTimerExpired(ISessionCallback * cb)555 void FakeFingerprintEngine::lockoutTimerExpired(ISessionCallback* cb) {
556     BEGIN_OP(0);
557     if (!isLockoutTimerAborted) {
558         clearLockout(cb, true);
559     }
560     isLockoutTimerStarted = false;
561     isLockoutTimerAborted = false;
562 }
563 
waitForFingerDown(ISessionCallback * cb,const std::future<void> & cancel)564 void FakeFingerprintEngine::waitForFingerDown(ISessionCallback* cb,
565                                               const std::future<void>& cancel) {
566     if (mFingerIsDown) {
567         LOG(WARNING) << "waitForFingerDown: mFingerIsDown==true already!";
568     }
569 
570     while (!mFingerIsDown) {
571         if (shouldCancel(cancel)) {
572             LOG(ERROR) << "waitForFingerDown, Fail: cancel";
573             cb->onError(Error::CANCELED, 0 /* vendorCode */);
574             return;
575         }
576         SLEEP_MS(10);
577     }
578 }
579 
580 }  // namespace aidl::android::hardware::biometrics::fingerprint
581