• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "FakeFaceEngine.h"
2 
3 #include <android-base/logging.h>
4 
5 #include <face.sysprop.h>
6 
7 #include "util/CancellationSignal.h"
8 #include "util/Util.h"
9 
10 using namespace ::android::face::virt;
11 
12 namespace aidl::android::hardware::biometrics::face {
13 
GetSensorType()14 FaceSensorType FakeFaceEngine::GetSensorType() {
15     std::string type = FaceHalProperties::type().value_or("");
16     if (type == "IR") {
17         return FaceSensorType::IR;
18     } else {
19         FaceHalProperties::type("RGB");
20         return FaceSensorType::RGB;
21     }
22 }
23 
GetSensorStrength()24 common::SensorStrength FakeFaceEngine::GetSensorStrength() {
25     std::string strength = FaceHalProperties::strength().value_or("");
26     if (strength == "convenience") {
27         return common::SensorStrength::CONVENIENCE;
28     } else if (strength == "weak") {
29         return common::SensorStrength::WEAK;
30     } else {
31         FaceHalProperties::strength("strong");
32         return common::SensorStrength::STRONG;
33     }
34 }
35 
generateChallengeImpl(ISessionCallback * cb)36 void FakeFaceEngine::generateChallengeImpl(ISessionCallback* cb) {
37     BEGIN_OP(0);
38     std::uniform_int_distribution<int64_t> dist;
39     auto challenge = dist(mRandom);
40     FaceHalProperties::challenge(challenge);
41     cb->onChallengeGenerated(challenge);
42 }
43 
revokeChallengeImpl(ISessionCallback * cb,int64_t challenge)44 void FakeFaceEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
45     BEGIN_OP(0);
46     FaceHalProperties::challenge({});
47     cb->onChallengeRevoked(challenge);
48 }
getEnrollmentConfigImpl(ISessionCallback *,std::vector<EnrollmentStageConfig> *)49 void FakeFaceEngine::getEnrollmentConfigImpl(ISessionCallback* /*cb*/,
50                                              std::vector<EnrollmentStageConfig>* /*return_val*/) {}
enrollImpl(ISessionCallback * cb,const keymaster::HardwareAuthToken & hat,EnrollmentType,const std::vector<Feature> &,const std::future<void> & cancel)51 void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
52                                 EnrollmentType /*enrollmentType*/,
53                                 const std::vector<Feature>& /*features*/,
54                                 const std::future<void>& cancel) {
55     BEGIN_OP(FaceHalProperties::operation_start_enroll_latency().value_or(0));
56     // format is "<id>,<bucket_id>:<delay>:<succeeds>,<bucket_id>:<delay>:<succeeds>...
57     auto nextEnroll = FaceHalProperties::next_enrollment().value_or("");
58     // Erase the next enrollment
59     FaceHalProperties::next_enrollment({});
60 
61     AuthenticationFrame frame;
62     frame.data.acquiredInfo = AcquiredInfo::START;
63     frame.data.vendorCode = 0;
64     cb->onAuthenticationFrame(frame);
65 
66     // Do proper HAT verification in the real implementation.
67     if (hat.mac.empty()) {
68         LOG(ERROR) << "Fail: hat";
69         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
70         return;
71     }
72 
73     if (FaceHalProperties::operation_enroll_fails().value_or(false)) {
74         LOG(ERROR) << "Fail: operation_enroll_fails";
75         cb->onError(Error::VENDOR, 0 /* vendorError */);
76         return;
77     }
78 
79     auto parts = Util::split(nextEnroll, ",");
80     if (parts.size() < 2) {
81         LOG(ERROR) << "Fail: invalid next_enrollment for : " << nextEnroll;
82         cb->onError(Error::VENDOR, 0 /* vendorError */);
83         return;
84     }
85 
86     auto enrollmentId = std::stoi(parts[0]);
87     const int numBuckets = parts.size() - 1;
88     for (size_t i = 1; i < parts.size(); i++) {
89         auto enrollHit = Util::split(parts[i], ":");
90         if (enrollHit.size() != 3) {
91             LOG(ERROR) << "Error when unpacking enrollment hit: " << parts[i];
92             cb->onError(Error::VENDOR, 0 /* vendorError */);
93         }
94         std::string bucket = enrollHit[0];
95         std::string delay = enrollHit[1];
96         std::string succeeds = enrollHit[2];
97 
98         SLEEP_MS(std::stoi(delay));
99 
100         if (shouldCancel(cancel)) {
101             LOG(ERROR) << "Fail: cancel";
102             cb->onError(Error::CANCELED, 0 /* vendorCode */);
103             return;
104         }
105 
106         if (!IS_TRUE(succeeds)) {  // end and failed
107             LOG(ERROR) << "Fail: requested by caller: " << parts[i];
108             cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
109             return;
110         }
111 
112         EnrollmentFrame frame;
113 
114         frame.data.acquiredInfo = AcquiredInfo::GOOD;
115         frame.data.vendorCode = 0;
116         cb->onEnrollmentFrame(frame);
117 
118         frame.data.acquiredInfo = AcquiredInfo::VENDOR;
119         frame.data.vendorCode = std::stoi(bucket);
120         cb->onEnrollmentFrame(frame);
121 
122         int remainingBuckets = numBuckets - i;
123         if (remainingBuckets > 0) {
124             cb->onEnrollmentProgress(enrollmentId, remainingBuckets);
125         }
126     }
127 
128     auto enrollments = FaceHalProperties::enrollments();
129     enrollments.push_back(enrollmentId);
130     FaceHalProperties::enrollments(enrollments);
131     LOG(INFO) << "enrolled : " << enrollmentId;
132     cb->onEnrollmentProgress(enrollmentId, 0);
133 }
134 
authenticateImpl(ISessionCallback * cb,int64_t,const std::future<void> & cancel)135 void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/,
136                                       const std::future<void>& cancel) {
137     BEGIN_OP(FaceHalProperties::operation_authenticate_latency().value_or(0));
138 
139     // Signal to the framework that we have begun authenticating.
140     AuthenticationFrame frame;
141     frame.data.acquiredInfo = AcquiredInfo::START;
142     frame.data.vendorCode = 0;
143     cb->onAuthenticationFrame(frame);
144 
145     // Also signal that we have opened the camera.
146     frame = {};
147     frame.data.acquiredInfo = AcquiredInfo::FIRST_FRAME_RECEIVED;
148     frame.data.vendorCode = 0;
149     cb->onAuthenticationFrame(frame);
150 
151     auto now = Util::getSystemNanoTime();
152     int64_t duration = FaceHalProperties::operation_authenticate_duration().value_or(0);
153     if (duration > 0) {
154         do {
155             SLEEP_MS(5);
156         } while (!Util::hasElapsed(now, duration));
157     }
158 
159     if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
160         LOG(ERROR) << "Fail: operation_authenticate_fails";
161         cb->onError(Error::VENDOR, 0 /* vendorError */);
162         return;
163     }
164 
165     if (FaceHalProperties::lockout().value_or(false)) {
166         LOG(ERROR) << "Fail: lockout";
167         cb->onLockoutPermanent();
168         cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
169         return;
170     }
171 
172     if (shouldCancel(cancel)) {
173         LOG(ERROR) << "Fail: cancel";
174         cb->onError(Error::CANCELED, 0 /* vendorCode */);
175         return;
176     }
177 
178     auto id = FaceHalProperties::enrollment_hit().value_or(0);
179     auto enrolls = FaceHalProperties::enrollments();
180     auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
181     if (id < 0 || !isEnrolled) {
182         LOG(ERROR) << (isEnrolled ? "invalid enrollment hit" : "Fail: not enrolled");
183         cb->onAuthenticationFailed();
184         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
185         return;
186     }
187 
188     cb->onAuthenticationSucceeded(id, {} /* hat */);
189 }
190 
detectInteractionImpl(ISessionCallback * cb,const std::future<void> & cancel)191 void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
192     BEGIN_OP(FaceHalProperties::operation_detect_interaction_latency().value_or(0));
193 
194     if (FaceHalProperties::operation_detect_interaction_fails().value_or(false)) {
195         LOG(ERROR) << "Fail: operation_detect_interaction_fails";
196         cb->onError(Error::VENDOR, 0 /* vendorError */);
197         return;
198     }
199 
200     if (shouldCancel(cancel)) {
201         LOG(ERROR) << "Fail: cancel";
202         cb->onError(Error::CANCELED, 0 /* vendorCode */);
203         return;
204     }
205 
206     auto id = FaceHalProperties::enrollment_hit().value_or(0);
207     auto enrolls = FaceHalProperties::enrollments();
208     auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
209     if (id <= 0 || !isEnrolled) {
210         LOG(ERROR) << "Fail: not enrolled";
211         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
212         return;
213     }
214 
215     cb->onInteractionDetected();
216 }
217 
enumerateEnrollmentsImpl(ISessionCallback * cb)218 void FakeFaceEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
219     BEGIN_OP(0);
220     std::vector<int32_t> enrollments;
221     for (const auto& enrollmentId : FaceHalProperties::enrollments()) {
222         if (enrollmentId) {
223             enrollments.push_back(*enrollmentId);
224         }
225     }
226     cb->onEnrollmentsEnumerated(enrollments);
227 }
228 
removeEnrollmentsImpl(ISessionCallback * cb,const std::vector<int32_t> & enrollmentIds)229 void FakeFaceEngine::removeEnrollmentsImpl(ISessionCallback* cb,
230                                            const std::vector<int32_t>& enrollmentIds) {
231     BEGIN_OP(0);
232 
233     std::vector<std::optional<int32_t>> newEnrollments;
234     for (const auto& enrollment : FaceHalProperties::enrollments()) {
235         auto id = enrollment.value_or(0);
236         if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) == enrollmentIds.end()) {
237             newEnrollments.emplace_back(id);
238         }
239     }
240     FaceHalProperties::enrollments(newEnrollments);
241     cb->onEnrollmentsRemoved(enrollmentIds);
242 }
243 
getFeaturesImpl(ISessionCallback * cb)244 void FakeFaceEngine::getFeaturesImpl(ISessionCallback* cb) {
245     BEGIN_OP(0);
246 
247     if (FaceHalProperties::enrollments().empty()) {
248         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
249         return;
250     }
251 
252     std::vector<Feature> featuresToReturn = {};
253     for (const auto& feature : FaceHalProperties::features()) {
254         if (feature) {
255             featuresToReturn.push_back((Feature)(*feature));
256         }
257     }
258     cb->onFeaturesRetrieved(featuresToReturn);
259 }
260 
setFeatureImpl(ISessionCallback * cb,const keymaster::HardwareAuthToken & hat,Feature feature,bool enabled)261 void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
262                                     Feature feature, bool enabled) {
263     BEGIN_OP(0);
264 
265     if (FaceHalProperties::enrollments().empty()) {
266         LOG(ERROR) << "Unable to set feature, enrollments are empty";
267         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
268         return;
269     }
270 
271     if (hat.mac.empty()) {
272         LOG(ERROR) << "Unable to set feature, invalid hat";
273         cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
274         return;
275     }
276 
277     auto features = FaceHalProperties::features();
278 
279     auto itr = std::find_if(features.begin(), features.end(), [feature](const auto& theFeature) {
280         return *theFeature == (int)feature;
281     });
282 
283     if (!enabled && (itr != features.end())) {
284         features.erase(itr);
285     } else if (enabled && (itr == features.end())) {
286         features.push_back((int)feature);
287     }
288 
289     FaceHalProperties::features(features);
290     cb->onFeatureSet(feature);
291 }
292 
getAuthenticatorIdImpl(ISessionCallback * cb)293 void FakeFaceEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
294     BEGIN_OP(0);
295     // If this is a weak HAL return 0 per the spec.
296     if (GetSensorStrength() != common::SensorStrength::STRONG) {
297         cb->onAuthenticatorIdRetrieved(0);
298     } else {
299         cb->onAuthenticatorIdRetrieved(FaceHalProperties::authenticator_id().value_or(0));
300     }
301 }
302 
invalidateAuthenticatorIdImpl(ISessionCallback * cb)303 void FakeFaceEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
304     BEGIN_OP(0);
305     int64_t authenticatorId = FaceHalProperties::authenticator_id().value_or(0);
306     int64_t newId = authenticatorId + 1;
307     FaceHalProperties::authenticator_id(newId);
308     cb->onAuthenticatorIdInvalidated(newId);
309 }
310 
resetLockoutImpl(ISessionCallback * cb,const keymaster::HardwareAuthToken &)311 void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
312                                       const keymaster::HardwareAuthToken& /*hat*/) {
313     BEGIN_OP(0);
314     FaceHalProperties::lockout(false);
315     cb->onLockoutCleared();
316 }
317 
318 }  // namespace aidl::android::hardware::biometrics::face