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