blob: 68a1f26a0be671da1854199fa6941598dca4fde6 [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
59 if (FingerprintHalProperties::operation_enroll_fails().value_or(false)) {
60 LOG(ERROR) << "Fail: operation_enroll_fails";
61 cb->onError(Error::VENDOR, 0 /* vendorError */);
62 return;
63 }
64
65 // format is "<id>:<progress_ms>,<progress_ms>,...:<result>
66 auto nextEnroll = FingerprintHalProperties::next_enrollment().value_or("");
Joshua McCloskeydb009a52022-05-10 05:18:20 +000067 auto parts = Util::split(nextEnroll, ":");
Joe Bolingerde94aa02021-12-09 17:00:32 -080068 if (parts.size() != 3) {
69 LOG(ERROR) << "Fail: invalid next_enrollment";
70 cb->onError(Error::VENDOR, 0 /* vendorError */);
71 return;
72 }
73 auto enrollmentId = std::stoi(parts[0]);
Joshua McCloskeydb009a52022-05-10 05:18:20 +000074 auto progress = Util::split(parts[1], ",");
Joe Bolingerde94aa02021-12-09 17:00:32 -080075 for (size_t i = 0; i < progress.size(); i++) {
76 auto left = progress.size() - i - 1;
77 SLEEP_MS(std::stoi(progress[i]));
78
79 if (shouldCancel(cancel)) {
80 LOG(ERROR) << "Fail: cancel";
81 cb->onError(Error::CANCELED, 0 /* vendorCode */);
82 return;
83 }
84
85 cb->onAcquired(AcquiredInfo::GOOD, 0 /* vendorCode */);
86 if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
87 LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
88 FingerprintHalProperties::next_enrollment({});
89 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
90 } else { // progress and update props if last time
91 if (left == 0) {
92 auto enrollments = FingerprintHalProperties::enrollments();
93 enrollments.emplace_back(enrollmentId);
94 FingerprintHalProperties::enrollments(enrollments);
95 FingerprintHalProperties::next_enrollment({});
96 LOG(INFO) << "Enrolled: " << enrollmentId;
97 }
98 cb->onEnrollmentProgress(enrollmentId, left);
99 }
100 }
101}
102
103void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */,
104 const std::future<void>& cancel) {
105 BEGIN_OP(FingerprintHalProperties::operation_authenticate_latency().value_or(DEFAULT_LATENCY));
106
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000107 auto now = Util::getSystemNanoTime();
Joe Bolingerde94aa02021-12-09 17:00:32 -0800108 int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(0);
109 do {
110 if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
111 LOG(ERROR) << "Fail: operation_authenticate_fails";
112 cb->onError(Error::VENDOR, 0 /* vendorError */);
113 return;
114 }
115
116 if (FingerprintHalProperties::lockout().value_or(false)) {
117 LOG(ERROR) << "Fail: lockout";
118 cb->onLockoutPermanent();
119 cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
120 return;
121 }
122
123 if (shouldCancel(cancel)) {
124 LOG(ERROR) << "Fail: cancel";
125 cb->onError(Error::CANCELED, 0 /* vendorCode */);
126 return;
127 }
128
129 auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
130 auto enrolls = FingerprintHalProperties::enrollments();
131 auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
132 if (id > 0 && isEnrolled) {
133 cb->onAuthenticationSucceeded(id, {} /* hat */);
134 return;
135 }
136
137 SLEEP_MS(100);
Joshua McCloskeydb009a52022-05-10 05:18:20 +0000138 } while (!Util::hasElapsed(now, duration));
Joe Bolingerde94aa02021-12-09 17:00:32 -0800139
140 LOG(ERROR) << "Fail: not enrolled";
141 cb->onAuthenticationFailed();
142 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
143}
144
145void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
146 const std::future<void>& cancel) {
147 BEGIN_OP(FingerprintHalProperties::operation_detect_interaction_latency().value_or(
148 DEFAULT_LATENCY));
149
150 if (FingerprintHalProperties::operation_detect_interaction_fails().value_or(false)) {
151 LOG(ERROR) << "Fail: operation_detect_interaction_fails";
152 cb->onError(Error::VENDOR, 0 /* vendorError */);
153 return;
154 }
155
156 if (shouldCancel(cancel)) {
157 LOG(ERROR) << "Fail: cancel";
158 cb->onError(Error::CANCELED, 0 /* vendorCode */);
159 return;
160 }
161
162 auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
163 auto enrolls = FingerprintHalProperties::enrollments();
164 auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
165 if (id <= 0 || !isEnrolled) {
166 LOG(ERROR) << "Fail: not enrolled";
167 cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
168 return;
169 }
170
171 cb->onInteractionDetected();
172}
173
174void FakeFingerprintEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
175 BEGIN_OP(0);
176
177 std::vector<int32_t> ids;
Jeff Pu63f33c72022-07-28 16:06:23 -0400178 // There are some enrollment sync issue with framework, which results in
179 // a single template removal during the very firt sync command after reboot.
180 // This is a workaround for now. TODO(b/243129174)
181 ids.push_back(-1);
182
Joe Bolingerde94aa02021-12-09 17:00:32 -0800183 for (auto& enrollment : FingerprintHalProperties::enrollments()) {
184 auto id = enrollment.value_or(0);
185 if (id > 0) {
186 ids.push_back(id);
187 }
188 }
189
190 cb->onEnrollmentsEnumerated(ids);
191}
192
193void FakeFingerprintEngine::removeEnrollmentsImpl(ISessionCallback* cb,
194 const std::vector<int32_t>& enrollmentIds) {
195 BEGIN_OP(0);
196
197 std::vector<std::optional<int32_t>> newEnrollments;
198 std::vector<int32_t> removed;
199 for (auto& enrollment : FingerprintHalProperties::enrollments()) {
200 auto id = enrollment.value_or(0);
201 if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) != enrollmentIds.end()) {
202 removed.push_back(id);
203 } else if (id > 0) {
204 newEnrollments.emplace_back(id);
205 }
206 }
207 FingerprintHalProperties::enrollments(newEnrollments);
208
209 cb->onEnrollmentsRemoved(enrollmentIds);
210}
211
212void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
213 BEGIN_OP(0);
Jeff Pu63f33c72022-07-28 16:06:23 -0400214 int64_t authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
215 if (FingerprintHalProperties::enrollments().size() > 0 && authenticatorId == 0) {
216 authenticatorId = 99999999; // default authenticatorId, TODO(b/230515082)
217 }
218 cb->onAuthenticatorIdRetrieved(authenticatorId);
Joe Bolingerde94aa02021-12-09 17:00:32 -0800219}
220
221void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
222 BEGIN_OP(0);
223 auto id = FingerprintHalProperties::authenticator_id().value_or(0);
224 auto newId = id + 1;
225 FingerprintHalProperties::authenticator_id(newId);
226 cb->onAuthenticatorIdInvalidated(newId);
227}
228
229void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
230 const keymaster::HardwareAuthToken& /*hat*/) {
231 BEGIN_OP(0);
232 FingerprintHalProperties::lockout(false);
233 cb->onLockoutCleared();
234}
235
Jeff Pu63f33c72022-07-28 16:06:23 -0400236ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
237 int32_t /*y*/, float /*minor*/,
238 float /*major*/) {
239 BEGIN_OP(0);
240 return ndk::ScopedAStatus::ok();
241}
242
243ndk::ScopedAStatus FakeFingerprintEngine::onPointerUpImpl(int32_t /*pointerId*/) {
244 BEGIN_OP(0);
245 return ndk::ScopedAStatus::ok();
246}
247
248ndk::ScopedAStatus FakeFingerprintEngine::onUiReadyImpl() {
249 BEGIN_OP(0);
250 return ndk::ScopedAStatus::ok();
251}
252
253bool FakeFingerprintEngine::getSensorLocationConfig(SensorLocation& out) {
254 auto loc = FingerprintHalProperties::sensor_location().value_or("");
255 auto isValidStr = false;
256 auto dim = Util::split(loc, ":");
257
258 if (dim.size() < 3 or dim.size() > 4) {
259 if (!loc.empty()) LOG(WARNING) << "Invalid sensor location input (x:y:radius):" + loc;
260 return false;
261 } else {
262 int32_t x, y, r;
263 std::string d = "";
264 if (dim.size() >= 3) {
265 isValidStr = ParseInt(dim[0], &x) && ParseInt(dim[1], &y) && ParseInt(dim[2], &r);
266 }
267 if (dim.size() >= 4) {
268 d = dim[3];
269 }
270 if (isValidStr) out = {0, x, y, r, d};
271
272 return isValidStr;
273 }
274}
275SensorLocation FakeFingerprintEngine::getSensorLocation() {
276 SensorLocation location;
277
278 if (getSensorLocationConfig(location)) {
279 return location;
280 } else {
281 return defaultSensorLocation();
282 }
283}
284
285SensorLocation FakeFingerprintEngine::defaultSensorLocation() {
286 return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */,
287 0 /* sensorRadius */, "" /* display */};
288}
Joe Bolingerde94aa02021-12-09 17:00:32 -0800289} // namespace aidl::android::hardware::biometrics::fingerprint