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