/* * Copyright (C) 2017 The Android Open Source Project * 2022 The LineageOS Project * * SPDX-License-Identifier: Apache-2.0 */ #define LOG_TAG "android.hardware.biometrics.fingerprint@2.3-service.xiaomi" #include #include #include "BiometricsFingerprint.h" #include #include namespace { typedef struct fingerprint_hal { const char* class_name; const bool is_udfps; } fingerprint_hal_t; static const fingerprint_hal_t kModules[] = { {"fpc", false}, {"fpc_fod", true}, {"goodix", false}, {"goodix_fod", true}, {"goodix_fod6", true}, {"silead", false}, {"syna", true}, }; } // anonymous namespace namespace android { namespace hardware { namespace biometrics { namespace fingerprint { namespace V2_3 { namespace implementation { // Supported fingerprint HAL version static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1); using RequestStatus = android::hardware::biometrics::fingerprint::V2_1::RequestStatus; BiometricsFingerprint* BiometricsFingerprint::sInstance = nullptr; BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr), mDevice(nullptr) { sInstance = this; // keep track of the most recent instance for (auto& [class_name, is_udfps] : kModules) { mDevice = openHal(class_name); if (!mDevice) { ALOGE("Can't open HAL module, class %s", class_name); continue; } ALOGI("Opened fingerprint HAL, class %s", class_name); mIsUdfps = is_udfps; break; } if (!mDevice) { ALOGE("Can't open any HAL module"); } } BiometricsFingerprint::~BiometricsFingerprint() { ALOGV("~BiometricsFingerprint()"); if (mDevice == nullptr) { ALOGE("No valid device"); return; } int err; if (0 != (err = mDevice->common.close(reinterpret_cast(mDevice)))) { ALOGE("Can't close fingerprint module, error: %d", err); return; } mDevice = nullptr; } Return BiometricsFingerprint::ErrorFilter(int32_t error) { switch (error) { case 0: return RequestStatus::SYS_OK; case -2: return RequestStatus::SYS_ENOENT; case -4: return RequestStatus::SYS_EINTR; case -5: return RequestStatus::SYS_EIO; case -11: return RequestStatus::SYS_EAGAIN; case -12: return RequestStatus::SYS_ENOMEM; case -13: return RequestStatus::SYS_EACCES; case -14: return RequestStatus::SYS_EFAULT; case -16: return RequestStatus::SYS_EBUSY; case -22: return RequestStatus::SYS_EINVAL; case -28: return RequestStatus::SYS_ENOSPC; case -110: return RequestStatus::SYS_ETIMEDOUT; default: ALOGE("An unknown error returned from fingerprint vendor library: %d", error); return RequestStatus::SYS_UNKNOWN; } } // Translate from errors returned by traditional HAL (see fingerprint.h) to // HIDL-compliant FingerprintError. FingerprintError BiometricsFingerprint::VendorErrorFilter(int32_t error, int32_t* vendorCode) { *vendorCode = 0; switch (error) { case FINGERPRINT_ERROR_HW_UNAVAILABLE: return FingerprintError::ERROR_HW_UNAVAILABLE; case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: return FingerprintError::ERROR_UNABLE_TO_PROCESS; case FINGERPRINT_ERROR_TIMEOUT: return FingerprintError::ERROR_TIMEOUT; case FINGERPRINT_ERROR_NO_SPACE: return FingerprintError::ERROR_NO_SPACE; case FINGERPRINT_ERROR_CANCELED: return FingerprintError::ERROR_CANCELED; case FINGERPRINT_ERROR_UNABLE_TO_REMOVE: return FingerprintError::ERROR_UNABLE_TO_REMOVE; case FINGERPRINT_ERROR_LOCKOUT: return FingerprintError::ERROR_LOCKOUT; default: if (error >= FINGERPRINT_ERROR_VENDOR_BASE) { // vendor specific code. *vendorCode = error - FINGERPRINT_ERROR_VENDOR_BASE; return FingerprintError::ERROR_VENDOR; } } ALOGE("Unknown error from fingerprint vendor library: %d", error); return FingerprintError::ERROR_UNABLE_TO_PROCESS; } // Translate acquired messages returned by traditional HAL (see fingerprint.h) // to HIDL-compliant FingerprintAcquiredInfo. FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(int32_t info, int32_t* vendorCode) { *vendorCode = 0; switch (info) { case FINGERPRINT_ACQUIRED_GOOD: return FingerprintAcquiredInfo::ACQUIRED_GOOD; case FINGERPRINT_ACQUIRED_PARTIAL: return FingerprintAcquiredInfo::ACQUIRED_PARTIAL; case FINGERPRINT_ACQUIRED_INSUFFICIENT: return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT; case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: return FingerprintAcquiredInfo::ACQUIRED_IMAGER_DIRTY; case FINGERPRINT_ACQUIRED_TOO_SLOW: return FingerprintAcquiredInfo::ACQUIRED_TOO_SLOW; case FINGERPRINT_ACQUIRED_TOO_FAST: return FingerprintAcquiredInfo::ACQUIRED_TOO_FAST; default: if (info >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { // vendor specific code. *vendorCode = info - FINGERPRINT_ACQUIRED_VENDOR_BASE; return FingerprintAcquiredInfo::ACQUIRED_VENDOR; } } ALOGE("Unknown acquiredmsg from fingerprint vendor library: %d", info); return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT; } Return BiometricsFingerprint::setNotify( const sp& clientCallback) { std::lock_guard lock(mClientCallbackMutex); mClientCallback = clientCallback; // This is here because HAL 2.1 doesn't have a way to propagate a // unique token for its driver. Subsequent versions should send a unique // token for each call to setNotify(). This is fine as long as there's only // one fingerprint device on the platform. return reinterpret_cast(mDevice); } Return BiometricsFingerprint::preEnroll() { return mDevice->pre_enroll(mDevice); } Return BiometricsFingerprint::enroll(const hidl_array& hat, uint32_t gid, uint32_t timeoutSec) { const hw_auth_token_t* authToken = reinterpret_cast(hat.data()); return ErrorFilter(mDevice->enroll(mDevice, authToken, gid, timeoutSec)); } Return BiometricsFingerprint::postEnroll() { return ErrorFilter(mDevice->post_enroll(mDevice)); } Return BiometricsFingerprint::getAuthenticatorId() { return mDevice->get_authenticator_id(mDevice); } Return BiometricsFingerprint::cancel() { return ErrorFilter(mDevice->cancel(mDevice)); } Return BiometricsFingerprint::enumerate() { return ErrorFilter(mDevice->enumerate(mDevice)); } Return BiometricsFingerprint::remove(uint32_t gid, uint32_t fid) { return ErrorFilter(mDevice->remove(mDevice, gid, fid)); } Return BiometricsFingerprint::setActiveGroup(uint32_t gid, const hidl_string& storePath) { if (storePath.size() >= PATH_MAX || storePath.size() <= 0) { ALOGE("Bad path length: %zd", storePath.size()); return RequestStatus::SYS_EINVAL; } if (access(storePath.c_str(), W_OK)) { return RequestStatus::SYS_EINVAL; } return ErrorFilter(mDevice->set_active_group(mDevice, gid, storePath.c_str())); } Return BiometricsFingerprint::authenticate(uint64_t operationId, uint32_t gid) { return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid)); } Return BiometricsFingerprint::isUdfps(uint32_t /*sensorId*/) { return mIsUdfps; } Return BiometricsFingerprint::onFingerDown(uint32_t /*x*/, uint32_t /*y*/, float /*minor*/, float /*major*/) { return Void(); } Return BiometricsFingerprint::onFingerUp() { return Void(); } IBiometricsFingerprint* BiometricsFingerprint::getInstance() { if (!sInstance) { sInstance = new BiometricsFingerprint(); } return sInstance; } fingerprint_device_t* BiometricsFingerprint::openHal(const char* class_name) { int err; const hw_module_t* hw_mdl = nullptr; ALOGD("Opening fingerprint hal library..."); if (0 != (err = hw_get_module_by_class(FINGERPRINT_HARDWARE_MODULE_ID, class_name, &hw_mdl))) { ALOGE("Can't open fingerprint HW Module, error: %d", err); return nullptr; } if (hw_mdl == nullptr) { ALOGE("No valid fingerprint module"); return nullptr; } fingerprint_module_t const* module = reinterpret_cast(hw_mdl); if (module->common.methods->open == nullptr) { ALOGE("No valid open method"); return nullptr; } hw_device_t* device = nullptr; if (0 != (err = module->common.methods->open(hw_mdl, nullptr, &device))) { ALOGE("Can't open fingerprint methods, error: %d", err); return nullptr; } if (kVersion != device->version) { // enforce version on new devices because of HIDL@2.1 translation layer ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); return nullptr; } fingerprint_device_t* fp_device = reinterpret_cast(device); if (0 != (err = fp_device->set_notify(fp_device, BiometricsFingerprint::notify))) { ALOGE("Can't register fingerprint module callback, error: %d", err); return nullptr; } return fp_device; } void BiometricsFingerprint::notify(const fingerprint_msg_t* msg) { BiometricsFingerprint* thisPtr = static_cast(BiometricsFingerprint::getInstance()); std::lock_guard lock(thisPtr->mClientCallbackMutex); if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) { ALOGE("Receiving callbacks before the client callback is registered."); return; } const uint64_t devId = reinterpret_cast(thisPtr->mDevice); switch (msg->type) { case FINGERPRINT_ERROR: { int32_t vendorCode = 0; FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode); ALOGD("onError(%d)", result); if (!thisPtr->mClientCallback->onError(devId, result, vendorCode).isOk()) { ALOGE("failed to invoke fingerprint onError callback"); } } break; case FINGERPRINT_ACQUIRED: { int32_t vendorCode = 0; FingerprintAcquiredInfo result = VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode); ALOGD("onAcquired(%d)", result); if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) { ALOGE("failed to invoke fingerprint onAcquired callback"); } } break; case FINGERPRINT_TEMPLATE_ENROLLING: ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)", msg->data.enroll.finger.fid, msg->data.enroll.finger.gid, msg->data.enroll.samples_remaining); if (!thisPtr->mClientCallback ->onEnrollResult(devId, msg->data.enroll.finger.fid, msg->data.enroll.finger.gid, msg->data.enroll.samples_remaining) .isOk()) { ALOGE("failed to invoke fingerprint onEnrollResult callback"); } break; case FINGERPRINT_TEMPLATE_REMOVED: ALOGD("onRemove(fid=%d, gid=%d, rem=%d)", msg->data.removed.finger.fid, msg->data.removed.finger.gid, msg->data.removed.remaining_templates); if (!thisPtr->mClientCallback ->onRemoved(devId, msg->data.removed.finger.fid, msg->data.removed.finger.gid, msg->data.removed.remaining_templates) .isOk()) { ALOGE("failed to invoke fingerprint onRemoved callback"); } break; case FINGERPRINT_AUTHENTICATED: if (msg->data.authenticated.finger.fid != 0) { ALOGD("onAuthenticated(fid=%d, gid=%d)", msg->data.authenticated.finger.fid, msg->data.authenticated.finger.gid); const uint8_t* hat = reinterpret_cast(&msg->data.authenticated.hat); const hidl_vec token( std::vector(hat, hat + sizeof(msg->data.authenticated.hat))); if (!thisPtr->mClientCallback ->onAuthenticated(devId, msg->data.authenticated.finger.fid, msg->data.authenticated.finger.gid, token) .isOk()) { ALOGE("failed to invoke fingerprint onAuthenticated callback"); } } else { // Not a recognized fingerprint if (!thisPtr->mClientCallback ->onAuthenticated(devId, msg->data.authenticated.finger.fid, msg->data.authenticated.finger.gid, hidl_vec()) .isOk()) { ALOGE("failed to invoke fingerprint onAuthenticated callback"); } } break; case FINGERPRINT_TEMPLATE_ENUMERATING: ALOGD("onEnumerate(fid=%d, gid=%d, rem=%d)", msg->data.enumerated.finger.fid, msg->data.enumerated.finger.gid, msg->data.enumerated.remaining_templates); if (!thisPtr->mClientCallback ->onEnumerate(devId, msg->data.enumerated.finger.fid, msg->data.enumerated.finger.gid, msg->data.enumerated.remaining_templates) .isOk()) { ALOGE("failed to invoke fingerprint onEnumerate callback"); } break; } } } // namespace implementation } // namespace V2_3 } // namespace fingerprint } // namespace biometrics } // namespace hardware } // namespace android