/* * Copyright (C) 2017 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. */ #define LOG_TAG "android.hardware.biometrics.fingerprint@2.0-service" #define LOG_VERBOSE "android.hardware.biometrics.fingerprint@2.0-service" #include #include #include #include "BiometricsFingerprint.h" #include #include #include fingerprint_device_t* getWrapperService(fingerprint_notify_t); namespace android { namespace hardware { namespace biometrics { namespace fingerprint { namespace V2_1 { namespace implementation { // Supported fingerprint HAL version static bool is_goodix = false; 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 char vend [PROPERTY_VALUE_MAX]; property_get("ro.boot.fpsensor", vend, NULL); if (!strcmp(vend, "fpc")) { is_goodix = false; mDevice = openHal(); } else if (!strcmp(vend, "gdx")) { is_goodix = true; mDevice = getWrapperService(BiometricsFingerprint::notify); } if (!mDevice) { ALOGE("Can't open 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) { 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() { fingerprint_msg_t msg; msg.type = FINGERPRINT_ERROR; msg.data.error = FINGERPRINT_ERROR_CANCELED; mDevice->notify(&msg); return ErrorFilter(mDevice->cancel(mDevice)); } #define MAX_FINGERPRINTS 100 typedef int (*enumerate_2_0)(struct fingerprint_device *dev, fingerprint_finger_id_t *results, uint32_t *max_size); Return BiometricsFingerprint::enumerate() { fingerprint_finger_id_t results[MAX_FINGERPRINTS]; uint32_t n = MAX_FINGERPRINTS; enumerate_2_0 enumerate = (enumerate_2_0) mDevice->enumerate; int ret = enumerate(mDevice, results, &n); if (ret == 0 && mClientCallback != nullptr) { ALOGD("Got %d enumerated templates", n); for (uint32_t i = 0; i < n; i++) { const uint64_t devId = reinterpret_cast(mDevice); const auto& fp = results[i]; ALOGD("onEnumerate(fid=%d, gid=%d)", fp.fid, fp.gid); if (!mClientCallback->onEnumerate(devId, fp.fid, fp.gid, n - i - 1).isOk()) { ALOGE("failed to invoke fingerprint onEnumerate callback"); } } } return ErrorFilter(ret); } 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; } int ret = mDevice->set_active_group(mDevice, gid, storePath.c_str()); if ((ret > 0) && is_goodix) ret = 0; return ErrorFilter(ret); } Return BiometricsFingerprint::authenticate(uint64_t operationId, uint32_t gid) { return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid)); } IBiometricsFingerprint* BiometricsFingerprint::getInstance() { if (!sInstance) { sInstance = new BiometricsFingerprint(); } return sInstance; } fingerprint_device_t* BiometricsFingerprint::openHal() { int err; const hw_module_t *hw_mdl = nullptr; ALOGD("Opening fingerprint hal library..."); if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &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; } 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()); 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); 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); if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) { ALOGE("failed to invoke fingerprint onAcquired callback"); } } break; case FINGERPRINT_TEMPLATE_ENROLLING: 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: 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) { 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: // ignored, won't happen for 2.0 HALs break; } } } // namespace implementation } // namespace V2_1 } // namespace fingerprint } // namespace biometrics } // namespace hardware } // namespace android