/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "VirtualHal.h" #include #include "util/CancellationSignal.h" #undef LOG_TAG #define LOG_TAG "FaceVirtualHalAidl" namespace aidl::android::hardware::biometrics::face { using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode; using Tag = AcquiredInfoAndVendorCode::Tag; ::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector& enrollments) { Face::cfg().sourcedFromAidl(); Face::cfg().setopt("enrollments", intVec2OptIntVec(enrollments)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) { Face::cfg().sourcedFromAidl(); Face::cfg().set("enrollment_hit", enrollment_hit); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setNextEnrollment( const ::aidl::android::hardware::biometrics::face::NextEnrollment& next_enrollment) { Face::cfg().sourcedFromAidl(); std::ostringstream os; os << next_enrollment.id << ":"; int stepSize = next_enrollment.progressSteps.size(); for (int i = 0; i < stepSize; i++) { auto& step = next_enrollment.progressSteps[i]; os << step.durationMs; int acSize = step.acquiredInfoAndVendorCodes.size(); for (int j = 0; j < acSize; j++) { if (j == 0) os << "-["; auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j]; if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode) os << acquiredInfoAndVendorCode.get(); else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo) os << (int)acquiredInfoAndVendorCode.get(); else LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag"; if (j == acSize - 1) os << "]"; else os << ","; } if (i == stepSize - 1) os << ":"; else os << ","; } os << (next_enrollment.result ? "true" : "false"); Face::cfg().set("next_enrollment", os.str()); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) { Face::cfg().sourcedFromAidl(); Face::cfg().set("authenticator_id", in_id); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) { Face::cfg().sourcedFromAidl(); Face::cfg().set("challenge", in_challenge); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) { Face::cfg().sourcedFromAidl(); Face::cfg().set("operation_authenticate_fails", in_fail); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency( const std::vector& in_latency) { ndk::ScopedAStatus status = sanityCheckLatency(in_latency); if (!status.isOk()) { return status; } Face::cfg().sourcedFromAidl(); Face::cfg().setopt("operation_authenticate_latency", intVec2OptIntVec(in_latency)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) { if (in_duration < 0) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative")); } Face::cfg().sourcedFromAidl(); Face::cfg().set("operation_authenticate_duration", in_duration); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) { Face::cfg().sourcedFromAidl(); Face::cfg().set("operation_authenticate_error", in_error); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired( const std::vector& in_acquired) { Face::cfg().sourcedFromAidl(); Face::cfg().setopt("operation_authenticate_acquired", acquiredInfoVec2OptIntVec(in_acquired)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector& in_latency) { ndk::ScopedAStatus status = sanityCheckLatency(in_latency); if (!status.isOk()) { return status; } Face::cfg().sourcedFromAidl(); Face::cfg().setopt("operation_enroll_latency", intVec2OptIntVec(in_latency)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency( const std::vector& in_latency) { ndk::ScopedAStatus status = sanityCheckLatency(in_latency); if (!status.isOk()) { return status; } Face::cfg().sourcedFromAidl(); Face::cfg().setopt("operation_detect_interact_latency", intVec2OptIntVec(in_latency)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionFails(bool in_fails) { Face::cfg().sourcedFromAidl(); Face::cfg().set("operation_detect_interaction_fails", in_fails); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) { Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout", in_lockout); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) { Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout_enable", in_enable); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockoutTimedEnable(bool in_enable) { Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout_timed_enable", in_enable); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) { if (in_threshold < 0) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative")); } Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout_timed_threshold", in_threshold); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) { if (in_duration < 0) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative")); } Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout_timed_duration", in_duration); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) { if (in_threshold < 0) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative")); } Face::cfg().sourcedFromAidl(); Face::cfg().set("lockout_permanent_threshold", in_threshold); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::resetConfigurations() { Face::cfg().sourcedFromAidl(); Face::cfg().init(); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setType( ::aidl::android::hardware::biometrics::face::FaceSensorType in_type) { Face::cfg().sourcedFromAidl(); Face::cfg().set("type", Face::type2String(in_type)); return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::setSensorStrength(common::SensorStrength in_strength) { Face::cfg().sourcedFromAidl(); Face::cfg().set("strength", Face::strength2String(in_strength)); return ndk::ScopedAStatus::ok(); } OptIntVec VirtualHal::intVec2OptIntVec(const std::vector& in_vec) { OptIntVec optIntVec; std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec), [](int value) { return std::optional(value); }); return optIntVec; } OptIntVec VirtualHal::acquiredInfoVec2OptIntVec( const std::vector& in_vec) { OptIntVec optIntVec; std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec), [](AcquiredInfoAndVendorCode ac) { int value; if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo) value = (int)ac.get(); else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode) value = ac.get(); else LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag"; return std::optional(value); }); return optIntVec; } ::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector& in_latency) { if (in_latency.size() == 0 || in_latency.size() > 2) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: input input array must contain 1 or 2 elements")); } for (auto x : in_latency) { if (x < 0) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IVirtualHal::STATUS_INVALID_PARAMETER, "Error: input data must not be negative")); } } return ndk::ScopedAStatus::ok(); } ::ndk::ScopedAStatus VirtualHal::getFaceHal(std::shared_ptr* pFace) { *pFace = mFp; return ndk::ScopedAStatus::ok(); } } // namespace aidl::android::hardware::biometrics::face