From 3f9ee454dce96bddd6ae27732ab7de09d44ac914 Mon Sep 17 00:00:00 2001 From: Pig Date: Mon, 18 May 2020 19:04:57 +0200 Subject: [PATCH] sm6150-common: fingerprint: Add Xiaomi fingerprintextension support * Import fingerprint.h from https://android.googlesource.com/platform/hardware/libhardware/+/d88dfe8607af019186a309674d9081a056ed3daa and add the xiaomi fingerprint extension command. Co-authored-by: C457 Change-Id: Ie9deb0dfcc689034cd3c4b9095e319130ba8d8cd --- fingerprint/Android.bp | 1 + fingerprint/BiometricsFingerprint.cpp | 5 +- fingerprint/BiometricsFingerprint.h | 12 +- fingerprint/fingerprint.h | 283 ++++++++++++++++++++++++++ fingerprint/service.cpp | 44 +++- 5 files changed, 335 insertions(+), 10 deletions(-) create mode 100644 fingerprint/fingerprint.h diff --git a/fingerprint/Android.bp b/fingerprint/Android.bp index 3147da0..90bbe7e 100644 --- a/fingerprint/Android.bp +++ b/fingerprint/Android.bp @@ -17,6 +17,7 @@ cc_binary { "libhardware", "libutils", "android.hardware.biometrics.fingerprint@2.1", + "vendor.xiaomi.hardware.fingerprintextension@1.0", ], } diff --git a/fingerprint/BiometricsFingerprint.cpp b/fingerprint/BiometricsFingerprint.cpp index ff7d9a1..318e8b2 100644 --- a/fingerprint/BiometricsFingerprint.cpp +++ b/fingerprint/BiometricsFingerprint.cpp @@ -20,7 +20,6 @@ #include #include -#include #include "BiometricsFingerprint.h" #include @@ -379,6 +378,10 @@ void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) { } } +Return BiometricsFingerprint::extCmd(int32_t cmd, int32_t param) { + return mDevice->extCmd(mDevice, cmd, param); +} + } // namespace implementation } // namespace V2_1 } // namespace fingerprint diff --git a/fingerprint/BiometricsFingerprint.h b/fingerprint/BiometricsFingerprint.h index 6d64e3d..b5bf399 100644 --- a/fingerprint/BiometricsFingerprint.h +++ b/fingerprint/BiometricsFingerprint.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2017 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. @@ -20,10 +21,12 @@ #include #include #include -#include #include #include #include +#include + +#include "fingerprint.h" namespace android { namespace hardware { @@ -41,11 +44,15 @@ using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; using ::android::sp; -struct BiometricsFingerprint : public IBiometricsFingerprint { +using ::vendor::xiaomi::hardware::fingerprintextension::V1_0::IXiaomiFingerprint; + +struct BiometricsFingerprint : public IBiometricsFingerprint, public IXiaomiFingerprint { public: BiometricsFingerprint(); ~BiometricsFingerprint(); + status_t registerAsSystemService(); + // Method to wrap legacy HAL with BiometricsFingerprint class static IBiometricsFingerprint* getInstance(); @@ -60,6 +67,7 @@ public: 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; + Return extCmd(int32_t cmd, int32_t param) override; private: static fingerprint_device_t* openHal(); diff --git a/fingerprint/fingerprint.h b/fingerprint/fingerprint.h new file mode 100644 index 0000000..47d953c --- /dev/null +++ b/fingerprint/fingerprint.h @@ -0,0 +1,283 @@ +/* + * 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); + + /** + * Call a Xiaomi fingerprint extension command. + */ + int (*extCmd)(struct fingerprint_device *dev, int32_t cmd, int32_t param); + + /* 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 4e4fd65..760d101 100644 --- a/fingerprint/service.cpp +++ b/fingerprint/service.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2017 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. @@ -29,17 +30,46 @@ using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; using android::sp; +using android::status_t; + +status_t BiometricsFingerprint::registerAsSystemService() { + status_t ret = 0; + + ret = IBiometricsFingerprint::registerAsService(); + if (ret != 0) { + ALOGE("Failed to register IBiometricsFingerprint (%d)", ret); + goto fail; + } else { + ALOGI("Successfully registered IBiometricsFingerprint"); + } + + ret = IXiaomiFingerprint::registerAsService(); + if (ret != 0) { + ALOGE("Failed to register IXiaomiFingerprint (%d)", ret); + goto fail; + } else { + ALOGI("Successfully registered IXiaomiFingerprint"); + } + +fail: + return ret; +} + int main() { - android::sp bio = BiometricsFingerprint::getInstance(); + android::sp service = nullptr; + + service = new BiometricsFingerprint(); + if (service == nullptr) { + ALOGE("Instance of BiometricsFingerprint is null"); + return 1; + } configureRpcThreadpool(1, true /*callerWillJoin*/); - if (bio != nullptr) { - if (::android::OK != bio->registerAsService()) { - return 1; - } - } else { - ALOGE("Can't create instance of BiometricsFingerprint, nullptr"); + status_t status = service->registerAsSystemService(); + if (status != android::OK) { + ALOGE("Cannot register service for Fingerprint HAL(%d).", status); + return 1; } joinRpcThreadpool();