1 /*
2 * Copyright (C) 2024 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 <unordered_map>
18
19 #include "VirtualHal.h"
20
21 #include <android-base/logging.h>
22
23 #include "util/CancellationSignal.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "FingerprintVirtualHalAidl"
27
28 namespace aidl::android::hardware::biometrics::fingerprint {
29 using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
30 using Tag = AcquiredInfoAndVendorCode::Tag;
31
setEnrollments(const std::vector<int32_t> & enrollments)32 ::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
33 Fingerprint::cfg().sourcedFromAidl();
34 Fingerprint::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
35 return ndk::ScopedAStatus::ok();
36 }
37
setEnrollmentHit(int32_t enrollment_hit)38 ::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) {
39 Fingerprint::cfg().sourcedFromAidl();
40 Fingerprint::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
41 return ndk::ScopedAStatus::ok();
42 }
43
setNextEnrollment(const NextEnrollment & next_enrollment)44 ::ndk::ScopedAStatus VirtualHal::setNextEnrollment(const NextEnrollment& next_enrollment) {
45 Fingerprint::cfg().sourcedFromAidl();
46 std::ostringstream os;
47 os << next_enrollment.id << ":";
48
49 int stepSize = next_enrollment.progressSteps.size();
50 for (int i = 0; i < stepSize; i++) {
51 auto& step = next_enrollment.progressSteps[i];
52 os << step.durationMs;
53 int acSize = step.acquiredInfoAndVendorCodes.size();
54 for (int j = 0; j < acSize; j++) {
55 if (j == 0) os << "-[";
56 auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
57 if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
58 os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
59 else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
60 os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
61 else
62 LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
63 if (j == acSize - 1)
64 os << "]";
65 else
66 os << ",";
67 }
68 if (i == stepSize - 1)
69 os << ":";
70 else
71 os << ",";
72 }
73
74 os << (next_enrollment.result ? "true" : "false");
75 Fingerprint::cfg().set<std::string>("next_enrollment", os.str());
76 return ndk::ScopedAStatus::ok();
77 }
78
setAuthenticatorId(int64_t in_id)79 ::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
80 Fingerprint::cfg().sourcedFromAidl();
81 Fingerprint::cfg().set<int64_t>("authenticator_id", in_id);
82 return ndk::ScopedAStatus::ok();
83 }
84
setChallenge(int64_t in_challenge)85 ::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) {
86 Fingerprint::cfg().sourcedFromAidl();
87 Fingerprint::cfg().set<int64_t>("challenge", in_challenge);
88 return ndk::ScopedAStatus::ok();
89 }
90
setOperationAuthenticateFails(bool in_fail)91 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) {
92 Fingerprint::cfg().sourcedFromAidl();
93 Fingerprint::cfg().set<bool>("operation_authenticate_fails", in_fail);
94 return ndk::ScopedAStatus::ok();
95 }
96
setOperationAuthenticateLatency(const std::vector<int32_t> & in_latency)97 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency(
98 const std::vector<int32_t>& in_latency) {
99 ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
100 if (!status.isOk()) {
101 return status;
102 }
103
104 Fingerprint::cfg().sourcedFromAidl();
105 Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_latency",
106 intVec2OptIntVec(in_latency));
107 return ndk::ScopedAStatus::ok();
108 }
109
setOperationAuthenticateDuration(int32_t in_duration)110 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) {
111 if (in_duration < 0) {
112 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
113 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
114 }
115 Fingerprint::cfg().sourcedFromAidl();
116 Fingerprint::cfg().set<int32_t>("operation_authenticate_duration", in_duration);
117 return ndk::ScopedAStatus::ok();
118 }
119
setOperationAuthenticateError(int32_t in_error)120 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) {
121 Fingerprint::cfg().sourcedFromAidl();
122 Fingerprint::cfg().set<int32_t>("operation_authenticate_error", in_error);
123 return ndk::ScopedAStatus::ok();
124 }
125
setOperationAuthenticateAcquired(const std::vector<AcquiredInfoAndVendorCode> & in_acquired)126 ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
127 const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
128 Fingerprint::cfg().sourcedFromAidl();
129 Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
130 acquiredInfoVec2OptIntVec(in_acquired));
131 return ndk::ScopedAStatus::ok();
132 }
133
setOperationEnrollError(int32_t in_error)134 ::ndk::ScopedAStatus VirtualHal::setOperationEnrollError(int32_t in_error) {
135 Fingerprint::cfg().sourcedFromAidl();
136 Fingerprint::cfg().set<int32_t>("operation_enroll_error", in_error);
137 return ndk::ScopedAStatus::ok();
138 }
139
setOperationEnrollLatency(const std::vector<int32_t> & in_latency)140 ::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
141 ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
142 if (!status.isOk()) {
143 return status;
144 }
145 Fingerprint::cfg().sourcedFromAidl();
146 Fingerprint::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
147 return ndk::ScopedAStatus::ok();
148 }
149
setOperationDetectInteractionLatency(const std::vector<int32_t> & in_latency)150 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
151 const std::vector<int32_t>& in_latency) {
152 ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
153 if (!status.isOk()) {
154 return status;
155 }
156 Fingerprint::cfg().sourcedFromAidl();
157 Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
158 intVec2OptIntVec(in_latency));
159 return ndk::ScopedAStatus::ok();
160 }
161
setOperationDetectInteractionError(int32_t in_error)162 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionError(int32_t in_error) {
163 Fingerprint::cfg().sourcedFromAidl();
164 Fingerprint::cfg().set<int32_t>("operation_detect_interaction_error", in_error);
165 return ndk::ScopedAStatus::ok();
166 }
167
setOperationDetectInteractionDuration(int32_t in_duration)168 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionDuration(int32_t in_duration) {
169 if (in_duration < 0) {
170 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
171 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
172 }
173 Fingerprint::cfg().sourcedFromAidl();
174 Fingerprint::cfg().set<int32_t>("operation_detect_interaction_duration", in_duration);
175 return ndk::ScopedAStatus::ok();
176 }
177
setOperationDetectInteractionAcquired(const std::vector<AcquiredInfoAndVendorCode> & in_acquired)178 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionAcquired(
179 const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
180 Fingerprint::cfg().sourcedFromAidl();
181 Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_acquired",
182 acquiredInfoVec2OptIntVec(in_acquired));
183 return ndk::ScopedAStatus::ok();
184 }
185
setLockout(bool in_lockout)186 ::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
187 Fingerprint::cfg().sourcedFromAidl();
188 Fingerprint::cfg().set<bool>("lockout", in_lockout);
189 return ndk::ScopedAStatus::ok();
190 }
191
setLockoutEnable(bool in_enable)192 ::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
193 Fingerprint::cfg().sourcedFromAidl();
194 Fingerprint::cfg().set<bool>("lockout_enable", in_enable);
195 return ndk::ScopedAStatus::ok();
196 }
197
setLockoutTimedThreshold(int32_t in_threshold)198 ::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
199 if (in_threshold < 0) {
200 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
201 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
202 }
203 Fingerprint::cfg().sourcedFromAidl();
204 Fingerprint::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
205 return ndk::ScopedAStatus::ok();
206 }
207
setLockoutTimedDuration(int32_t in_duration)208 ::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
209 if (in_duration < 0) {
210 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
211 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
212 }
213 Fingerprint::cfg().sourcedFromAidl();
214 Fingerprint::cfg().set<int32_t>("lockout_timed_duration", in_duration);
215 return ndk::ScopedAStatus::ok();
216 }
217
setLockoutPermanentThreshold(int32_t in_threshold)218 ::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
219 if (in_threshold < 0) {
220 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
221 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
222 }
223 Fingerprint::cfg().sourcedFromAidl();
224 Fingerprint::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
225 return ndk::ScopedAStatus::ok();
226 }
227
resetConfigurations()228 ::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
229 Fingerprint::cfg().sourcedFromAidl();
230 Fingerprint::cfg().init();
231 return ndk::ScopedAStatus::ok();
232 }
233
setType(::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type)234 ::ndk::ScopedAStatus VirtualHal::setType(
235 ::aidl::android::hardware::biometrics::fingerprint::FingerprintSensorType in_type) {
236 Fingerprint::cfg().sourcedFromAidl();
237 Fingerprint::cfg().set<std::string>("type", Fingerprint::type2String(in_type));
238 return ndk::ScopedAStatus::ok();
239 }
240
setSensorId(int32_t in_id)241 ::ndk::ScopedAStatus VirtualHal::setSensorId(int32_t in_id) {
242 Fingerprint::cfg().sourcedFromAidl();
243 Fingerprint::cfg().set<int32_t>("sensor_id", in_id);
244 return ndk::ScopedAStatus::ok();
245 }
246
setSensorStrength(SensorStrength in_strength)247 ::ndk::ScopedAStatus VirtualHal::setSensorStrength(SensorStrength in_strength) {
248 Fingerprint::cfg().sourcedFromAidl();
249 Fingerprint::cfg().set<int32_t>("sensor_strength", (int32_t)in_strength);
250 return ndk::ScopedAStatus::ok();
251 }
252
setMaxEnrollmentPerUser(int32_t in_max)253 ::ndk::ScopedAStatus VirtualHal::setMaxEnrollmentPerUser(int32_t in_max) {
254 Fingerprint::cfg().sourcedFromAidl();
255 Fingerprint::cfg().set<int32_t>("max_enrollments", in_max);
256 return ndk::ScopedAStatus::ok();
257 }
258
setSensorLocation(const SensorLocation & in_loc)259 ::ndk::ScopedAStatus VirtualHal::setSensorLocation(const SensorLocation& in_loc) {
260 std::string str = std::to_string(in_loc.sensorLocationX) + ":" +
261 std::to_string(in_loc.sensorLocationY) + ":" +
262 std::to_string(in_loc.sensorRadius);
263 ;
264 Fingerprint::cfg().sourcedFromAidl();
265 Fingerprint::cfg().set<std::string>("sensor_location", str);
266 return ndk::ScopedAStatus::ok();
267 }
268
setNavigationGuesture(bool in_v)269 ::ndk::ScopedAStatus VirtualHal::setNavigationGuesture(bool in_v) {
270 Fingerprint::cfg().sourcedFromAidl();
271 Fingerprint::cfg().set<bool>("navigation_guesture", in_v);
272 return ndk::ScopedAStatus::ok();
273 }
274
setDetectInteraction(bool in_v)275 ::ndk::ScopedAStatus VirtualHal::setDetectInteraction(bool in_v) {
276 Fingerprint::cfg().sourcedFromAidl();
277 Fingerprint::cfg().set<bool>("detect_interaction", in_v);
278 return ndk::ScopedAStatus::ok();
279 }
280
setDisplayTouch(bool in_v)281 ::ndk::ScopedAStatus VirtualHal::setDisplayTouch(bool in_v) {
282 Fingerprint::cfg().sourcedFromAidl();
283 Fingerprint::cfg().set<bool>("display_touch", in_v);
284 return ndk::ScopedAStatus::ok();
285 }
286
setControlIllumination(bool in_v)287 ::ndk::ScopedAStatus VirtualHal::setControlIllumination(bool in_v) {
288 Fingerprint::cfg().sourcedFromAidl();
289 Fingerprint::cfg().set<bool>("control_illumination", in_v);
290 return ndk::ScopedAStatus::ok();
291 }
292
intVec2OptIntVec(const std::vector<int32_t> & in_vec)293 OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
294 OptIntVec optIntVec;
295 std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
296 [](int value) { return std::optional<int>(value); });
297 return optIntVec;
298 }
299
acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode> & in_vec)300 OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
301 const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
302 OptIntVec optIntVec;
303 std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
304 [](AcquiredInfoAndVendorCode ac) {
305 int value;
306 if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
307 value = (int)ac.get<Tag::acquiredInfo>();
308 else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
309 value = ac.get<Tag::vendorCode>();
310 else
311 LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
312 return std::optional<int>(value);
313 });
314 return optIntVec;
315 }
316
sanityCheckLatency(const std::vector<int32_t> & in_latency)317 ::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
318 if (in_latency.size() == 0 || in_latency.size() > 2) {
319 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
320 IVirtualHal::STATUS_INVALID_PARAMETER,
321 "Error: input input array must contain 1 or 2 elements"));
322 }
323
324 for (auto x : in_latency) {
325 if (x < 0) {
326 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
327 IVirtualHal::STATUS_INVALID_PARAMETER,
328 "Error: input data must not be negative"));
329 }
330 }
331
332 return ndk::ScopedAStatus::ok();
333 }
334
getFingerprintHal(std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint> * pFp)335 ::ndk::ScopedAStatus VirtualHal::getFingerprintHal(
336 std::shared_ptr<::aidl::android::hardware::biometrics::fingerprint::IFingerprint>* pFp) {
337 LOG(INFO) << " calling getFingerprintHal in VirtualHal.cpp";
338 *pFp = mFp;
339 return ndk::ScopedAStatus::ok();
340 }
341 } // namespace aidl::android::hardware::biometrics::fingerprint
342