From 57738613fb38bdedc9b0ea21d557307ef8e357f9 Mon Sep 17 00:00:00 2001 From: Pig Date: Mon, 18 May 2020 19:04:57 +0200 Subject: [PATCH] sm8350-common: fingerprint: Add xiaomi fingerprintextension support Co-authored-by: C457 Signed-off-by: Arian Change-Id: Ie9deb0dfcc689034cd3c4b9095e319130ba8d8cd --- Android.bp | 5 +- BoardConfigCommon.mk | 2 + common.mk | 3 +- fingerprint/Android.bp | 30 +- fingerprint/BiometricsFingerprint.cpp | 9 +- fingerprint/BiometricsFingerprint.h | 18 +- fingerprint/hardware/fingerprint.h | 285 ++++++++++++++++++ fingerprint/service.cpp | 22 +- ...aomi.hardware.fingerprintextension@1.0.xml | 11 + 9 files changed, 375 insertions(+), 10 deletions(-) create mode 100644 fingerprint/hardware/fingerprint.h create mode 100644 fingerprint/vendor.xiaomi.hardware.fingerprintextension@1.0.xml diff --git a/Android.bp b/Android.bp index dfecee0..2722586 100644 --- a/Android.bp +++ b/Android.bp @@ -1,3 +1,6 @@ soong_namespace { - imports: ["hardware/qcom-caf/bootctrl"], + imports: [ + "hardware/qcom-caf/bootctrl", + "hardware/xiaomi", + ], } diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk index 358bf97..cb16b99 100644 --- a/BoardConfigCommon.mk +++ b/BoardConfigCommon.mk @@ -183,7 +183,9 @@ BOARD_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/vendor # Soong SOONG_CONFIG_NAMESPACES += xiaomiSm8350Vars SOONG_CONFIG_xiaomiSm8350Vars += \ + fingerprint_use_extension \ vibrator_use_effect_stream +SOONG_CONFIG_xiaomiSm8350Vars_fingerprint_use_extension ?= false SOONG_CONFIG_xiaomiSm8350Vars_vibrator_use_effect_stream ?= false # Verified Boot diff --git a/common.mk b/common.mk index 573ca71..1882fe7 100644 --- a/common.mk +++ b/common.mk @@ -395,7 +395,8 @@ PRODUCT_COPY_FILES += \ # Soong namespaces PRODUCT_SOONG_NAMESPACES += \ - $(LOCAL_PATH) + $(LOCAL_PATH) \ + hardware/xiaomi # Telephony PRODUCT_PACKAGES += \ diff --git a/fingerprint/Android.bp b/fingerprint/Android.bp index 3cb39f1..a843932 100644 --- a/fingerprint/Android.bp +++ b/fingerprint/Android.bp @@ -1,6 +1,34 @@ +soong_config_module_type { + name: "fingerprint_extension", + module_type: "cc_defaults", + config_namespace: "xiaomiSm8350Vars", + bool_variables: ["fingerprint_use_extension"], + properties: [ + "cflags", + "shared_libs", + "vintf_fragments", + ], +} + +fingerprint_extension { + name: "fingerprint_extension_defaults", + soong_config_variables: { + fingerprint_use_extension: { + cflags: ["-DUSE_EXTENSION"], + shared_libs: [ + "vendor.xiaomi.hardware.fingerprintextension@1.0", + ], + vintf_fragments: ["vendor.xiaomi.hardware.fingerprintextension@1.0.xml"], + }, + }, +} + cc_binary { name: "android.hardware.biometrics.fingerprint@2.1-service.xiaomi_sm8350", - defaults: ["hidl_defaults"], + defaults: [ + "hidl_defaults", + "fingerprint_extension_defaults", + ], init_rc: ["android.hardware.biometrics.fingerprint@2.1-service.xiaomi_sm8350.rc"], vintf_fragments: ["android.hardware.biometrics.fingerprint@2.1-service.xiaomi_sm8350.xml"], vendor: true, diff --git a/fingerprint/BiometricsFingerprint.cpp b/fingerprint/BiometricsFingerprint.cpp index 1f85eae..329b2c2 100644 --- a/fingerprint/BiometricsFingerprint.cpp +++ b/fingerprint/BiometricsFingerprint.cpp @@ -19,7 +19,6 @@ #include #include -#include #include "BiometricsFingerprint.h" #include @@ -204,7 +203,13 @@ Return BiometricsFingerprint::authenticate(uint64_t operationId, return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid)); } -IBiometricsFingerprint* BiometricsFingerprint::getInstance() { +#ifdef USE_EXTENSION +Return BiometricsFingerprint::extCmd(int32_t cmd, int32_t param) { + return mDevice->extCmd(mDevice, cmd, param); +} +#endif + +BiometricsFingerprint* BiometricsFingerprint::getInstance() { if (!sInstance) { sInstance = new BiometricsFingerprint(); } diff --git a/fingerprint/BiometricsFingerprint.h b/fingerprint/BiometricsFingerprint.h index 6d64e3d..5cbd59a 100644 --- a/fingerprint/BiometricsFingerprint.h +++ b/fingerprint/BiometricsFingerprint.h @@ -20,10 +20,14 @@ #include #include #include -#include #include #include #include +#ifdef USE_EXTENSION +#include +#endif + +#include "hardware/fingerprint.h" namespace android { namespace hardware { @@ -40,14 +44,19 @@ using ::android::hardware::Void; using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; using ::android::sp; +#ifdef USE_EXTENSION +using ::vendor::xiaomi::hardware::fingerprintextension::V1_0::IXiaomiFingerprint; +struct BiometricsFingerprint : public IBiometricsFingerprint, public IXiaomiFingerprint { +#else struct BiometricsFingerprint : public IBiometricsFingerprint { +#endif public: BiometricsFingerprint(); ~BiometricsFingerprint(); // Method to wrap legacy HAL with BiometricsFingerprint class - static IBiometricsFingerprint* getInstance(); + static BiometricsFingerprint* getInstance(); // Methods from ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint follow. Return setNotify(const sp& clientCallback) override; @@ -61,6 +70,11 @@ public: Return setActiveGroup(uint32_t gid, const hidl_string& storePath) override; Return authenticate(uint64_t operationId, uint32_t gid) override; +#ifdef USE_EXTENSION + // Methods from ::vendor::xiaomi::hardware::fingerprintextension::V1_0::IXiaomiFingerprint follow. + Return extCmd(int32_t cmd, int32_t param) override; +#endif + private: static fingerprint_device_t* openHal(); static void notify(const fingerprint_msg_t *msg); /* Static callback for legacy HAL implementation */ diff --git a/fingerprint/hardware/fingerprint.h b/fingerprint/hardware/fingerprint.h new file mode 100644 index 0000000..233f4b5 --- /dev/null +++ b/fingerprint/hardware/fingerprint.h @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2020 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_INCLUDE_HARDWARE_FINGERPRINT_H +#define ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H + +#include +#include + +#define FINGERPRINT_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define FINGERPRINT_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0) +#define FINGERPRINT_MODULE_API_VERSION_2_1 HARDWARE_MODULE_API_VERSION(2, 1) +#define FINGERPRINT_MODULE_API_VERSION_3_0 HARDWARE_MODULE_API_VERSION(3, 0) +#define FINGERPRINT_HARDWARE_MODULE_ID "fingerprint" + +typedef enum fingerprint_msg_type { + FINGERPRINT_ERROR = -1, + FINGERPRINT_ACQUIRED = 1, + FINGERPRINT_TEMPLATE_ENROLLING = 3, + FINGERPRINT_TEMPLATE_REMOVED = 4, + FINGERPRINT_AUTHENTICATED = 5, + FINGERPRINT_TEMPLATE_ENUMERATING = 6, +} fingerprint_msg_type_t; + +/* + * Fingerprint errors are meant to tell the framework to terminate the current operation and ask + * for the user to correct the situation. These will almost always result in messaging and user + * interaction to correct the problem. + * + * For example, FINGERPRINT_ERROR_CANCELED should follow any acquisition message that results in + * a situation where the current operation can't continue without user interaction. For example, + * if the sensor is dirty during enrollment and no further enrollment progress can be made, + * send FINGERPRINT_ACQUIRED_IMAGER_DIRTY followed by FINGERPRINT_ERROR_CANCELED. + */ +typedef enum fingerprint_error { + FINGERPRINT_ERROR_HW_UNAVAILABLE = 1, /* The hardware has an error that can't be resolved. */ + FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2, /* Bad data; operation can't continue */ + FINGERPRINT_ERROR_TIMEOUT = 3, /* The operation has timed out waiting for user input. */ + FINGERPRINT_ERROR_NO_SPACE = 4, /* No space available to store a template */ + FINGERPRINT_ERROR_CANCELED = 5, /* The current operation can't proceed. See above. */ + FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6, /* fingerprint with given id can't be removed */ + FINGERPRINT_ERROR_LOCKOUT = 7, /* the fingerprint hardware is in lockout due to too many attempts */ + FINGERPRINT_ERROR_VENDOR_BASE = 1000 /* vendor-specific error messages start here */ +} fingerprint_error_t; + +/* + * Fingerprint acquisition info is meant as feedback for the current operation. Anything but + * FINGERPRINT_ACQUIRED_GOOD will be shown to the user as feedback on how to take action on the + * current operation. For example, FINGERPRINT_ACQUIRED_IMAGER_DIRTY can be used to tell the user + * to clean the sensor. If this will cause the current operation to fail, an additional + * FINGERPRINT_ERROR_CANCELED can be sent to stop the operation in progress (e.g. enrollment). + * In general, these messages will result in a "Try again" message. + */ +typedef enum fingerprint_acquired_info { + FINGERPRINT_ACQUIRED_GOOD = 0, + FINGERPRINT_ACQUIRED_PARTIAL = 1, /* sensor needs more data, i.e. longer swipe. */ + FINGERPRINT_ACQUIRED_INSUFFICIENT = 2, /* image doesn't contain enough detail for recognition*/ + FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3, /* sensor needs to be cleaned */ + FINGERPRINT_ACQUIRED_TOO_SLOW = 4, /* mostly swipe-type sensors; not enough data collected */ + FINGERPRINT_ACQUIRED_TOO_FAST = 5, /* for swipe and area sensors; tell user to slow down*/ + FINGERPRINT_ACQUIRED_DETECTED = 6, /* when the finger is first detected. Used to optimize wakeup. + Should be followed by one of the above messages */ + FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000 /* vendor-specific acquisition messages start here */ +} fingerprint_acquired_info_t; + +typedef struct fingerprint_finger_id { + uint32_t gid; + uint32_t fid; +} fingerprint_finger_id_t; + +typedef struct fingerprint_enroll { + fingerprint_finger_id_t finger; + /* samples_remaining goes from N (no data collected, but N scans needed) + * to 0 (no more data is needed to build a template). */ + uint32_t samples_remaining; + uint64_t msg; /* Vendor specific message. Used for user guidance */ +} fingerprint_enroll_t; + +typedef struct fingerprint_iterator { + fingerprint_finger_id_t finger; + uint32_t remaining_templates; +} fingerprint_iterator_t; + +typedef fingerprint_iterator_t fingerprint_enumerated_t; +typedef fingerprint_iterator_t fingerprint_removed_t; + +typedef struct fingerprint_acquired { + fingerprint_acquired_info_t acquired_info; /* information about the image */ +} fingerprint_acquired_t; + +typedef struct fingerprint_authenticated { + fingerprint_finger_id_t finger; + hw_auth_token_t hat; +} fingerprint_authenticated_t; + +typedef struct fingerprint_msg { + fingerprint_msg_type_t type; + union { + fingerprint_error_t error; + fingerprint_enroll_t enroll; + fingerprint_enumerated_t enumerated; + fingerprint_removed_t removed; + fingerprint_acquired_t acquired; + fingerprint_authenticated_t authenticated; + } data; +} fingerprint_msg_t; + +/* Callback function type */ +typedef void (*fingerprint_notify_t)(const fingerprint_msg_t *msg); + +/* Synchronous operation */ +typedef struct fingerprint_device { + /** + * Common methods of the fingerprint device. This *must* be the first member + * of fingerprint_device as users of this structure will cast a hw_device_t + * to fingerprint_device pointer in contexts where it's known + * the hw_device_t references a fingerprint_device. + */ + struct hw_device_t common; + + /* + * Client provided callback function to receive notifications. + * Do not set by hand, use the function above instead. + */ + fingerprint_notify_t notify; + + /* + * Set notification callback: + * Registers a user function that would receive notifications from the HAL + * The call will block if the HAL state machine is in busy state until HAL + * leaves the busy state. + * + * Function return: 0 if callback function is successfuly registered + * or a negative number in case of error, generally from the errno.h set. + */ + int (*set_notify)(struct fingerprint_device *dev, fingerprint_notify_t notify); + + /* + * Fingerprint pre-enroll enroll request: + * Generates a unique token to upper layers to indicate the start of an enrollment transaction. + * This token will be wrapped by security for verification and passed to enroll() for + * verification before enrollment will be allowed. This is to ensure adding a new fingerprint + * template was preceded by some kind of credential confirmation (e.g. device password). + * + * Function return: 0 if function failed + * otherwise, a uint64_t of token + */ + uint64_t (*pre_enroll)(struct fingerprint_device *dev); + + /* + * Fingerprint enroll request: + * Switches the HAL state machine to collect and store a new fingerprint + * template. Switches back as soon as enroll is complete + * (fingerprint_msg.type == FINGERPRINT_TEMPLATE_ENROLLING && + * fingerprint_msg.data.enroll.samples_remaining == 0) + * or after timeout_sec seconds. + * The fingerprint template will be assigned to the group gid. User has a choice + * to supply the gid or set it to 0 in which case a unique group id will be generated. + * + * Function return: 0 if enrollment process can be successfully started + * or a negative number in case of error, generally from the errno.h set. + * A notify() function may be called indicating the error condition. + */ + int (*enroll)(struct fingerprint_device *dev, const hw_auth_token_t *hat, + uint32_t gid, uint32_t timeout_sec); + + /* + * Finishes the enroll operation and invalidates the pre_enroll() generated challenge. + * This will be called at the end of a multi-finger enrollment session to indicate + * that no more fingers will be added. + * + * Function return: 0 if the request is accepted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*post_enroll)(struct fingerprint_device *dev); + + /* + * get_authenticator_id: + * Returns a token associated with the current fingerprint set. This value will + * change whenever a new fingerprint is enrolled, thus creating a new fingerprint + * set. + * + * Function return: current authenticator id or 0 if function failed. + */ + uint64_t (*get_authenticator_id)(struct fingerprint_device *dev); + + /* + * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED + * to all running clients. Switches the HAL state machine back to the idle state. + * Unlike enroll_done() doesn't invalidate the pre_enroll() challenge. + * + * Function return: 0 if cancel request is accepted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*cancel)(struct fingerprint_device *dev); + + /* + * Enumerate all the fingerprint templates found in the directory set by + * set_active_group() + * For each template found a notify() will be called with: + * fingerprint_msg.type == FINGERPRINT_TEMPLATE_ENUMERATED + * fingerprint_msg.data.enumerated.finger indicating a template id + * fingerprint_msg.data.enumerated.remaining_templates indicating how many more + * enumeration messages to expect. + * Note: If there are no fingerprints, then this should return 0 and the first fingerprint + * enumerated should have fingerid=0 and remaining=0 + * Function return: 0 if enumerate request is accepted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*enumerate)(struct fingerprint_device *dev); + + /* + * Fingerprint remove request: + * Deletes a fingerprint template. + * Works only within the path set by set_active_group(). + * The fid parameter can be used as a widcard: + * * fid == 0 -- delete all the templates in the group. + * * fid != 0 -- delete this specific template from the group. + * For each template found a notify() will be called with: + * fingerprint_msg.type == FINGERPRINT_TEMPLATE_REMOVED + * fingerprint_msg.data.removed.finger indicating a template id deleted + * fingerprint_msg.data.removed.remaining_templates indicating how many more + * templates will be deleted by this operation. + * + * Function return: 0 if fingerprint template(s) can be successfully deleted + * or a negative number in case of error, generally from the errno.h set. + */ + int (*remove)(struct fingerprint_device *dev, uint32_t gid, uint32_t fid); + + /* + * Restricts the HAL operation to a set of fingerprints belonging to a + * group provided. + * The caller must provide a path to a storage location within the user's + * data directory. + * + * Function return: 0 on success + * or a negative number in case of error, generally from the errno.h set. + */ + int (*set_active_group)(struct fingerprint_device *dev, uint32_t gid, + const char *store_path); + + /* + * Authenticates an operation identifed by operation_id + * + * Function return: 0 on success + * or a negative number in case of error, generally from the errno.h set. + */ + int (*authenticate)(struct fingerprint_device *dev, uint64_t operation_id, uint32_t gid); + +#ifdef USE_EXTENSION + /* + * Xiaomi fingerprint extension command. + */ + int (*extCmd)(struct fingerprint_device *dev, int32_t cmd, int32_t param); +#endif + + /* Reserved for backward binary compatibility */ + void *reserved[4]; +} fingerprint_device_t; + +typedef struct fingerprint_module { + /** + * Common methods of the fingerprint module. This *must* be the first member + * of fingerprint_module as users of this structure will cast a hw_module_t + * to fingerprint_module pointer in contexts where it's known + * the hw_module_t references a fingerprint_module. + */ + struct hw_module_t common; +} fingerprint_module_t; + +#endif /* ANDROID_INCLUDE_HARDWARE_FINGERPRINT_H */ diff --git a/fingerprint/service.cpp b/fingerprint/service.cpp index 77d1d87..30aa9e3 100644 --- a/fingerprint/service.cpp +++ b/fingerprint/service.cpp @@ -28,20 +28,36 @@ using android::hardware::biometrics::fingerprint::V2_1::implementation::Biometri using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::sp; +#ifdef USE_EXTENSION +using vendor::xiaomi::hardware::fingerprintextension::V1_0::IXiaomiFingerprint; +#endif int main() { - android::sp bio = BiometricsFingerprint::getInstance(); + android::sp biometricsFingerprint = BiometricsFingerprint::getInstance(); +#ifdef USE_EXTENSION + android::sp xiaomiFingerprint = BiometricsFingerprint::getInstance(); +#endif configureRpcThreadpool(1, true /*callerWillJoin*/); - if (bio != nullptr) { - if (::android::OK != bio->registerAsService()) { + if (biometricsFingerprint != nullptr) { + if (::android::OK != biometricsFingerprint->registerAsService()) { return 1; } } else { ALOGE("Can't create instance of BiometricsFingerprint, nullptr"); } +#ifdef USE_EXTENSION + if (xiaomiFingerprint != nullptr) { + if (::android::OK != xiaomiFingerprint->registerAsService()) { + return 1; + } + } else { + ALOGE("Can't create instance of XiaomiFingerprint, nullptr"); + } +#endif + joinRpcThreadpool(); return 0; // should never get here diff --git a/fingerprint/vendor.xiaomi.hardware.fingerprintextension@1.0.xml b/fingerprint/vendor.xiaomi.hardware.fingerprintextension@1.0.xml new file mode 100644 index 0000000..9f93e0a --- /dev/null +++ b/fingerprint/vendor.xiaomi.hardware.fingerprintextension@1.0.xml @@ -0,0 +1,11 @@ + + + vendor.xiaomi.hardware.fingerprintextension + hwbinder + 1.0 + + IXiaomiFingerprint + default + + +