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