summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Altensen <info@stricted.net>2019-08-20 23:20:25 +0200
committerJan Altensen <info@stricted.net>2019-08-21 23:31:41 +0200
commit1813ff97bb1b896772654e271f0c3694ef6bcf79 (patch)
tree8b4bd402a2d6e11f363b73891f4c64aa8365574f
parentf267b8f90ebe956e3ac97bfd2ba90c8e82af916d (diff)
downloadandroid_hardware_samsung-1813ff97bb1b896772654e271f0c3694ef6bcf79.tar.gz
android_hardware_samsung-1813ff97bb1b896772654e271f0c3694ef6bcf79.tar.bz2
android_hardware_samsung-1813ff97bb1b896772654e271f0c3694ef6bcf79.zip
samsung: hidl: Add fingerprint 2.1 HAL
Change-Id: Ibd1b7fe7e1847ec28b2450fbf44cc740e5f364ef
-rw-r--r--hidl/fingerprint/.clang-format11
-rw-r--r--hidl/fingerprint/Android.mk45
-rw-r--r--hidl/fingerprint/BiometricsFingerprint.cpp361
-rw-r--r--hidl/fingerprint/BiometricsFingerprint.h97
-rw-r--r--hidl/fingerprint/android.hardware.biometrics.fingerprint@2.1-service.samsung.rc8
-rw-r--r--hidl/fingerprint/service.cpp51
6 files changed, 573 insertions, 0 deletions
diff --git a/hidl/fingerprint/.clang-format b/hidl/fingerprint/.clang-format
new file mode 100644
index 0000000..ae4a451
--- /dev/null
+++ b/hidl/fingerprint/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/hidl/fingerprint/Android.mk b/hidl/fingerprint/Android.mk
new file mode 100644
index 0000000..8f644b0
--- /dev/null
+++ b/hidl/fingerprint/Android.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2019 The LineageOS 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ BiometricsFingerprint.cpp \
+ service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ libhardware \
+ libhidlbase \
+ libhidltransport \
+ liblog \
+ libutils \
+ android.hardware.biometrics.fingerprint@2.1
+
+ifeq ($(TARGET_SEC_FP_USES_PERCENTAGE_SAMPLES),true)
+ LOCAL_CFLAGS += -DUSES_PERCENTAGE_SAMPLES
+endif
+
+LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.1-service.samsung
+LOCAL_INIT_RC := android.hardware.biometrics.fingerprint@2.1-service.samsung.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_OWNER := samsung
+LOCAL_VENDOR_MODULE := true
+
+include $(BUILD_EXECUTABLE)
diff --git a/hidl/fingerprint/BiometricsFingerprint.cpp b/hidl/fingerprint/BiometricsFingerprint.cpp
new file mode 100644
index 0000000..e8db272
--- /dev/null
+++ b/hidl/fingerprint/BiometricsFingerprint.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2019 The LineageOS 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.samsung"
+
+#include <android-base/logging.h>
+
+#include <hardware/hw_auth_token.h>
+
+#include <hardware/fingerprint.h>
+#include <hardware/hardware.h>
+#include "BiometricsFingerprint.h"
+
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+namespace android {
+namespace hardware {
+namespace biometrics {
+namespace fingerprint {
+namespace V2_1 {
+namespace implementation {
+
+using RequestStatus = android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
+
+BiometricsFingerprint* BiometricsFingerprint::sInstance = nullptr;
+
+BiometricsFingerprint::BiometricsFingerprint() : mClientCallback(nullptr) {
+ sInstance = this; // keep track of the most recent instance
+ if (!openHal()) {
+ LOG(ERROR) << "Can't open HAL module";
+ }
+}
+
+BiometricsFingerprint::~BiometricsFingerprint() {
+ if (ss_fingerprint_close() != 0) {
+ LOG(ERROR) << "Can't close HAL module";
+ }
+}
+
+Return<RequestStatus> 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:
+ LOG(ERROR) << "An unknown error returned from fingerprint vendor library: " << 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;
+ }
+ }
+ LOG(ERROR) << "Unknown error from fingerprint vendor library: " << 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;
+ }
+ }
+ LOG(ERROR) << "Unknown acquiredmsg from fingerprint vendor library: " << info;
+ return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
+}
+
+Return<uint64_t> BiometricsFingerprint::setNotify(
+ const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
+ std::lock_guard<std::mutex> 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<uint64_t>(this);
+}
+
+Return<uint64_t> BiometricsFingerprint::preEnroll() {
+ return ss_fingerprint_pre_enroll();
+}
+
+Return<RequestStatus> BiometricsFingerprint::enroll(const hidl_array<uint8_t, 69>& hat,
+ uint32_t gid, uint32_t timeoutSec) {
+ const hw_auth_token_t* authToken = reinterpret_cast<const hw_auth_token_t*>(hat.data());
+
+ return ErrorFilter(ss_fingerprint_enroll(authToken, gid, timeoutSec));
+}
+
+Return<RequestStatus> BiometricsFingerprint::postEnroll() {
+ return ErrorFilter(ss_fingerprint_post_enroll());
+}
+
+Return<uint64_t> BiometricsFingerprint::getAuthenticatorId() {
+ return ss_fingerprint_get_auth_id();
+}
+
+Return<RequestStatus> BiometricsFingerprint::cancel() {
+ return ErrorFilter(ss_fingerprint_cancel());
+}
+
+Return<RequestStatus> BiometricsFingerprint::enumerate() {
+ if (ss_fingerprint_enumerate != nullptr) {
+ return ErrorFilter(ss_fingerprint_enumerate());
+ }
+
+ return RequestStatus::SYS_UNKNOWN;
+}
+
+Return<RequestStatus> BiometricsFingerprint::remove(uint32_t gid, uint32_t fid) {
+ return ErrorFilter(ss_fingerprint_remove(gid, fid));
+}
+
+Return<RequestStatus> BiometricsFingerprint::setActiveGroup(uint32_t gid,
+ const hidl_string& storePath) {
+ if (storePath.size() >= PATH_MAX || storePath.size() <= 0) {
+ LOG(ERROR) << "Bad path length: " << storePath.size();
+ return RequestStatus::SYS_EINVAL;
+ }
+
+ if (access(storePath.c_str(), W_OK)) {
+ return RequestStatus::SYS_EINVAL;
+ }
+
+ return ErrorFilter(ss_fingerprint_set_active_group(gid, storePath.c_str()));
+}
+
+Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId, uint32_t gid) {
+ return ErrorFilter(ss_fingerprint_authenticate(operationId, gid));
+}
+
+IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
+ if (!sInstance) {
+ sInstance = new BiometricsFingerprint();
+ }
+ return sInstance;
+}
+
+bool BiometricsFingerprint::openHal() {
+ void* handle = dlopen("libbauthserver.so", RTLD_NOW);
+ if (handle) {
+ int err;
+
+ ss_fingerprint_close =
+ reinterpret_cast<typeof(ss_fingerprint_close)>(dlsym(handle, "ss_fingerprint_close"));
+ ss_fingerprint_open =
+ reinterpret_cast<typeof(ss_fingerprint_open)>(dlsym(handle, "ss_fingerprint_open"));
+
+ ss_set_notify_callback = reinterpret_cast<typeof(ss_set_notify_callback)>(
+ dlsym(handle, "ss_set_notify_callback"));
+ ss_fingerprint_pre_enroll = reinterpret_cast<typeof(ss_fingerprint_pre_enroll)>(
+ dlsym(handle, "ss_fingerprint_pre_enroll"));
+ ss_fingerprint_enroll =
+ reinterpret_cast<typeof(ss_fingerprint_enroll)>(dlsym(handle, "ss_fingerprint_enroll"));
+ ss_fingerprint_post_enroll = reinterpret_cast<typeof(ss_fingerprint_post_enroll)>(
+ dlsym(handle, "ss_fingerprint_post_enroll"));
+ ss_fingerprint_get_auth_id = reinterpret_cast<typeof(ss_fingerprint_get_auth_id)>(
+ dlsym(handle, "ss_fingerprint_get_auth_id"));
+ ss_fingerprint_cancel =
+ reinterpret_cast<typeof(ss_fingerprint_cancel)>(dlsym(handle, "ss_fingerprint_cancel"));
+ ss_fingerprint_enumerate = reinterpret_cast<typeof(ss_fingerprint_enumerate)>(
+ dlsym(handle, "ss_fingerprint_enumerate"));
+ ss_fingerprint_remove =
+ reinterpret_cast<typeof(ss_fingerprint_remove)>(dlsym(handle, "ss_fingerprint_remove"));
+ ss_fingerprint_set_active_group = reinterpret_cast<typeof(ss_fingerprint_set_active_group)>(
+ dlsym(handle, "ss_fingerprint_set_active_group"));
+ ss_fingerprint_authenticate = reinterpret_cast<typeof(ss_fingerprint_authenticate)>(
+ dlsym(handle, "ss_fingerprint_authenticate"));
+
+ if ((err = ss_fingerprint_open(nullptr)) != 0) {
+ LOG(ERROR) << "Can't open fingerprint, error: " << err;
+ return false;
+ }
+
+ if ((err = ss_set_notify_callback(BiometricsFingerprint::notify)) != 0) {
+ LOG(ERROR) << "Can't register fingerprint module callback, error: " << err;
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void BiometricsFingerprint::notify(const fingerprint_msg_t* msg) {
+ BiometricsFingerprint* thisPtr =
+ static_cast<BiometricsFingerprint*>(BiometricsFingerprint::getInstance());
+ std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
+ if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
+ LOG(ERROR) << "Receiving callbacks before the client callback is registered.";
+ return;
+ }
+ const uint64_t devId = 1;
+ switch (msg->type) {
+ case FINGERPRINT_ERROR: {
+ int32_t vendorCode = 0;
+ FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
+ LOG(DEBUG) << "onError(" << static_cast<int>(result) << ")";
+ if (!thisPtr->mClientCallback->onError(devId, result, vendorCode).isOk()) {
+ LOG(ERROR) << "failed to invoke fingerprint onError callback";
+ }
+ } break;
+ case FINGERPRINT_ACQUIRED: {
+ int32_t vendorCode = 0;
+ FingerprintAcquiredInfo result =
+ VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
+ LOG(DEBUG) << "onAcquired(" << static_cast<int>(result) << ")";
+ if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) {
+ LOG(ERROR) << "failed to invoke fingerprint onAcquired callback";
+ }
+ } break;
+ case FINGERPRINT_TEMPLATE_ENROLLING:
+ LOG(DEBUG) << "onEnrollResult(fid=" << msg->data.enroll.finger.fid
+ << ", gid=" << msg->data.enroll.finger.gid
+ << ", rem=" << 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()) {
+#ifdef USES_PERCENTAGE_SAMPLES
+ fingerprint_msg_t* newMsg = (fingerprint_msg_t*)msg;
+ newMsg->data.enroll.samples_remaining = 100 - msg->data.enroll.samples_remaining;
+ msg = newMsg;
+#endif
+ } else {
+ LOG(ERROR) << "failed to invoke fingerprint onEnrollResult callback";
+ }
+ break;
+ case FINGERPRINT_TEMPLATE_REMOVED:
+ LOG(DEBUG) << "onRemove(fid=" << msg->data.removed.finger.fid
+ << ", gid=" << msg->data.removed.finger.gid
+ << ", rem=" << 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()) {
+ LOG(ERROR) << "failed to invoke fingerprint onRemoved callback";
+ }
+ break;
+ case FINGERPRINT_AUTHENTICATED:
+ LOG(DEBUG) << "onAuthenticated(fid=" << msg->data.authenticated.finger.fid
+ << ", gid=" << msg->data.authenticated.finger.gid << ")";
+ if (msg->data.authenticated.finger.fid != 0) {
+ const uint8_t* hat = reinterpret_cast<const uint8_t*>(&msg->data.authenticated.hat);
+ const hidl_vec<uint8_t> token(
+ std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
+ if (!thisPtr->mClientCallback
+ ->onAuthenticated(devId, msg->data.authenticated.finger.fid,
+ msg->data.authenticated.finger.gid, token)
+ .isOk()) {
+ LOG(ERROR) << "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<uint8_t>())
+ .isOk()) {
+ LOG(ERROR) << "failed to invoke fingerprint onAuthenticated callback";
+ }
+ }
+ break;
+ case FINGERPRINT_TEMPLATE_ENUMERATING:
+ LOG(DEBUG) << "onEnumerate(fid=" << msg->data.enumerated.finger.fid
+ << ", gid=" << msg->data.enumerated.finger.gid
+ << ", rem=" << 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()) {
+ LOG(ERROR) << "failed to invoke fingerprint onEnumerate callback";
+ }
+ break;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace fingerprint
+} // namespace biometrics
+} // namespace hardware
+} // namespace android
diff --git a/hidl/fingerprint/BiometricsFingerprint.h b/hidl/fingerprint/BiometricsFingerprint.h
new file mode 100644
index 0000000..4848a33
--- /dev/null
+++ b/hidl/fingerprint/BiometricsFingerprint.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The LineageOS 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 <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
+#include <hardware/fingerprint.h>
+#include <hardware/hardware.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace biometrics {
+namespace fingerprint {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
+using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
+using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
+
+struct BiometricsFingerprint : public IBiometricsFingerprint {
+ BiometricsFingerprint();
+ ~BiometricsFingerprint();
+
+ // Method to wrap legacy HAL with BiometricsFingerprint class
+ static IBiometricsFingerprint* getInstance();
+
+ // Methods from ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint follow.
+ Return<uint64_t> setNotify(
+ const sp<IBiometricsFingerprintClientCallback>& clientCallback) override;
+ Return<uint64_t> preEnroll() override;
+ Return<RequestStatus> enroll(const hidl_array<uint8_t, 69>& hat, uint32_t gid,
+ uint32_t timeoutSec) override;
+ Return<RequestStatus> postEnroll() override;
+ Return<uint64_t> getAuthenticatorId() override;
+ Return<RequestStatus> cancel() override;
+ Return<RequestStatus> enumerate() override;
+ Return<RequestStatus> remove(uint32_t gid, uint32_t fid) override;
+ Return<RequestStatus> setActiveGroup(uint32_t gid, const hidl_string& storePath) override;
+ Return<RequestStatus> authenticate(uint64_t operationId, uint32_t gid) override;
+
+ private:
+ bool openHal();
+ static void notify(
+ const fingerprint_msg_t* msg); /* Static callback for legacy HAL implementation */
+ static Return<RequestStatus> 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;
+
+ std::mutex mClientCallbackMutex;
+ sp<IBiometricsFingerprintClientCallback> mClientCallback;
+
+ int (*ss_fingerprint_close)();
+ int (*ss_fingerprint_open)(const char* id);
+
+ int (*ss_set_notify_callback)(fingerprint_notify_t notify);
+ uint64_t (*ss_fingerprint_pre_enroll)();
+ int (*ss_fingerprint_enroll)(const hw_auth_token_t* hat, uint32_t gid, uint32_t timeout_sec);
+ int (*ss_fingerprint_post_enroll)();
+ uint64_t (*ss_fingerprint_get_auth_id)();
+ int (*ss_fingerprint_cancel)();
+ int (*ss_fingerprint_enumerate)();
+ int (*ss_fingerprint_remove)(uint32_t gid, uint32_t fid);
+ int (*ss_fingerprint_set_active_group)(uint32_t gid, const char* store_path);
+ int (*ss_fingerprint_authenticate)(uint64_t operation_id, uint32_t gid);
+};
+
+} // 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/hidl/fingerprint/android.hardware.biometrics.fingerprint@2.1-service.samsung.rc b/hidl/fingerprint/android.hardware.biometrics.fingerprint@2.1-service.samsung.rc
new file mode 100644
index 0000000..dbc3043
--- /dev/null
+++ b/hidl/fingerprint/android.hardware.biometrics.fingerprint@2.1-service.samsung.rc
@@ -0,0 +1,8 @@
+service vendor.fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service.samsung
+ # "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
+ writepid /dev/cpuset/system-background/tasks
diff --git a/hidl/fingerprint/service.cpp b/hidl/fingerprint/service.cpp
new file mode 100644
index 0000000..09d5111
--- /dev/null
+++ b/hidl/fingerprint/service.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 The LineageOS 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.samsung"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Errors.h>
+
+#include "BiometricsFingerprint.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
+using android::hardware::biometrics::fingerprint::V2_1::implementation::BiometricsFingerprint;
+
+using android::OK;
+using android::sp;
+
+int main() {
+ android::sp<IBiometricsFingerprint> bio = BiometricsFingerprint::getInstance();
+
+ configureRpcThreadpool(1, true);
+
+ if (bio == nullptr || bio->registerAsService() != OK) {
+ LOG(ERROR) << "Could not register service for Fingerprint HAL";
+ goto shutdown;
+ }
+
+ LOG(INFO) << "Fingerprint HAL service is Ready.";
+ joinRpcThreadpool();
+
+shutdown:
+ // In normal operation, we don't expect the thread pool to shutdown
+ LOG(ERROR) << "Fingerprint HAL failed to join thread pool.";
+ return 1;
+}