blob: 651c9dc352f73da33e6da444347e654ee8bfb8f1 [file] [log] [blame]
Joe Bolingerde94aa02021-12-09 17:00:32 -08001/*
2 * Copyright (C) 2021 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"
Jeff Pu63f33c72022-07-28 16:06:23 -040018#include "Fingerprint.h"
Joe Bolingerde94aa02021-12-09 17:00:32 -080019
Joe Bolingerde94aa02021-12-09 17:00:32 -080020#include <android-base/logging.h>
Jeff Pu63f33c72022-07-28 16:06:23 -040021#include <android-base/parseint.h>
Joshua McCloskeyc8c0bad2022-05-10 05:17:44 +000022
23#include <fingerprint.sysprop.h>
Joe Bolingerde94aa02021-12-09 17:00:32 -080024
Joshua McCloskeyc8c0bad2022-05-10 05:17:44 +000025#include "util/CancellationSignal.h"
Joshua McCloskeydb009a52022-05-10 05:18:20 +000026#include "util/Util.h"
Joe Bolingerde94aa02021-12-09 17:00:32 -080027
28using namespace ::android::fingerprint::virt;
Jeff Pu63f33c72022-07-28 16:06:23 -040029using ::android::base::ParseInt;
Joe Bolingerde94aa02021-12-09 17:00:32 -080030
31namespace aidl::android::hardware::biometrics::fingerprint {
32
33void FakeFingerprintEngine::generateChallengeImpl(ISessionCallback* cb) {
34 BEGIN_OP(0);
35 std::uniform_int_distribution<int64_t> dist;
36 auto challenge = dist(mRandom);
37 FingerprintHalProperties::challenge(challenge);
38 cb->onChallengeGenerated(challenge);
39}
40
41void FakeFingerprintEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
42 BEGIN_OP(0);
43 FingerprintHalProperties::challenge({});
44 cb->onChallengeRevoked(challenge);
45}
46
47void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
48 const keymaster::HardwareAuthToken& hat,
49 const std::future<void>& cancel) {
50 BEGIN_OP(FingerprintHalProperties::operation_enroll_latency().value_or(DEFAULT_LATENCY));
51
52 // Do proper HAT verification in the real implementation.
53 if (hat.mac.empty()) {
54 LOG(ERROR) << "Fail: hat";
55 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
56 return;
57 }
58
Jeff Pu343ca942022-09-14 15:56:30 -040059 // Force error-out
60 auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
61 if (err != 0) {
62 LOG(ERROR) << "Fail: operation_enroll_error";
63 auto ec = convertError(err);
64 cb->onError(ec.first, ec.second);
Joe Bolingerde94aa02021-12-09 17:00:32 -080065 return;
66 }
67
Jeff Pu343ca942022-09-14 15:56:30 -040068 // Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
Joe Bolingerde94aa02021-12-09 17:00:32 -080069 auto nextEnroll = FingerprintHalProperties::next_enrollment().value_or("");
Joshua McCloskeydb009a52022-05-10 05:18:20 +000070 auto parts = Util::split(nextEnroll, ":");
Joe Bolingerde94aa02021-12-09 17:00:32 -080071 if (parts.size() != 3) {
Jeff Pu343ca942022-09-14 15:56:30 -040072 LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
Joe Bolingerde94aa02021-12-09 17:00:32 -080073 cb->onError(Error::VENDOR, 0 /* vendorError */);
74 return;
75 }
76 auto enrollmentId = std::stoi(parts[0]);
Jeff Pu343ca942022-09-14 15:56:30 -040077 auto progress = parseEnrollmentCapture(parts[1]);
78 for (size_t i = 0; i < progress.size(); i += 2) {
79 auto left = (progress.size() - i) / 2 - 1;
80 auto duration = progress[i][0];
81 auto acquired = progress[i + 1];
82 auto N = acquired.size();
Joe Bolingerde94aa02021-12-09 17:00:32 -080083
Jeff Pu343ca942022-09-14 15:56:30 -040084 for (int j = 0; j < N; j++) {
85 SLEEP_MS(duration / N);
86
87 if (shouldCancel(cancel)) {
88 LOG(ERROR) << "Fail: cancel";
89 cb->onError(Error::CANCELED, 0 /* vendorCode */);
90 return;
91 }
92 auto ac = convertAcquiredInfo(acquired[j]);
93 cb->onAcquired(ac.first, ac.second);
Joe Bolingerde94aa02021-12-09 17:00:32 -080094 }
95
Joe Bolingerde94aa02021-12-09 17:00:32 -080096 if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
97 LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
98 FingerprintHalProperties::next_enrollment({});
99 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
100 } else { // progress and update props if last time
Jeff Pu343ca942022-09-14 15:56:30 -0400101 LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
Joe Bolingerde94aa02021-12-09 17:00:32 -0800102 if (left == 0) {
103 auto enrollments = FingerprintHalProperties::enrollments();
104 enrollments.emplace_back(enrollmentId);
105 FingerprintHalProperties::enrollments(enrollments);
106 FingerprintHalProperties::next_enrollment({});
Jeff Pu343ca942022-09-14 15:56:30 -0400107 // change authenticatorId after new enrollment
108 auto id = FingerprintHalProperties::authenticator_id().value_or(0);
109 auto newId = id + 1;
110 FingerprintHalProperties::authenticator_id(newId);
Joe Bolingerde94aa02021-12-09 17:00:32 -0800111 LOG(INFO) << "Enrolled: " << enrollmentId;
112 }
113 cb->onEnrollmentProgress(enrollmentId, left);
114 }
115 }
116}
117
118void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */,
119 const std::future<void>& cancel) {
120 BEGIN_OP(FingerprintHalProperties::operation_authenticate_latency().value_or(DEFAULT_LATENCY));
121
Jeff Pu343ca942022-09-14 15:56:30 -0400122 int64_t now = Util::getSystemNanoTime();
123 int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
124 auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
125 auto acquiredInfos = parseIntSequence(acquired);
126 int N = acquiredInfos.size();
127
128 if (N == 0) {
129 LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
130 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
131 return;
132 }
133
134 int i = 0;
Joe Bolingerde94aa02021-12-09 17:00:32 -0800135 do {
136 if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
137 LOG(ERROR) << "Fail: operation_authenticate_fails";
Jeff Pu343ca942022-09-14 15:56:30 -0400138 cb->onAuthenticationFailed();
139 return;
140 }
141
142 auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0);
143 if (err != 0) {
144 LOG(ERROR) << "Fail: operation_authenticate_error";
145 auto ec = convertError(err);
146 cb->onError(ec.first, ec.second);
Joe Bolingerde94aa02021-12-09 17:00:32 -0800147 return;
148 }
149
150 if (FingerprintHalProperties::lockout().value_or(false)) {
151 LOG(ERROR) << "Fail: lockout";
152 cb->onLockoutPermanent();
153 cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
154 return;
155 }
156
157 if (shouldCancel(cancel)) {
158 LOG(ERROR) << "Fail: cancel";
159 cb->onError(Error::CANCELED, 0 /* vendorCode */);
160 return;
161 }
162
Jeff Pu343ca942022-09-14 15:56:30 -0400163 if (i < N) {
164 auto ac = convertAcquiredInfo(acquiredInfos[i]);
165 cb->onAcquired(ac.first, ac.second);
166 i++;
Joe Bolingerde94aa02021-12-09 17:00:32 -0800167 }
168
Jeff Pu343ca942022-09-14 15:56:30 -0400169 SLEEP_MS(duration / N);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000170 } while (!Util::hasElapsed(now, duration));
Joe Bolingerde94aa02021-12-09 17:00:32 -0800171
Jeff Pu343ca942022-09-14 15:56:30 -0400172 auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
173 auto enrolls = FingerprintHalProperties::enrollments();
174 auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
175 if (id > 0 && isEnrolled) {
176 cb->onAuthenticationSucceeded(id, {} /* hat */);
177 return;
178 } else {
179 LOG(ERROR) << "Fail: fingerprint not enrolled";
180 cb->onAuthenticationFailed();
181 }
Joe Bolingerde94aa02021-12-09 17:00:32 -0800182}
183
184void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
185 const std::future<void>& cancel) {
186 BEGIN_OP(FingerprintHalProperties::operation_detect_interaction_latency().value_or(
187 DEFAULT_LATENCY));
188
Jeff Pu343ca942022-09-14 15:56:30 -0400189 int64_t duration =
190 FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
191 auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
192 auto acquiredInfos = parseIntSequence(acquired);
193 int N = acquiredInfos.size();
194 int64_t now = Util::getSystemNanoTime();
195
196 if (N == 0) {
197 LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired;
198 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
Joe Bolingerde94aa02021-12-09 17:00:32 -0800199 return;
200 }
201
Jeff Pu343ca942022-09-14 15:56:30 -0400202 int i = 0;
203 do {
204 auto err = FingerprintHalProperties::operation_detect_interaction_error().value_or(0);
205 if (err != 0) {
206 LOG(ERROR) << "Fail: operation_detect_interaction_error";
207 auto ec = convertError(err);
208 cb->onError(ec.first, ec.second);
209 return;
210 }
211
212 if (shouldCancel(cancel)) {
213 LOG(ERROR) << "Fail: cancel";
214 cb->onError(Error::CANCELED, 0 /* vendorCode */);
215 return;
216 }
217
218 if (i < N) {
219 auto ac = convertAcquiredInfo(acquiredInfos[i]);
220 cb->onAcquired(ac.first, ac.second);
221 i++;
222 }
223 SLEEP_MS(duration / N);
224 } while (!Util::hasElapsed(now, duration));
Joe Bolingerde94aa02021-12-09 17:00:32 -0800225
226 auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
227 auto enrolls = FingerprintHalProperties::enrollments();
228 auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
229 if (id <= 0 || !isEnrolled) {
230 LOG(ERROR) << "Fail: not enrolled";
231 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
232 return;
233 }
234
235 cb->onInteractionDetected();
236}
237
238void FakeFingerprintEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
239 BEGIN_OP(0);
240
241 std::vector<int32_t> ids;
Jeff Pu63f33c72022-07-28 16:06:23 -0400242 // There are some enrollment sync issue with framework, which results in
243 // a single template removal during the very firt sync command after reboot.
244 // This is a workaround for now. TODO(b/243129174)
245 ids.push_back(-1);
246
Joe Bolingerde94aa02021-12-09 17:00:32 -0800247 for (auto& enrollment : FingerprintHalProperties::enrollments()) {
248 auto id = enrollment.value_or(0);
249 if (id > 0) {
250 ids.push_back(id);
251 }
252 }
253
254 cb->onEnrollmentsEnumerated(ids);
255}
256
257void FakeFingerprintEngine::removeEnrollmentsImpl(ISessionCallback* cb,
258 const std::vector<int32_t>& enrollmentIds) {
259 BEGIN_OP(0);
260
261 std::vector<std::optional<int32_t>> newEnrollments;
262 std::vector<int32_t> removed;
263 for (auto& enrollment : FingerprintHalProperties::enrollments()) {
264 auto id = enrollment.value_or(0);
265 if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) != enrollmentIds.end()) {
266 removed.push_back(id);
267 } else if (id > 0) {
268 newEnrollments.emplace_back(id);
269 }
270 }
271 FingerprintHalProperties::enrollments(newEnrollments);
272
273 cb->onEnrollmentsRemoved(enrollmentIds);
274}
275
276void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
277 BEGIN_OP(0);
Jeff Pu343ca942022-09-14 15:56:30 -0400278 int64_t authenticatorId;
279 if (FingerprintHalProperties::enrollments().size() == 0) {
280 authenticatorId = 0;
281 } else {
282 authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
283 if (authenticatorId == 0) authenticatorId = 1;
Jeff Pu63f33c72022-07-28 16:06:23 -0400284 }
285 cb->onAuthenticatorIdRetrieved(authenticatorId);
Joe Bolingerde94aa02021-12-09 17:00:32 -0800286}
287
288void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
289 BEGIN_OP(0);
Jeff Pu343ca942022-09-14 15:56:30 -0400290 int64_t newId;
291 if (FingerprintHalProperties::enrollments().size() == 0) {
292 newId = 0;
293 } else {
294 auto id = FingerprintHalProperties::authenticator_id().value_or(0);
295 newId = id + 1;
296 }
Joe Bolingerde94aa02021-12-09 17:00:32 -0800297 FingerprintHalProperties::authenticator_id(newId);
298 cb->onAuthenticatorIdInvalidated(newId);
299}
300
301void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
Jeff Pu343ca942022-09-14 15:56:30 -0400302 const keymaster::HardwareAuthToken& hat) {
Joe Bolingerde94aa02021-12-09 17:00:32 -0800303 BEGIN_OP(0);
Jeff Pu343ca942022-09-14 15:56:30 -0400304 if (hat.mac.empty()) {
305 LOG(ERROR) << "Fail: hat in resetLockout()";
306 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
307 return;
308 }
Joe Bolingerde94aa02021-12-09 17:00:32 -0800309 FingerprintHalProperties::lockout(false);
310 cb->onLockoutCleared();
311}
312
Jeff Pu63f33c72022-07-28 16:06:23 -0400313ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
314 int32_t /*y*/, float /*minor*/,
315 float /*major*/) {
316 BEGIN_OP(0);
317 return ndk::ScopedAStatus::ok();
318}
319
320ndk::ScopedAStatus FakeFingerprintEngine::onPointerUpImpl(int32_t /*pointerId*/) {
321 BEGIN_OP(0);
322 return ndk::ScopedAStatus::ok();
323}
324
325ndk::ScopedAStatus FakeFingerprintEngine::onUiReadyImpl() {
326 BEGIN_OP(0);
327 return ndk::ScopedAStatus::ok();
328}
329
330bool FakeFingerprintEngine::getSensorLocationConfig(SensorLocation& out) {
331 auto loc = FingerprintHalProperties::sensor_location().value_or("");
332 auto isValidStr = false;
333 auto dim = Util::split(loc, ":");
334
335 if (dim.size() < 3 or dim.size() > 4) {
336 if (!loc.empty()) LOG(WARNING) << "Invalid sensor location input (x:y:radius):" + loc;
337 return false;
338 } else {
339 int32_t x, y, r;
340 std::string d = "";
341 if (dim.size() >= 3) {
342 isValidStr = ParseInt(dim[0], &x) && ParseInt(dim[1], &y) && ParseInt(dim[2], &r);
343 }
344 if (dim.size() >= 4) {
345 d = dim[3];
346 }
347 if (isValidStr) out = {0, x, y, r, d};
348
349 return isValidStr;
350 }
351}
352SensorLocation FakeFingerprintEngine::getSensorLocation() {
353 SensorLocation location;
354
355 if (getSensorLocationConfig(location)) {
356 return location;
357 } else {
358 return defaultSensorLocation();
359 }
360}
361
362SensorLocation FakeFingerprintEngine::defaultSensorLocation() {
363 return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */,
364 0 /* sensorRadius */, "" /* display */};
365}
Jeff Pu343ca942022-09-14 15:56:30 -0400366
367std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
368 const std::string& sep) {
369 std::vector<std::string> seqs = Util::split(str, sep);
370 std::vector<int32_t> res;
371
372 for (const auto& seq : seqs) {
373 int32_t val;
374 if (ParseInt(seq, &val)) {
375 res.push_back(val);
376 } else {
377 LOG(WARNING) << "Invalid int sequence:" + str;
378 res.clear();
379 break;
380 }
381 }
382
383 return res;
384}
385
386std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
387 const std::string& str) {
388 std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
389 std::vector<std::vector<int32_t>> res;
390 int i = 0, N = str.length();
391 std::size_t found = 0;
392 bool aborted = true;
393
394 while (found != std::string::npos) {
395 std::string durationStr, acquiredStr;
396 found = str.find_first_of("-,", i);
397 if (found == std::string::npos) {
398 if (N - i < 1) break;
399 durationStr = str.substr(i, N - i);
400 } else {
401 durationStr = str.substr(i, found - i);
402 if (str[found] == '-') {
403 found = str.find_first_of('[', found + 1);
404 if (found == std::string::npos) break;
405 i = found + 1;
406 found = str.find_first_of(']', found + 1);
407 if (found == std::string::npos) break;
408 acquiredStr = str.substr(i, found - i);
409 found = str.find_first_of(',', found + 1);
410 }
411 }
412 std::vector<int32_t> duration{0};
413 if (!ParseInt(durationStr, &duration[0])) break;
414 res.push_back(duration);
415 if (!acquiredStr.empty()) {
416 std::vector<int32_t> acquiredInfo = parseIntSequence(acquiredStr);
417 if (acquiredInfo.empty()) break;
418 res.push_back(acquiredInfo);
419 } else
420 res.push_back(defaultAcquiredInfo);
421
422 i = found + 1;
423 if (found == std::string::npos || found == N - 1) aborted = false;
424 }
425
426 if (aborted) {
427 LOG(ERROR) << "Failed to parse enrollment captures:" + str;
428 res.clear();
429 }
430
431 return res;
432}
433
434std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
435 std::pair<AcquiredInfo, int32_t> res;
436 if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
437 res.first = AcquiredInfo::VENDOR;
438 res.second = code - FINGERPRINT_ACQUIRED_VENDOR_BASE;
439 } else {
440 res.first = (AcquiredInfo)code;
441 res.second = 0;
442 }
443 return res;
444}
445
446std::pair<Error, int32_t> FakeFingerprintEngine::convertError(int32_t code) {
447 std::pair<Error, int32_t> res;
448 if (code > FINGERPRINT_ERROR_VENDOR_BASE) {
449 res.first = Error::VENDOR;
450 res.second = code - FINGERPRINT_ERROR_VENDOR_BASE;
451 } else {
452 res.first = (Error)code;
453 res.second = 0;
454 }
455 return res;
456}
457
Joe Bolingerde94aa02021-12-09 17:00:32 -0800458} // namespace aidl::android::hardware::biometrics::fingerprint