From 265678c804f708197d558e554d8f06526f08f7a5 Mon Sep 17 00:00:00 2001 From: TheScarastic Date: Sat, 16 Dec 2017 17:05:08 +0530 Subject: [PATCH] msm8937-common: Add custom biometrics --- biometrics/Android.mk | 31 ++ biometrics/BiometricsFingerprint.cpp | 369 ++++++++++++++++++ biometrics/BiometricsFingerprint.h | 83 ++++ ....fingerprint@2.1-service.xiaomi_msm8937.rc | 8 + .../FingerprintDaemonCallbackProxy.cpp | 132 +++++++ .../FingerprintDaemonCallbackProxy.h | 46 +++ .../fingerprintd/FingerprintDaemonProxy.cpp | 249 ++++++++++++ .../fingerprintd/FingerprintDaemonProxy.h | 65 +++ .../fingerprintd/IFingerprintDaemon.cpp | 334 ++++++++++++++++ biometrics/fingerprintd/IFingerprintDaemon.h | 89 +++++ .../IFingerprintDaemonCallback.cpp | 147 +++++++ .../fingerprintd/IFingerprintDaemonCallback.h | 60 +++ biometrics/fingerprintd/wrapper.cpp | 78 ++++ biometrics/service.cpp | 68 ++++ product/fingerprint.mk | 2 +- rootdir/init.qcom.rc | 9 +- sepolicy/file_contexts | 3 + 17 files changed, 1766 insertions(+), 7 deletions(-) create mode 100644 biometrics/Android.mk create mode 100644 biometrics/BiometricsFingerprint.cpp create mode 100644 biometrics/BiometricsFingerprint.h create mode 100644 biometrics/android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937.rc create mode 100644 biometrics/fingerprintd/FingerprintDaemonCallbackProxy.cpp create mode 100644 biometrics/fingerprintd/FingerprintDaemonCallbackProxy.h create mode 100644 biometrics/fingerprintd/FingerprintDaemonProxy.cpp create mode 100644 biometrics/fingerprintd/FingerprintDaemonProxy.h create mode 100644 biometrics/fingerprintd/IFingerprintDaemon.cpp create mode 100644 biometrics/fingerprintd/IFingerprintDaemon.h create mode 100644 biometrics/fingerprintd/IFingerprintDaemonCallback.cpp create mode 100644 biometrics/fingerprintd/IFingerprintDaemonCallback.h create mode 100644 biometrics/fingerprintd/wrapper.cpp create mode 100644 biometrics/service.cpp diff --git a/biometrics/Android.mk b/biometrics/Android.mk new file mode 100644 index 0000000..23721fe --- /dev/null +++ b/biometrics/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937 +LOCAL_INIT_RC := android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937.rc +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + BiometricsFingerprint.cpp \ + service.cpp \ + fingerprintd/FingerprintDaemonCallbackProxy.cpp \ + fingerprintd/FingerprintDaemonProxy.cpp \ + fingerprintd/IFingerprintDaemonCallback.cpp \ + fingerprintd/IFingerprintDaemon.cpp \ + fingerprintd/wrapper.cpp + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libcutils \ + liblog \ + libhidlbase \ + libhidltransport \ + libhardware \ + libutils \ + libhwbinder \ + libkeystore_binder \ + android.hardware.biometrics.fingerprint@2.1 \ + +include $(BUILD_EXECUTABLE) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/biometrics/BiometricsFingerprint.cpp b/biometrics/BiometricsFingerprint.cpp new file mode 100644 index 0000000..288635c --- /dev/null +++ b/biometrics/BiometricsFingerprint.cpp @@ -0,0 +1,369 @@ +/* + * 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 diff --git a/biometrics/BiometricsFingerprint.h b/biometrics/BiometricsFingerprint.h new file mode 100644 index 0000000..5923c84 --- /dev/null +++ b/biometrics/BiometricsFingerprint.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#ifndef ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H +#define ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { +namespace V2_1 { +namespace implementation { + +using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint; +using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback; +using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct BiometricsFingerprint : public IBiometricsFingerprint { +public: + BiometricsFingerprint(); + ~BiometricsFingerprint(); + + // Method to wrap legacy HAL with BiometricsFingerprint class + static IBiometricsFingerprint* getInstance(); + + // Methods from ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint follow. + Return setNotify(const sp& clientCallback) override; + Return preEnroll() override; + Return enroll(const hidl_array& hat, uint32_t gid, uint32_t timeoutSec) override; + Return postEnroll() override; + Return getAuthenticatorId() override; + Return cancel() override; + Return enumerate() override; + Return remove(uint32_t gid, uint32_t fid) override; + Return setActiveGroup(uint32_t gid, const hidl_string& storePath) override; + Return authenticate(uint64_t operationId, uint32_t gid) override; + +private: + static fingerprint_device_t* openHal(); + static void notify(const fingerprint_msg_t *msg); /* Static callback for legacy HAL implementation */ + static Return ErrorFilter(int32_t error); + static FingerprintError VendorErrorFilter(int32_t error, int32_t* vendorCode); + static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode); + static BiometricsFingerprint* sInstance; + + sp mClientCallback; + fingerprint_device_t *mDevice; +}; + +} // namespace implementation +} // namespace V2_1 +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H diff --git a/biometrics/android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937.rc b/biometrics/android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937.rc new file mode 100644 index 0000000..0dbf01a --- /dev/null +++ b/biometrics/android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937.rc @@ -0,0 +1,8 @@ +service fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937 + # "class hal" causes a race condition on some devices due to files created + # in /data. As a workaround, postpone startup until later in boot once + # /data is mounted. + class late_start + user system + group system input + disabled diff --git a/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.cpp b/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.cpp new file mode 100644 index 0000000..3d58837 --- /dev/null +++ b/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.cpp @@ -0,0 +1,132 @@ +/* + * 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_NDEBUG 0 +#define LOG_TAG "FingerprintDaemonCallbackProxy" + +#include +#include +#include +#include +#include +#include +#include "IFingerprintDaemonCallback.h" +#include "FingerprintDaemonCallbackProxy.h" + +using namespace android; + +fingerprint_notify_t FingerprintDaemonCallbackProxy::mNotify = NULL; + +FingerprintDaemonCallbackProxy::FingerprintDaemonCallbackProxy() { +} + +FingerprintDaemonCallbackProxy::~FingerprintDaemonCallbackProxy() { +} + +status_t FingerprintDaemonCallbackProxy::onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, + int32_t rem) { + fingerprint_msg_t message; + message.type = FINGERPRINT_TEMPLATE_ENROLLING; + message.data.enroll.finger.fid = fpId; + message.data.enroll.finger.gid = gpId; + message.data.enroll.samples_remaining = rem; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onEnrollResult mDevice is NULL"); + } + + return 0; +} + +status_t FingerprintDaemonCallbackProxy::onAcquired(int64_t devId, int32_t acquiredInfo) { + fingerprint_msg_t message; + message.type = FINGERPRINT_ACQUIRED; + message.data.acquired.acquired_info = (fingerprint_acquired_info_t)acquiredInfo; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onAcquired mDevice is NULL"); + } + + return 0; +} + +status_t FingerprintDaemonCallbackProxy::onAuthenticated(int64_t devId, int32_t fingerId, + int32_t groupId) { + fingerprint_msg_t message; + message.type = FINGERPRINT_AUTHENTICATED; + message.data.authenticated.finger.fid = fingerId; + message.data.authenticated.finger.gid = groupId; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onAuthenticated mDevice is NULL"); + } + + return 0; +} + +status_t FingerprintDaemonCallbackProxy::onError(int64_t devId, int32_t error) { + fingerprint_msg_t message; + message.type = FINGERPRINT_ERROR; + message.data.error = (fingerprint_error_t)error; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onError mDevice is NULL"); + } + + return 0; +} + +status_t FingerprintDaemonCallbackProxy::onRemoved(int64_t devId, + int32_t fingerId, int32_t groupId) { + fingerprint_msg_t message; + message.type = FINGERPRINT_TEMPLATE_REMOVED; + message.data.removed.finger.fid = fingerId; + message.data.removed.finger.gid = groupId; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onRemoved mDevice is NULL"); + } + + return 0; +} + +status_t FingerprintDaemonCallbackProxy::onEnumerate(int64_t devId, + const int32_t fingerId, const int32_t groupId, int32_t remaining) { + + fingerprint_msg_t message; + message.type = FINGERPRINT_TEMPLATE_ENUMERATING; + message.data.enumerated.finger.fid = fingerId; + message.data.enumerated.finger.gid = groupId; + message.data.enumerated.remaining_templates = remaining; + + if(mNotify != NULL) { + mNotify(&message); + } else { + ALOGE("onEnumerate mDevice is NULL"); + } + + return 0; +} diff --git a/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.h b/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.h new file mode 100644 index 0000000..68e429d --- /dev/null +++ b/biometrics/fingerprintd/FingerprintDaemonCallbackProxy.h @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#ifndef FINGERPRINT_DAEMON_CALLBACK_PROXY_H_ +#define FINGERPRINT_DAEMON_CALLBACK_PROXY_H_ + +#include +#include "IFingerprintDaemonCallback.h" + +namespace android { + +class FingerprintDaemonCallbackProxy: public BnFingerprintDaemonCallback { +public: + virtual status_t onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem); + virtual status_t onAcquired(int64_t devId, int32_t acquiredInfo); + virtual status_t onAuthenticated(int64_t devId, int32_t fingerId, int32_t groupId); + virtual status_t onError(int64_t devId, int32_t error); + virtual status_t onRemoved(int64_t devId, int32_t fingerId, int32_t groupId); + virtual status_t onEnumerate(int64_t devId, const int32_t fpId, const int32_t gpId, + int32_t rem); + FingerprintDaemonCallbackProxy(); + virtual ~FingerprintDaemonCallbackProxy(); + + static void setDevice(fingerprint_notify_t notify) { + mNotify = notify; + } +private: + static fingerprint_notify_t mNotify; +}; + +} + +#endif // FINGERPRINT_DAEMON_CALLBACK_PROXY_H_ diff --git a/biometrics/fingerprintd/FingerprintDaemonProxy.cpp b/biometrics/fingerprintd/FingerprintDaemonProxy.cpp new file mode 100644 index 0000000..5474fe9 --- /dev/null +++ b/biometrics/fingerprintd/FingerprintDaemonProxy.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2015 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_NDEBUG 0 +#define LOG_TAG "FingerprintDaemonProxy" + +#include +#include +#include +#include +#include +#include +#include // for error codes +#include + +#include "FingerprintDaemonProxy.h" + +namespace android { + +FingerprintDaemonProxy* FingerprintDaemonProxy::sInstance = NULL; + +// Supported fingerprint HAL version +static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 0); + +FingerprintDaemonProxy::FingerprintDaemonProxy() : mModule(NULL), mDevice(NULL), mCallback(NULL) { + +} + +FingerprintDaemonProxy::~FingerprintDaemonProxy() { + closeHal(); +} + +void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) { + FingerprintDaemonProxy* instance = FingerprintDaemonProxy::getInstance(); + const sp callback = instance->mCallback; + if (callback == NULL) { + ALOGE("Invalid callback object"); + return; + } + const int64_t device = (int64_t) instance->mDevice; + switch (msg->type) { + case FINGERPRINT_ERROR: + callback->onError(device, msg->data.error); + break; + case FINGERPRINT_ACQUIRED: + callback->onAcquired(device, msg->data.acquired.acquired_info); + break; + case FINGERPRINT_AUTHENTICATED: + if (msg->data.authenticated.finger.fid != 0) { + const uint8_t* hat = reinterpret_cast(&msg->data.authenticated.hat); + instance->notifyKeystore(hat, sizeof(msg->data.authenticated.hat)); + } + callback->onAuthenticated(device, + msg->data.authenticated.finger.fid, + msg->data.authenticated.finger.gid); + break; + case FINGERPRINT_TEMPLATE_ENROLLING: + callback->onEnrollResult(device, + msg->data.enroll.finger.fid, + msg->data.enroll.finger.gid, + msg->data.enroll.samples_remaining); + break; + case FINGERPRINT_TEMPLATE_REMOVED: + callback->onRemoved(device, + msg->data.removed.finger.fid, + msg->data.removed.finger.gid); + break; + case FINGERPRINT_TEMPLATE_ENUMERATING: + callback->onEnumerate(device, + msg->data.enumerated.finger.fid, + msg->data.enumerated.finger.gid, + msg->data.enumerated.remaining_templates); + break; + default: + ALOGE("invalid msg type: %d", msg->type); + return; + } +} + +void FingerprintDaemonProxy::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) { + if (auth_token != NULL && auth_token_length > 0) { + // TODO: cache service? + sp < IServiceManager > sm = defaultServiceManager(); + sp < IBinder > binder = sm->getService(String16("android.security.keystore")); + sp < IKeystoreService > service = interface_cast < IKeystoreService > (binder); + if (service != NULL) { + status_t ret = service->addAuthToken(auth_token, auth_token_length); + if (ret != (int)ResponseCode::NO_ERROR) { + ALOGE("Falure sending auth token to KeyStore: %d", ret); + } + } else { + ALOGE("Unable to communicate with KeyStore"); + } + } +} + +void FingerprintDaemonProxy::init(const sp& callback) { + if (mCallback != NULL && IInterface::asBinder(callback) != IInterface::asBinder(mCallback)) { + IInterface::asBinder(mCallback)->unlinkToDeath(this); + } + IInterface::asBinder(callback)->linkToDeath(this); + mCallback = callback; +} + +int32_t FingerprintDaemonProxy::enroll(const uint8_t* token, ssize_t tokenSize, int32_t groupId, + int32_t timeout) { + if (tokenSize != sizeof(hw_auth_token_t) ) { + ALOGE("enroll() : invalid token size %zu\n", tokenSize); + return -1; + } + const hw_auth_token_t* authToken = reinterpret_cast(token); + return mDevice->enroll(mDevice, authToken, groupId, timeout); +} + +uint64_t FingerprintDaemonProxy::preEnroll() { + return mDevice->pre_enroll(mDevice); +} + +int32_t FingerprintDaemonProxy::postEnroll() { + return mDevice->post_enroll(mDevice); +} + +int32_t FingerprintDaemonProxy::stopEnrollment() { + return mDevice->cancel(mDevice); +} + +int32_t FingerprintDaemonProxy::authenticate(uint64_t sessionId, uint32_t groupId) { + return mDevice->authenticate(mDevice, sessionId, groupId); +} + +int32_t FingerprintDaemonProxy::stopAuthentication() { + return mDevice->cancel(mDevice); +} + +int32_t FingerprintDaemonProxy::remove(int32_t fingerId, int32_t groupId) { + return mDevice->remove(mDevice, groupId, fingerId); +} + +int32_t FingerprintDaemonProxy::enumerate() { + return mDevice->enumerate(mDevice); +} + +int32_t FingerprintDaemonProxy::cancel() { + int ret = mDevice->cancel(mDevice); + return ret; +} + +uint64_t FingerprintDaemonProxy::getAuthenticatorId() { + return mDevice->get_authenticator_id(mDevice); +} + +int32_t FingerprintDaemonProxy::setActiveGroup(int32_t groupId, const uint8_t* path, + ssize_t pathlen) { + if (pathlen >= PATH_MAX || pathlen <= 0) { + ALOGE("Bad path length: %zd", pathlen); + return -1; + } + // Convert to null-terminated string + char path_name[PATH_MAX]; + memcpy(path_name, path, pathlen); + path_name[pathlen] = '\0'; + return mDevice->set_active_group(mDevice, groupId, path_name); +} + +int64_t FingerprintDaemonProxy::openHal() { + int err; + const hw_module_t *hw_module = NULL; + + if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_module))) { + ALOGE("Can't open fingerprint HW Module, error: %d", err); + return 0; + } + if (NULL == hw_module) { + ALOGE("No valid fingerprint module"); + return 0; + } + + mModule = reinterpret_cast(hw_module); + + if (mModule->common.methods->open == NULL) { + ALOGE("No valid open method"); + return 0; + } + + hw_device_t *device = NULL; + + if (0 != (err = mModule->common.methods->open(hw_module, NULL, &device))) { + ALOGE("Can't open fingerprint methods, error: %d", err); + return 0; + } + + if (kVersion != device->version) { + ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version); + // return 0; + } + + mDevice = reinterpret_cast(device); + err = mDevice->set_notify(mDevice, hal_notify_callback); + if (err < 0) { + ALOGE("Failed in call to set_notify(), err=%d", err); + return 0; + } + + // Sanity check - remove + if (mDevice->notify != hal_notify_callback) { + ALOGE("NOTIFY not set properly: %p != %p", mDevice->notify, hal_notify_callback); + } + + ALOGE("fingerprint HAL successfully initialized"); + return reinterpret_cast(mDevice); // This is just a handle +} + +int32_t FingerprintDaemonProxy::closeHal() { + if (mDevice == NULL) { + ALOGE("No valid device"); + return -ENOSYS; + } + int err; + if (0 != (err = mDevice->common.close(reinterpret_cast(mDevice)))) { + ALOGE("Can't close fingerprint module, error: %d", err); + return err; + } + mDevice = NULL; + return 0; +} + +void FingerprintDaemonProxy::binderDied(const wp& who) { + int err; + if (0 != (err = closeHal())) { + ALOGE("Can't close fingerprint device, error: %d", err); + } + if (IInterface::asBinder(mCallback) == who) { + mCallback = NULL; + } +} + +} diff --git a/biometrics/fingerprintd/FingerprintDaemonProxy.h b/biometrics/fingerprintd/FingerprintDaemonProxy.h new file mode 100644 index 0000000..5798e85 --- /dev/null +++ b/biometrics/fingerprintd/FingerprintDaemonProxy.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef FINGERPRINT_DAEMON_PROXY_H_ +#define FINGERPRINT_DAEMON_PROXY_H_ + +#include "IFingerprintDaemon.h" +#include "IFingerprintDaemonCallback.h" + +namespace android { + +class FingerprintDaemonProxy : public BnFingerprintDaemon { + public: + static FingerprintDaemonProxy* getInstance() { + if (sInstance == NULL) { + sInstance = new FingerprintDaemonProxy(); + } + return sInstance; + } + + // These reflect binder methods. + virtual void init(const sp& callback); + virtual int32_t enroll(const uint8_t* token, ssize_t tokenLength, int32_t groupId, int32_t timeout); + virtual uint64_t preEnroll(); + virtual int32_t postEnroll(); + virtual int32_t stopEnrollment(); + virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId); + virtual int32_t stopAuthentication(); + virtual int32_t remove(int32_t fingerId, int32_t groupId); + virtual int32_t enumerate(); + virtual int32_t cancel(); + virtual uint64_t getAuthenticatorId(); + virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen); + virtual int64_t openHal(); + virtual int32_t closeHal(); + + private: + FingerprintDaemonProxy(); + virtual ~FingerprintDaemonProxy(); + void binderDied(const wp& who); + void notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length); + static void hal_notify_callback(const fingerprint_msg_t *msg); + + static FingerprintDaemonProxy* sInstance; + fingerprint_module_t const* mModule; + fingerprint_device_t* mDevice; + sp mCallback; +}; + +} // namespace android + +#endif // FINGERPRINT_DAEMON_PROXY_H_ diff --git a/biometrics/fingerprintd/IFingerprintDaemon.cpp b/biometrics/fingerprintd/IFingerprintDaemon.cpp new file mode 100644 index 0000000..64c4093 --- /dev/null +++ b/biometrics/fingerprintd/IFingerprintDaemon.cpp @@ -0,0 +1,334 @@ +/* + * Copyright 2015, 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_NDEBUG 0 +#include +#define LOG_TAG "FingerprintDaemon" + +#include +#include +#include +#include +#include +#include +#include // for error code +#include +#include +#include +#include "IFingerprintDaemon.h" +#include "IFingerprintDaemonCallback.h" + +namespace android { + +static const String16 USE_FINGERPRINT_PERMISSION("android.permission.USE_FINGERPRINT"); +static const String16 MANAGE_FINGERPRINT_PERMISSION("android.permission.MANAGE_FINGERPRINT"); +static const String16 HAL_FINGERPRINT_PERMISSION("android.permission.MANAGE_FINGERPRINT"); // TODO +static const String16 DUMP_PERMISSION("android.permission.DUMP"); + +status_t BnFingerprintDaemon::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + switch(code) { + case AUTHENTICATE: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const uint64_t sessionId = data.readInt64(); + const uint32_t groupId = data.readInt32(); + const int32_t ret = authenticate(sessionId, groupId); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + }; + case CANCEL_AUTHENTICATION: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = stopAuthentication(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case ENROLL: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const ssize_t tokenSize = data.readInt32(); + const uint8_t* token = static_cast(data.readInplace(tokenSize)); + const int32_t groupId = data.readInt32(); + const int32_t timeout = data.readInt32(); + const int32_t ret = enroll(token, tokenSize, groupId, timeout); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case CANCEL_ENROLLMENT: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = stopEnrollment(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case PRE_ENROLL: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const uint64_t ret = preEnroll(); + reply->writeNoException(); + reply->writeInt64(ret); + return NO_ERROR; + } + case POST_ENROLL: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = postEnroll(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case REMOVE: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t fingerId = data.readInt32(); + const int32_t groupId = data.readInt32(); + const int32_t ret = remove(fingerId, groupId); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case ENUMERATE: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = enumerate(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case GET_AUTHENTICATOR_ID: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const uint64_t ret = getAuthenticatorId(); + reply->writeNoException(); + reply->writeInt64(ret); + return NO_ERROR; + } + case SET_ACTIVE_GROUP: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t group = data.readInt32(); + const ssize_t pathSize = data.readInt32(); + const uint8_t* path = static_cast(data.readInplace(pathSize)); + const int32_t ret = setActiveGroup(group, path, pathSize); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case OPEN_HAL: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int64_t ret = openHal(); + reply->writeNoException(); + reply->writeInt64(ret); + return NO_ERROR; + } + case CLOSE_HAL: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + const int32_t ret = closeHal(); + reply->writeNoException(); + reply->writeInt32(ret); + return NO_ERROR; + } + case INIT: { + CHECK_INTERFACE(IFingerprintDaemon, data, reply); + if (!checkPermission(HAL_FINGERPRINT_PERMISSION)) { + return PERMISSION_DENIED; + } + sp callback = + interface_cast(data.readStrongBinder()); + init(callback); + reply->writeNoException(); + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +}; + +bool BnFingerprintDaemon::checkPermission(const String16& permission) { + const IPCThreadState* ipc = IPCThreadState::self(); + const int calling_pid = ipc->getCallingPid(); + const int calling_uid = ipc->getCallingUid(); + + return PermissionCache::checkPermission(permission, calling_pid, calling_uid); +} + +class BpFingerprintDaemon : public BpInterface { + public: + BpFingerprintDaemon(const sp & impl) : + BpInterface(impl) { + } + + virtual void init(const sp& callback) { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + data.writeStrongBinder(callback->asBinder(callback)); + remote()->transact(INIT, data, &reply); + reply.readExceptionCode(); + return; + } + + virtual int32_t enroll(const uint8_t* token, ssize_t tokenLength, int32_t groupId, int32_t timeout) { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + data.writeInt32(tokenLength); + data.write(token, tokenLength); + data.writeInt32(groupId); + data.writeInt32(timeout); + remote()->transact(ENROLL, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual uint64_t preEnroll() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(PRE_ENROLL, data, &reply); + reply.readExceptionCode(); + return reply.readInt64(); + } + + virtual int32_t postEnroll() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(POST_ENROLL, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int32_t stopEnrollment() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(CANCEL_ENROLLMENT, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId) { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + data.writeInt64(sessionId); + data.writeInt32(groupId); + remote()->transact(AUTHENTICATE, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int32_t stopAuthentication() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(CANCEL_AUTHENTICATION, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int32_t remove(int32_t fingerId, int32_t groupId) { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + data.writeInt32(fingerId); + data.writeInt32(groupId); + remote()->transact(REMOVE, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int32_t enumerate() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(ENUMERATE, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual uint64_t getAuthenticatorId() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(GET_AUTHENTICATOR_ID, data, &reply); + reply.readExceptionCode(); + return reply.readInt64(); + } + + virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen) { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + data.writeInt32(groupId); + data.writeInt32(pathLen); + data.write(path, pathLen); + remote()->transact(SET_ACTIVE_GROUP, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual int64_t openHal() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(OPEN_HAL, data, &reply); + reply.readExceptionCode(); + return reply.readInt64(); + } + + virtual int32_t closeHal() { + Parcel data, reply; + data.writeInterfaceToken(descriptor); + remote()->transact(CLOSE_HAL, data, &reply); + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual void binderDied(const wp __unused &who) { + ALOGE("binderDied()"); + return; + } + + virtual void hal_notify_callback(const fingerprint_msg_t __unused *msg) { + ALOGE("Daemon hal_notify_callback"); + return; + } +}; + +IMPLEMENT_META_INTERFACE(FingerprintDaemon, "android.hardware.fingerprint.IFingerprintDaemon"); + +}; // namespace android diff --git a/biometrics/fingerprintd/IFingerprintDaemon.h b/biometrics/fingerprintd/IFingerprintDaemon.h new file mode 100644 index 0000000..96128e4 --- /dev/null +++ b/biometrics/fingerprintd/IFingerprintDaemon.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef IFINGERPRINT_DAEMON_H_ +#define IFINGERPRINT_DAEMON_H_ + +#include +#include + +namespace android { + +class IFingerprintDaemonCallback; + +/* +* Abstract base class for native implementation of FingerprintService. +* +* Note: This must be kept manually in sync with IFingerprintDaemon.aidl +*/ +class IFingerprintDaemon : public IInterface, public IBinder::DeathRecipient { + public: + enum { + AUTHENTICATE = IBinder::FIRST_CALL_TRANSACTION + 0, + CANCEL_AUTHENTICATION = IBinder::FIRST_CALL_TRANSACTION + 1, + ENROLL = IBinder::FIRST_CALL_TRANSACTION + 2, + CANCEL_ENROLLMENT = IBinder::FIRST_CALL_TRANSACTION + 3, + PRE_ENROLL = IBinder::FIRST_CALL_TRANSACTION + 4, + REMOVE = IBinder::FIRST_CALL_TRANSACTION + 5, + GET_AUTHENTICATOR_ID = IBinder::FIRST_CALL_TRANSACTION + 6, + SET_ACTIVE_GROUP = IBinder::FIRST_CALL_TRANSACTION + 7, + OPEN_HAL = IBinder::FIRST_CALL_TRANSACTION + 8, + CLOSE_HAL = IBinder::FIRST_CALL_TRANSACTION + 9, + INIT = IBinder::FIRST_CALL_TRANSACTION + 10, + POST_ENROLL = IBinder::FIRST_CALL_TRANSACTION + 11, + ENUMERATE = IBinder::FIRST_CALL_TRANSACTION + 12, + }; + +// IFingerprintDaemon() { } +// virtual ~IFingerprintDaemon() { } +// virtual const android::String16& getInterfaceDescriptor() const; + + // Binder interface methods + virtual void init(const sp& callback) = 0; + virtual int32_t enroll(const uint8_t* token, ssize_t tokenLength, int32_t groupId, + int32_t timeout) = 0; + virtual uint64_t preEnroll() = 0; + virtual int32_t postEnroll() = 0; + virtual int32_t stopEnrollment() = 0; + virtual int32_t authenticate(uint64_t sessionId, uint32_t groupId) = 0; + virtual int32_t stopAuthentication() = 0; + virtual int32_t remove(int32_t fingerId, int32_t groupId) = 0; + virtual int32_t enumerate() = 0; + virtual uint64_t getAuthenticatorId() = 0; + virtual int32_t setActiveGroup(int32_t groupId, const uint8_t* path, ssize_t pathLen) = 0; + virtual int64_t openHal() = 0; + virtual int32_t closeHal() = 0; + + DECLARE_META_INTERFACE(FingerprintDaemon); + + // DECLARE_META_INTERFACE - C++ client interface not needed + static void hal_notify_callback(const fingerprint_msg_t *msg); +}; + +// ---------------------------------------------------------------------------- + +class BnFingerprintDaemon: public BnInterface { + public: + virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags = 0); + private: + bool checkPermission(const String16& permission); +}; + +} // namespace android + +#endif // IFINGERPRINT_DAEMON_H_ + diff --git a/biometrics/fingerprintd/IFingerprintDaemonCallback.cpp b/biometrics/fingerprintd/IFingerprintDaemonCallback.cpp new file mode 100644 index 0000000..ccbd2cf --- /dev/null +++ b/biometrics/fingerprintd/IFingerprintDaemonCallback.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2015 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_NDEBUG 0 +#define LOG_TAG "IFingerprintDaemonCallback" +#include +#include +#include +#include + +#include "IFingerprintDaemonCallback.h" + +namespace android { + +status_t BnFingerprintDaemonCallback::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + switch (code) { + case ON_ENROLL_RESULT: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t fpId = data.readInt32(); + int32_t gpId = data.readInt32(); + int32_t rem = data.readInt32(); + onEnrollResult(devId, fpId, gpId, rem); + return NO_ERROR; + } + case ON_ACQUIRED: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t acquiredInfo = data.readInt32(); + onAcquired(devId, acquiredInfo); + return NO_ERROR; + } + case ON_AUTHENTICATED: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t fpId = data.readInt32(); + int32_t gpId = data.readInt32(); + onAuthenticated(devId, fpId, gpId); + return NO_ERROR; + } + case ON_ERROR: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t error = data.readInt32(); + onError(devId, error); + return NO_ERROR; + } + case ON_REMOVED: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t fpId = data.readInt32(); + int32_t gpId = data.readInt32(); + onRemoved(devId, fpId, gpId); + return NO_ERROR; + } + case ON_ENUMERATE: { + CHECK_INTERFACE(IFingerprintDaemonCallback, data, reply); + int64_t devId = data.readInt64(); + int32_t fpId = data.readInt32(); + int32_t gpId = data.readInt32(); + int32_t rem = data.readInt32(); + onEnumerate(devId, fpId, gpId, rem); + return NO_ERROR; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +class BpFingerprintDaemonCallback : public BpInterface +{ +public: + BpFingerprintDaemonCallback(const sp& impl) : + BpInterface(impl) { + } + virtual status_t onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(fpId); + data.writeInt32(gpId); + data.writeInt32(rem); + return remote()->transact(ON_ENROLL_RESULT, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual status_t onAcquired(int64_t devId, int32_t acquiredInfo) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(acquiredInfo); + return remote()->transact(ON_ACQUIRED, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual status_t onAuthenticated(int64_t devId, int32_t fpId, int32_t gpId) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(fpId); + data.writeInt32(gpId); + return remote()->transact(ON_AUTHENTICATED, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual status_t onError(int64_t devId, int32_t error) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(error); + return remote()->transact(ON_ERROR, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual status_t onRemoved(int64_t devId, int32_t fpId, int32_t gpId) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(fpId); + data.writeInt32(gpId); + return remote()->transact(ON_REMOVED, data, &reply, IBinder::FLAG_ONEWAY); + } + + virtual status_t onEnumerate(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) { + Parcel data, reply; + data.writeInterfaceToken(IFingerprintDaemonCallback::getInterfaceDescriptor()); + data.writeInt64(devId); + data.writeInt32(fpId); + data.writeInt32(gpId); + data.writeInt32(rem); + return remote()->transact(ON_ENUMERATE, data, &reply, IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(FingerprintDaemonCallback, + "android.hardware.fingerprint.IFingerprintDaemonCallback"); + +}; // namespace android diff --git a/biometrics/fingerprintd/IFingerprintDaemonCallback.h b/biometrics/fingerprintd/IFingerprintDaemonCallback.h new file mode 100644 index 0000000..2466d63 --- /dev/null +++ b/biometrics/fingerprintd/IFingerprintDaemonCallback.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef IFINGERPRINT_DAEMON_CALLBACK_H_ +#define IFINGERPRINT_DAEMON_CALLBACK_H_ + +#include +#include +#include +#include + +namespace android { + +/* +* Communication channel back to FingerprintService.java +*/ +class IFingerprintDaemonCallback : public IInterface { + public: + // must be kept in sync with IFingerprintService.aidl + enum { + ON_ENROLL_RESULT = IBinder::FIRST_CALL_TRANSACTION + 0, + ON_ACQUIRED = IBinder::FIRST_CALL_TRANSACTION + 1, + ON_AUTHENTICATED = IBinder::FIRST_CALL_TRANSACTION + 2, + ON_ERROR = IBinder::FIRST_CALL_TRANSACTION + 3, + ON_REMOVED = IBinder::FIRST_CALL_TRANSACTION + 4, + ON_ENUMERATE = IBinder::FIRST_CALL_TRANSACTION + 5, + }; + + virtual status_t onEnrollResult(int64_t devId, int32_t fpId, int32_t gpId, int32_t rem) = 0; + virtual status_t onAcquired(int64_t devId, int32_t acquiredInfo) = 0; + virtual status_t onAuthenticated(int64_t devId, int32_t fingerId, int32_t groupId) = 0; + virtual status_t onError(int64_t devId, int32_t error) = 0; + virtual status_t onRemoved(int64_t devId, int32_t fingerId, int32_t groupId) = 0; + virtual status_t onEnumerate(int64_t devId, int32_t fingerId, int32_t groupId, int32_t rem) = 0; + + DECLARE_META_INTERFACE(FingerprintDaemonCallback); +}; + +class BnFingerprintDaemonCallback: public BnInterface { + public: + virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // IFINGERPRINT_DAEMON_CALLBACK_H_ diff --git a/biometrics/fingerprintd/wrapper.cpp b/biometrics/fingerprintd/wrapper.cpp new file mode 100644 index 0000000..29d3218 --- /dev/null +++ b/biometrics/fingerprintd/wrapper.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2014 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_NDEBUG 0 +#define LOG_TAG "FingerprintHal" +#include +#include +#include +#include + +#include "FingerprintDaemonProxy.h" +#include "IFingerprintDaemon.h" +#include "IFingerprintDaemonCallback.h" +#include "FingerprintDaemonCallbackProxy.h" + +using namespace android; + +sp g_service = NULL; + +fingerprint_device_t* getWrapperService(); + +class BinderDiednotify: public IBinder::DeathRecipient { + public: + void binderDied(const wp __unused &who) { + ALOGE("binderDied"); + g_service = NULL; + } +}; + +static sp gDeathRecipient = new BinderDiednotify(); + +fingerprint_device_t* getWrapperService(fingerprint_notify_t notify) { + int64_t ret = 0; + do { + if (g_service == NULL) { + ALOGE("getService g_servie is NULL"); + + sp sm = defaultServiceManager(); + sp binder = sm->getService(android::FingerprintDaemonProxy::descriptor); + if (binder == NULL) { + ALOGE("getService failed"); + sleep(1); + continue; + } + g_service = interface_cast(binder); + binder->linkToDeath(gDeathRecipient, NULL, 0); + + if (g_service != NULL) { + ALOGE("getService succeed"); + sp callback = + new FingerprintDaemonCallbackProxy(); + FingerprintDaemonCallbackProxy::setDevice(notify); + g_service->init(callback); + + ret = g_service->openHal(); + if (ret == 0) { + ALOGE("getService openHal failed!"); + g_service = NULL; + } + } + } + } while (0); + + return reinterpret_cast(ret); +} diff --git a/biometrics/service.cpp b/biometrics/service.cpp new file mode 100644 index 0000000..8f0046c --- /dev/null +++ b/biometrics/service.cpp @@ -0,0 +1,68 @@ +/* + * 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.1-service.xiaomi_msm8937" + +#include +#include +#include +#include +#include +#include // for error codes + +#include +#include +#include +#include +#include + +#include "BiometricsFingerprint.h" +#include "fingerprintd/FingerprintDaemonProxy.h" + +using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint; +using android::hardware::biometrics::fingerprint::V2_1::implementation::BiometricsFingerprint; +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::sp; + +int main() { + ALOGE("Start fingerprintd"); + android::sp serviceManager = android::defaultServiceManager(); + android::sp proxy = + android::FingerprintDaemonProxy::getInstance(); + android::status_t ret = serviceManager->addService( + android::FingerprintDaemonProxy::descriptor, proxy); + if (ret != android::OK) { + ALOGE("Couldn't register " LOG_TAG " binder service!"); + return -1; + } + + ALOGE("Start biometrics"); + android::sp bio = BiometricsFingerprint::getInstance(); + configureRpcThreadpool(1, false /*callerWillJoin*/); + if (bio != nullptr) { + ret = bio->registerAsService(); + if (ret != android::OK) { + ALOGE("Cannot register BiometricsFingerprint service: %d", ret); + } + } else { + ALOGE("Can't create instance of BiometricsFingerprint, nullptr"); + } + + android::IPCThreadState::self()->joinThreadPool(); // run binder service fingerprintd part + + return 0; // should never get here +} diff --git a/product/fingerprint.mk b/product/fingerprint.mk index f48d6e5..bdbf932 100644 --- a/product/fingerprint.mk +++ b/product/fingerprint.mk @@ -1,6 +1,6 @@ # Fingerprint PRODUCT_PACKAGES += \ - fingerprintd + android.hardware.biometrics.fingerprint@2.1-service.xiaomi_msm8937 # Permissions PRODUCT_COPY_FILES += \ diff --git a/rootdir/init.qcom.rc b/rootdir/init.qcom.rc index 32a69e6..bf11c33 100644 --- a/rootdir/init.qcom.rc +++ b/rootdir/init.qcom.rc @@ -417,17 +417,14 @@ service gx_fpd /vendor/bin/gx_fpd on property:persist.sys.fp.vendor=switchf stop gx_fpd setprop persist.sys.fp.vendor searchf - start fingerprintd setprop ro.boot.fpsensor fpc + start fps_hal on property:persist.sys.fp.vendor=goodix + setprop persist.sys.fp.onstart 1 setprop ro.boot.fpsensor gdx - -on property:persist.sys.fp.onstart=1 - start fingerprintd - -on property:ro.boot.fpsensor=gdx setprop ro.hardware.fingerprint goodix + start fps_hal service time_daemon /vendor/bin/time_daemon class main diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts index d1a584e..24c764e 100644 --- a/sepolicy/file_contexts +++ b/sepolicy/file_contexts @@ -1,3 +1,6 @@ +# Biometric +/(vendor|system/vendor)/bin/hw/android\.hardware\.biometrics\.fingerprint@2\.1-service\.xiaomi_msm8937 u:object_r:hal_fingerprint_default_exec:s0 + # Block devices /dev/block/bootdevice/by-name/persist u:object_r:persist_block_device:s0 /dev/block/bootdevice/by-name/userdata u:object_r:userdata_block_device:s0