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 "FaceVirtualHalAidl"
27
28 namespace aidl::android::hardware::biometrics::face {
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 Face::cfg().sourcedFromAidl();
34 Face::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 Face::cfg().sourcedFromAidl();
40 Face::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
41 return ndk::ScopedAStatus::ok();
42 }
43
setNextEnrollment(const::aidl::android::hardware::biometrics::face::NextEnrollment & next_enrollment)44 ::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
45 const ::aidl::android::hardware::biometrics::face::NextEnrollment& next_enrollment) {
46 Face::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 Face::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 Face::cfg().sourcedFromAidl();
82 Face::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 Face::cfg().sourcedFromAidl();
88 Face::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 Face::cfg().sourcedFromAidl();
94 Face::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 Face::cfg().sourcedFromAidl();
106 Face::cfg().setopt<OptIntVec>("operation_authenticate_latency", 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 Face::cfg().sourcedFromAidl();
116 Face::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 Face::cfg().sourcedFromAidl();
122 Face::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 Face::cfg().sourcedFromAidl();
129 Face::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
130 acquiredInfoVec2OptIntVec(in_acquired));
131 return ndk::ScopedAStatus::ok();
132 }
133
setOperationEnrollLatency(const std::vector<int32_t> & in_latency)134 ::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
135 ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
136 if (!status.isOk()) {
137 return status;
138 }
139 Face::cfg().sourcedFromAidl();
140 Face::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
141 return ndk::ScopedAStatus::ok();
142 }
143
setOperationDetectInteractionLatency(const std::vector<int32_t> & in_latency)144 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
145 const std::vector<int32_t>& in_latency) {
146 ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
147 if (!status.isOk()) {
148 return status;
149 }
150 Face::cfg().sourcedFromAidl();
151 Face::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
152 intVec2OptIntVec(in_latency));
153 return ndk::ScopedAStatus::ok();
154 }
155
setOperationDetectInteractionFails(bool in_fails)156 ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionFails(bool in_fails) {
157 Face::cfg().sourcedFromAidl();
158 Face::cfg().set<bool>("operation_detect_interaction_fails", in_fails);
159 return ndk::ScopedAStatus::ok();
160 }
161
setLockout(bool in_lockout)162 ::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
163 Face::cfg().sourcedFromAidl();
164 Face::cfg().set<bool>("lockout", in_lockout);
165 return ndk::ScopedAStatus::ok();
166 }
167
setLockoutEnable(bool in_enable)168 ::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
169 Face::cfg().sourcedFromAidl();
170 Face::cfg().set<bool>("lockout_enable", in_enable);
171 return ndk::ScopedAStatus::ok();
172 }
173
setLockoutTimedEnable(bool in_enable)174 ::ndk::ScopedAStatus VirtualHal::setLockoutTimedEnable(bool in_enable) {
175 Face::cfg().sourcedFromAidl();
176 Face::cfg().set<bool>("lockout_timed_enable", in_enable);
177 return ndk::ScopedAStatus::ok();
178 }
179
setLockoutTimedThreshold(int32_t in_threshold)180 ::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
181 if (in_threshold < 0) {
182 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
183 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
184 }
185 Face::cfg().sourcedFromAidl();
186 Face::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
187 return ndk::ScopedAStatus::ok();
188 }
189
setLockoutTimedDuration(int32_t in_duration)190 ::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
191 if (in_duration < 0) {
192 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
193 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
194 }
195 Face::cfg().sourcedFromAidl();
196 Face::cfg().set<int32_t>("lockout_timed_duration", in_duration);
197 return ndk::ScopedAStatus::ok();
198 }
199
setLockoutPermanentThreshold(int32_t in_threshold)200 ::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
201 if (in_threshold < 0) {
202 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
203 IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
204 }
205 Face::cfg().sourcedFromAidl();
206 Face::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
207 return ndk::ScopedAStatus::ok();
208 }
209
resetConfigurations()210 ::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
211 Face::cfg().sourcedFromAidl();
212 Face::cfg().init();
213 return ndk::ScopedAStatus::ok();
214 }
215
setType(::aidl::android::hardware::biometrics::face::FaceSensorType in_type)216 ::ndk::ScopedAStatus VirtualHal::setType(
217 ::aidl::android::hardware::biometrics::face::FaceSensorType in_type) {
218 Face::cfg().sourcedFromAidl();
219 Face::cfg().set<std::string>("type", Face::type2String(in_type));
220 return ndk::ScopedAStatus::ok();
221 }
222
setSensorStrength(common::SensorStrength in_strength)223 ::ndk::ScopedAStatus VirtualHal::setSensorStrength(common::SensorStrength in_strength) {
224 Face::cfg().sourcedFromAidl();
225 Face::cfg().set<std::string>("strength", Face::strength2String(in_strength));
226 return ndk::ScopedAStatus::ok();
227 }
228
intVec2OptIntVec(const std::vector<int32_t> & in_vec)229 OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
230 OptIntVec optIntVec;
231 std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
232 [](int value) { return std::optional<int>(value); });
233 return optIntVec;
234 }
235
acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode> & in_vec)236 OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
237 const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
238 OptIntVec optIntVec;
239 std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
240 [](AcquiredInfoAndVendorCode ac) {
241 int value;
242 if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
243 value = (int)ac.get<Tag::acquiredInfo>();
244 else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
245 value = ac.get<Tag::vendorCode>();
246 else
247 LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
248 return std::optional<int>(value);
249 });
250 return optIntVec;
251 }
252
sanityCheckLatency(const std::vector<int32_t> & in_latency)253 ::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
254 if (in_latency.size() == 0 || in_latency.size() > 2) {
255 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
256 IVirtualHal::STATUS_INVALID_PARAMETER,
257 "Error: input input array must contain 1 or 2 elements"));
258 }
259
260 for (auto x : in_latency) {
261 if (x < 0) {
262 return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
263 IVirtualHal::STATUS_INVALID_PARAMETER,
264 "Error: input data must not be negative"));
265 }
266 }
267
268 return ndk::ScopedAStatus::ok();
269 }
270
getFaceHal(std::shared_ptr<IFace> * pFace)271 ::ndk::ScopedAStatus VirtualHal::getFaceHal(std::shared_ptr<IFace>* pFace) {
272 *pFace = mFp;
273 return ndk::ScopedAStatus::ok();
274 }
275 } // namespace aidl::android::hardware::biometrics::face
276