diff --git a/aidl/fingerprint/Android.bp b/aidl/fingerprint/Android.bp index 8bb8efd4..e67e23a0 100644 --- a/aidl/fingerprint/Android.bp +++ b/aidl/fingerprint/Android.bp @@ -10,17 +10,28 @@ cc_binary { init_rc: ["android.hardware.biometrics.fingerprint-service.samsung.rc"], vintf_fragments: ["android.hardware.biometrics.fingerprint-service.samsung.xml"], srcs: [ + "CancellationSignal.cpp", "Fingerprint.cpp", + "LegacyHAL.cpp", + "LockoutTracker.cpp", "Session.cpp", "service.cpp", ], shared_libs: [ "libbase", "libbinder_ndk", + "libhardware", "android.hardware.biometrics.fingerprint-V3-ndk", "android.hardware.biometrics.common-V3-ndk", - "android.hardware.biometrics.common.thread", "android.hardware.biometrics.common.util", ], + static_libs: ["libandroid.hardware.biometrics.fingerprint.SamsungProps"], + vendor: true, +} + +sysprop_library { + name: "android.hardware.biometrics.fingerprint.SamsungProps", + srcs: ["fingerprint.sysprop"], + property_owner: "Vendor", vendor: true, } diff --git a/aidl/fingerprint/CancellationSignal.cpp b/aidl/fingerprint/CancellationSignal.cpp new file mode 100644 index 00000000..4f49b44a --- /dev/null +++ b/aidl/fingerprint/CancellationSignal.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CancellationSignal.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +CancellationSignal::CancellationSignal(Session* session) + : mSession(session) { +} + +ndk::ScopedAStatus CancellationSignal::cancel() { + return mSession->cancel(); +} + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/CancellationSignal.h b/aidl/fingerprint/CancellationSignal.h new file mode 100644 index 00000000..737dd3ac --- /dev/null +++ b/aidl/fingerprint/CancellationSignal.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "Session.h" + +using ::aidl::android::hardware::biometrics::common::BnCancellationSignal; + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +class CancellationSignal : public BnCancellationSignal { +public: + CancellationSignal(Session* session); + ndk::ScopedAStatus cancel() override; + +private: + Session* mSession; +}; + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/Fingerprint.cpp b/aidl/fingerprint/Fingerprint.cpp index 2e2d660f..4ca160da 100644 --- a/aidl/fingerprint/Fingerprint.cpp +++ b/aidl/fingerprint/Fingerprint.cpp @@ -5,21 +5,219 @@ */ #include "Fingerprint.h" +#include "VendorConstants.h" + +#include + +#include +#include +#include + +#include +#include + +using namespace ::android::fingerprint::samsung; + +using ::android::base::ParseInt; +using ::android::base::Split; namespace aidl { namespace android { namespace hardware { namespace biometrics { namespace fingerprint { +namespace { +constexpr int SENSOR_ID = 0; +constexpr common::SensorStrength SENSOR_STRENGTH = common::SensorStrength::STRONG; +constexpr int MAX_ENROLLMENTS_PER_USER = 4; +constexpr bool SUPPORTS_NAVIGATION_GESTURES = false; +constexpr char HW_COMPONENT_ID[] = "fingerprintSensor"; +constexpr char HW_VERSION[] = "vendor/model/revision"; +constexpr char FW_VERSION[] = "1.01"; +constexpr char SERIAL_NUMBER[] = "00000001"; +constexpr char SW_COMPONENT_ID[] = "matchingAlgorithm"; +constexpr char SW_VERSION[] = "vendor/version/revision"; +} + +static Fingerprint* sInstance; + +Fingerprint::Fingerprint() { + sInstance = this; // keep track of the most recent instance + if (!mHal.openHal(Fingerprint::notify)) { + LOG(ERROR) << "Can't open HAL module"; + } + + std::string sensorTypeProp = FingerprintHalProperties::type().value_or(""); + if (sensorTypeProp == "" || sensorTypeProp == "default" || sensorTypeProp == "rear") + mSensorType = FingerprintSensorType::REAR; + else if (sensorTypeProp == "udfps") + mSensorType = FingerprintSensorType::UNDER_DISPLAY_ULTRASONIC; + else if (sensorTypeProp == "udfps_optical") + mSensorType = FingerprintSensorType::UNDER_DISPLAY_OPTICAL; + else if (sensorTypeProp == "side") + mSensorType = FingerprintSensorType::POWER_BUTTON; + else if (sensorTypeProp == "home") + mSensorType = FingerprintSensorType::HOME_BUTTON; + else + mSensorType = FingerprintSensorType::UNKNOWN; + + mMaxEnrollmentsPerUser = + FingerprintHalProperties::max_enrollments_per_user().value_or(MAX_ENROLLMENTS_PER_USER); + mSupportsGestures = + FingerprintHalProperties::supports_gestures().value_or(SUPPORTS_NAVIGATION_GESTURES); -ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + if (mSupportsGestures) { + mHal.request(FINGERPRINT_REQUEST_NAVIGATION_MODE_START, 1); + + uinputFd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinputFd < 0) { + LOG(ERROR) << "Unable to open uinput node"; + goto skip_uinput_setup; + } + + int err = ioctl(uinputFd, UI_SET_EVBIT, EV_KEY) | + ioctl(uinputFd, UI_SET_KEYBIT, KEY_UP) | + ioctl(uinputFd, UI_SET_KEYBIT, KEY_DOWN); + if (err != 0) { + LOG(ERROR) << "Unable to enable key events"; + goto skip_uinput_setup; + } + + struct uinput_user_dev uidev; + sprintf(uidev.name, "uinput-sec-fp"); + uidev.id.bustype = BUS_VIRTUAL; + + err = write(uinputFd, &uidev, sizeof(uidev)); + if (err < 0) { + LOG(ERROR) << "Write user device to uinput node failed"; + goto skip_uinput_setup; + } + + err = ioctl(uinputFd, UI_DEV_CREATE); + if (err < 0) { + LOG(ERROR) << "Unable to create uinput device"; + goto skip_uinput_setup; + } + + LOG(INFO) << "Successfully registered uinput-sec-fp for fingerprint gestures"; + } +skip_uinput_setup: + return; } -ndk::ScopedAStatus Fingerprint::createSession(int32_t /*sensorId*/, int32_t /*userId*/, - const std::shared_ptr& /*cb*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector* out) { + std::vector componentInfo = { + {HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */}, + {SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */, + "" /* serialNumber */, SW_VERSION}}; + common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, + mMaxEnrollmentsPerUser, componentInfo}; + + SensorLocation sensorLocation; + std::string loc = FingerprintHalProperties::sensor_location().value_or(""); + std::vector dim = Split(loc, "|"); + if (dim.size() >= 3 && dim.size() <= 4) { + ParseInt(dim[0], &sensorLocation.sensorLocationX); + ParseInt(dim[1], &sensorLocation.sensorLocationY); + ParseInt(dim[2], &sensorLocation.sensorRadius); + + if (dim.size() >= 4) + sensorLocation.display = dim[3]; + } else if(loc.length() > 0) { + LOG(WARNING) << "Invalid sensor location input (x|y|radius|display): " << loc; + } + + LOG(INFO) << "Sensor type: " << ::android::internal::ToString(mSensorType) + << " location: " << sensorLocation.toString(); + + *out = {{commonProps, + mSensorType, + {sensorLocation}, + mSupportsGestures, + false, + false, + false, + std::nullopt}}; + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Fingerprint::createSession(int32_t /*sensorId*/, int32_t userId, + const std::shared_ptr& cb, + std::shared_ptr* out) { + CHECK(mSession == nullptr || mSession->isClosed()) << "Open session already exists!"; + + mSession = SharedRefBase::make(mHal, userId, cb, mLockoutTracker); + *out = mSession; + + mSession->linkToDeath(cb->asBinder().get()); + + return ndk::ScopedAStatus::ok(); +} + +void Fingerprint::notify(const fingerprint_msg_t* msg) { + Fingerprint* thisPtr = sInstance; + if (msg->type == FINGERPRINT_ACQUIRED + && msg->data.acquired.acquired_info > SEM_FINGERPRINT_EVENT_BASE) { + thisPtr->handleEvent(msg->data.acquired.acquired_info); + return; + } + + if (thisPtr->mSession == nullptr || thisPtr->mSession->isClosed()) { + LOG(ERROR) << "Receiving callbacks before a session is opened."; + return; + } + + thisPtr->mSession->notify(msg); +} + +void Fingerprint::handleEvent(int eventCode) { + switch (eventCode) { + case SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_DOWN: + case SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP: + if (!mSupportsGestures) return; + + struct input_event event {}; + int keycode = eventCode == SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP ? + KEY_UP : KEY_DOWN; + + // Report the key + event.type = EV_KEY; + event.code = keycode; + event.value = 1; + if (write(uinputFd, &event, sizeof(event)) < 0) { + LOG(ERROR) << "Write EV_KEY to uinput node failed"; + return; + } + + // Force a flush with an EV_SYN + event.type = EV_SYN; + event.code = SYN_REPORT; + event.value = 0; + if (write(uinputFd, &event, sizeof(event)) < 0) { + LOG(ERROR) << "Write EV_SYN to uinput node failed"; + return; + } + + // Report the key + event.type = EV_KEY; + event.code = keycode; + event.value = 0; + if (write(uinputFd, &event, sizeof(event)) < 0) { + LOG(ERROR) << "Write EV_KEY to uinput node failed"; + return; + } + + // Force a flush with an EV_SYN + event.type = EV_SYN; + event.code = SYN_REPORT; + event.value = 0; + if (write(uinputFd, &event, sizeof(event)) < 0) { + LOG(ERROR) << "Write EV_SYN to uinput node failed"; + return; + } + break; + } } } // namespace fingerprint diff --git a/aidl/fingerprint/Fingerprint.h b/aidl/fingerprint/Fingerprint.h index f4655d7a..09281926 100644 --- a/aidl/fingerprint/Fingerprint.h +++ b/aidl/fingerprint/Fingerprint.h @@ -8,6 +8,10 @@ #include +#include "LegacyHAL.h" +#include "LockoutTracker.h" +#include "Session.h" + using ::aidl::android::hardware::biometrics::fingerprint::ISession; using ::aidl::android::hardware::biometrics::fingerprint::ISessionCallback; using ::aidl::android::hardware::biometrics::fingerprint::SensorProps; @@ -20,10 +24,25 @@ namespace fingerprint { class Fingerprint : public BnFingerprint { public: + Fingerprint(); ndk::ScopedAStatus getSensorProps(std::vector* _aidl_return) override; ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId, const std::shared_ptr& cb, std::shared_ptr* out) override; + +private: + static void notify( + const fingerprint_msg_t* msg); /* Static callback for legacy HAL implementation */ + void handleEvent(int eventCode); + + LegacyHAL mHal; + LockoutTracker mLockoutTracker; + FingerprintSensorType mSensorType; + int mMaxEnrollmentsPerUser; + bool mSupportsGestures; + int uinputFd; + + std::shared_ptr mSession; }; } // namespace fingerprint diff --git a/aidl/fingerprint/Legacy2Aidl.h b/aidl/fingerprint/Legacy2Aidl.h new file mode 100644 index 00000000..939e02eb --- /dev/null +++ b/aidl/fingerprint/Legacy2Aidl.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include + +#include + +using aidl::android::hardware::keymaster::HardwareAuthToken; + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +inline void translate(const HardwareAuthToken& authToken, hw_auth_token_t& hat) { + hat.challenge = authToken.challenge; + hat.user_id = authToken.userId; + hat.authenticator_id = authToken.authenticatorId; + // these are in host order: translate to network order + hat.authenticator_type = htobe32(static_cast(authToken.authenticatorType)); + hat.timestamp = htobe64(authToken.timestamp.milliSeconds); + std::copy(authToken.mac.begin(), authToken.mac.end(), hat.hmac); +} + +inline void translate(const hw_auth_token_t& hat, HardwareAuthToken& authToken) { + authToken.challenge = hat.challenge; + authToken.userId = hat.user_id; + authToken.authenticatorId = hat.authenticator_id; + // these are in network order: translate to host + authToken.authenticatorType = + static_cast( + be32toh(hat.authenticator_type)); + authToken.timestamp.milliSeconds = be64toh(hat.timestamp); + authToken.mac.insert(authToken.mac.begin(), std::begin(hat.hmac), + std::end(hat.hmac)); +} + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/LegacyHAL.cpp b/aidl/fingerprint/LegacyHAL.cpp new file mode 100644 index 00000000..54f5a358 --- /dev/null +++ b/aidl/fingerprint/LegacyHAL.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "Fingerprint.h" + +#include + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +bool LegacyHAL::openHal(fingerprint_notify_t notify) { + void* handle = dlopen("libbauthserver.so", RTLD_NOW); + if (handle) { + int err; + + ss_fingerprint_close = + reinterpret_cast(dlsym(handle, "ss_fingerprint_close")); + ss_fingerprint_open = + reinterpret_cast(dlsym(handle, "ss_fingerprint_open")); + + ss_set_notify_callback = reinterpret_cast( + dlsym(handle, "ss_set_notify_callback")); + ss_fingerprint_pre_enroll = reinterpret_cast( + dlsym(handle, "ss_fingerprint_pre_enroll")); + ss_fingerprint_enroll = + reinterpret_cast(dlsym(handle, "ss_fingerprint_enroll")); + ss_fingerprint_post_enroll = reinterpret_cast( + dlsym(handle, "ss_fingerprint_post_enroll")); + ss_fingerprint_get_auth_id = reinterpret_cast( + dlsym(handle, "ss_fingerprint_get_auth_id")); + ss_fingerprint_cancel = + reinterpret_cast(dlsym(handle, "ss_fingerprint_cancel")); + ss_fingerprint_enumerate = reinterpret_cast( + dlsym(handle, "ss_fingerprint_enumerate")); + ss_fingerprint_remove = + reinterpret_cast(dlsym(handle, "ss_fingerprint_remove")); + ss_fingerprint_set_active_group = reinterpret_cast( + dlsym(handle, "ss_fingerprint_set_active_group")); + ss_fingerprint_authenticate = reinterpret_cast( + dlsym(handle, "ss_fingerprint_authenticate")); + ss_fingerprint_request = reinterpret_cast( + dlsym(handle, "ss_fingerprint_request")); + + if ((err = ss_fingerprint_open(nullptr)) != 0) { + LOG(ERROR) << "Can't open fingerprint, error: " << err; + return false; + } + + if ((err = ss_set_notify_callback(notify)) != 0) { + LOG(ERROR) << "Can't register fingerprint module callback, error: " << err; + return false; + } + + return true; + } + + return false; +} + +int LegacyHAL::request(int cmd, int param) { + // TO-DO: input, output handling not implemented + int result = ss_fingerprint_request(cmd, nullptr, 0, nullptr, 0, param); + LOG(INFO) << "request(cmd=" << cmd << ", param=" << param << ", result=" << result << ")"; + return result; +} + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/LegacyHAL.h b/aidl/fingerprint/LegacyHAL.h new file mode 100644 index 00000000..023a8737 --- /dev/null +++ b/aidl/fingerprint/LegacyHAL.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +class LegacyHAL { +public: + bool openHal(fingerprint_notify_t notify); + int request(int cmd, int param); + + 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); + int (*ss_fingerprint_request)(uint32_t cmd, char *inBuf, uint32_t inBuf_length, char *outBuf, uint32_t outBuf_length, uint32_t param); +}; + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/LockoutTracker.cpp b/aidl/fingerprint/LockoutTracker.cpp new file mode 100644 index 00000000..7baa6fd3 --- /dev/null +++ b/aidl/fingerprint/LockoutTracker.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "Fingerprint.h" +#include "LockoutTracker.h" + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +void LockoutTracker::reset(bool clearAttemptCounter) { + if (clearAttemptCounter) + mFailedCount = 0; + mLockoutTimedStart = 0; + mCurrentMode = LockoutMode::NONE; +} + +void LockoutTracker::addFailedAttempt() { + mFailedCount++; + + if (mFailedCount >= LOCKOUT_PERMANENT_THRESHOLD) + mCurrentMode = LockoutMode::PERMANENT; + else if (mFailedCount >= LOCKOUT_TIMED_THRESHOLD) { + mCurrentMode = LockoutMode::TIMED; + mLockoutTimedStart = Util::getSystemNanoTime(); + } +} + +LockoutMode LockoutTracker::getMode() { + if (mCurrentMode == LockoutMode::TIMED) { + if (Util::hasElapsed(mLockoutTimedStart, LOCKOUT_TIMED_DURATION)) { + mCurrentMode = LockoutMode::NONE; + mLockoutTimedStart = 0; + } + } + + return mCurrentMode; +} + +int64_t LockoutTracker::getLockoutTimeLeft() { + int64_t res = 0; + + if (mLockoutTimedStart > 0) { + auto now = Util::getSystemNanoTime(); + auto elapsed = (now - mLockoutTimedStart) / 1000000LL; + res = LOCKOUT_TIMED_DURATION - elapsed; + } + + return res; +} + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/LockoutTracker.h b/aidl/fingerprint/LockoutTracker.h new file mode 100644 index 00000000..4e529d28 --- /dev/null +++ b/aidl/fingerprint/LockoutTracker.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +namespace aidl { +namespace android { +namespace hardware { +namespace biometrics { +namespace fingerprint { + +#define LOCKOUT_TIMED_THRESHOLD 5 +#define LOCKOUT_TIMED_DURATION 30 * 1000 +#define LOCKOUT_PERMANENT_THRESHOLD 20 + +enum class LockoutMode { + NONE, + TIMED, + PERMANENT +}; + +class LockoutTracker { +public: + void reset(bool clearAttemptCounter); + LockoutMode getMode(); + void addFailedAttempt(); + int64_t getLockoutTimeLeft(); + +private: + int32_t mFailedCount = 0; + int64_t mLockoutTimedStart; + LockoutMode mCurrentMode; +}; + +} // namespace fingerprint +} // namespace biometrics +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/fingerprint/Session.cpp b/aidl/fingerprint/Session.cpp index 3a1d9190..6f650463 100644 --- a/aidl/fingerprint/Session.cpp +++ b/aidl/fingerprint/Session.cpp @@ -4,7 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "CancellationSignal.h" +#include "Legacy2Aidl.h" #include "Session.h" +#include "VendorConstants.h" + +#include + +#include + +#include +#include + +using namespace ::android::fingerprint::samsung; namespace aidl { namespace android { @@ -12,100 +24,399 @@ namespace hardware { namespace biometrics { namespace fingerprint { +void onClientDeath(void* cookie) { + LOG(INFO) << "FingerprintService has died"; + Session* session = static_cast(cookie); + if (session && !session->isClosed()) { + session->close(); + } +} + +Session::Session(LegacyHAL hal, int userId, std::shared_ptr cb, + LockoutTracker lockoutTracker) + : mHal(hal), + mLockoutTracker(lockoutTracker), + mUserId(userId), + mCb(cb) { + mDeathRecipient = AIBinder_DeathRecipient_new(onClientDeath); + + char filename[64]; + snprintf(filename, sizeof(filename), "/data/vendor_de/%d/fpdata/"); + mHal.ss_fingerprint_set_active_group(userId, &filename[0]); +} + ndk::ScopedAStatus Session::generateChallenge() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "generateChallenge"; + + uint64_t challenge = mHal.ss_fingerprint_pre_enroll(); + mCb->onChallengeGenerated(challenge); + + return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Session::revokeChallenge(int64_t /*challenge*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::revokeChallenge(int64_t challenge) { + LOG(INFO) << "revokeChallenge"; + + mHal.ss_fingerprint_post_enroll(); + mCb->onChallengeRevoked(challenge); + + return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Session::enroll(const HardwareAuthToken& /*hat*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::enroll(const HardwareAuthToken& hat, + std::shared_ptr* out) { + LOG(INFO) << "enroll"; + + if (FingerprintHalProperties::force_calibrate().value_or(false)) { + mHal.request(SEM_REQUEST_FORCE_CBGE, 1); + } + + hw_auth_token_t authToken; + translate(hat, authToken); + + int32_t error = mHal.ss_fingerprint_enroll(&authToken, mUserId, 0 /* timeoutSec */); + if (error) { + LOG(ERROR) << "ss_fingerprint_enroll failed: " << error; + mCb->onError(Error::UNABLE_TO_PROCESS, error); + } + + *out = SharedRefBase::make(this); + return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Session::authenticate(int64_t /*operationId*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::authenticate(int64_t operationId, + std::shared_ptr* out) { + LOG(INFO) << "authenticate"; + + int32_t error = mHal.ss_fingerprint_authenticate(operationId, mUserId); + if (error) { + LOG(ERROR) << "ss_fingerprint_authenticate failed: " << error; + mCb->onError(Error::UNABLE_TO_PROCESS, error); + } + + *out = SharedRefBase::make(this); + return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr* out) { + LOG(INFO) << "detectInteraction"; + + LOG(DEBUG) << "Detect interaction is not supported"; + mCb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */); + + *out = SharedRefBase::make(this); + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::enumerateEnrollments() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "enumerateEnrollments"; + + int32_t error = mHal.ss_fingerprint_enumerate(); + if (error) + LOG(ERROR) << "ss_fingerprint_enumerate failed: " << error; + + return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Session::removeEnrollments(const std::vector& /*enrollmentIds*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::removeEnrollments(const std::vector& enrollmentIds) { + LOG(INFO) << "removeEnrollments, size: " << enrollmentIds.size(); + + for (int32_t enrollment : enrollmentIds) { + int32_t error = mHal.ss_fingerprint_remove(mUserId, enrollment); + if (error) + LOG(ERROR) << "ss_fingerprint_remove failed: " << error; + } + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::getAuthenticatorId() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "getAuthenticatorId"; + + mCb->onAuthenticatorIdRetrieved(mHal.ss_fingerprint_get_auth_id()); + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::invalidateAuthenticatorId() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "invalidateAuthenticatorId"; + + mCb->onAuthenticatorIdInvalidated(mHal.ss_fingerprint_get_auth_id()); + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::resetLockout(const HardwareAuthToken& /*hat*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "resetLockout"; + + clearLockout(true); + mIsLockoutTimerAborted = true; + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::close() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "close"; + mClosed = true; + mCb->onSessionClosed(); + AIBinder_DeathRecipient_delete(mDeathRecipient); + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::onPointerDown(int32_t /*pointerId*/, int32_t /*x*/, int32_t /*y*/, float /*minor*/, float /*major*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "onPointerDown"; + + if (FingerprintHalProperties::request_touch_event().value_or(false)) { + mHal.request(SEM_REQUEST_TOUCH_EVENT, 2); + } + checkSensorLockout(); + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::onPointerUp(int32_t /*pointerId*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "onPointerUp"; + + if (FingerprintHalProperties::request_touch_event().value_or(false)) { + mHal.request(SEM_REQUEST_TOUCH_EVENT, 1); + } + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::onUiReady() { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + LOG(INFO) << "onUiReady"; + + // TODO: stub + + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::authenticateWithContext( - int64_t /*operationId*/, const OperationContext& /*context*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + int64_t operationId, const OperationContext& /*context*/, + std::shared_ptr* out) { + return authenticate(operationId, out); } -ndk::ScopedAStatus Session::enrollWithContext(const HardwareAuthToken& /*hat*/, +ndk::ScopedAStatus Session::enrollWithContext(const HardwareAuthToken& hat, const OperationContext& /*context*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + std::shared_ptr* out) { + return enroll(hat, out); } ndk::ScopedAStatus Session::detectInteractionWithContext(const OperationContext& /*context*/, - std::shared_ptr* /*out*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + std::shared_ptr* out) { + return detectInteraction(out); } -ndk::ScopedAStatus Session::onPointerDownWithContext(const PointerContext& /*context*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::onPointerDownWithContext(const PointerContext& context) { + return onPointerDown(context.pointerId, context.x, context.y, context.minor, context.major); } -ndk::ScopedAStatus Session::onPointerUpWithContext(const PointerContext& /*context*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +ndk::ScopedAStatus Session::onPointerUpWithContext(const PointerContext& context) { + return onPointerUp(context.pointerId); } ndk::ScopedAStatus Session::onContextChanged(const OperationContext& /*context*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::onPointerCancelWithContext(const PointerContext& /*context*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Session::setIgnoreDisplayTouches(bool /*shouldIgnore*/) { - return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Session::cancel() { + int32_t ret = mHal.ss_fingerprint_cancel(); + + if (ret == 0) { + mCb->onError(Error::CANCELED, 0 /* vendorCode */); + + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromServiceSpecificError(ret); + } +} + +binder_status_t Session::linkToDeath(AIBinder* binder) { + return AIBinder_linkToDeath(binder, mDeathRecipient, this); +} + +bool Session::isClosed() { + return mClosed; +} + +// Translate from errors returned by traditional HAL (see fingerprint.h) to +// AIDL-compliant Error +Error Session::VendorErrorFilter(int32_t error, int32_t* vendorCode) { + *vendorCode = 0; + + switch (error) { + case FINGERPRINT_ERROR_HW_UNAVAILABLE: + return Error::HW_UNAVAILABLE; + case FINGERPRINT_ERROR_UNABLE_TO_PROCESS: + return Error::UNABLE_TO_PROCESS; + case FINGERPRINT_ERROR_TIMEOUT: + return Error::TIMEOUT; + case FINGERPRINT_ERROR_NO_SPACE: + return Error::NO_SPACE; + case FINGERPRINT_ERROR_CANCELED: + return Error::CANCELED; + case FINGERPRINT_ERROR_UNABLE_TO_REMOVE: + return Error::UNABLE_TO_REMOVE; + case FINGERPRINT_ERROR_LOCKOUT: { + *vendorCode = FINGERPRINT_ERROR_LOCKOUT; + return Error::VENDOR; + } + default: + if (error >= FINGERPRINT_ERROR_VENDOR_BASE) { + // vendor specific code. + *vendorCode = error - FINGERPRINT_ERROR_VENDOR_BASE; + return Error::VENDOR; + } + } + LOG(ERROR) << "Unknown error from fingerprint vendor library: " << error; + return Error::UNABLE_TO_PROCESS; +} + +// Translate acquired messages returned by traditional HAL (see fingerprint.h) +// to AIDL-compliant AcquiredInfo +AcquiredInfo Session::VendorAcquiredFilter(int32_t info, int32_t* vendorCode) { + *vendorCode = 0; + + switch (info) { + case FINGERPRINT_ACQUIRED_GOOD: + return AcquiredInfo::GOOD; + case FINGERPRINT_ACQUIRED_PARTIAL: + return AcquiredInfo::PARTIAL; + case FINGERPRINT_ACQUIRED_INSUFFICIENT: + return AcquiredInfo::INSUFFICIENT; + case FINGERPRINT_ACQUIRED_IMAGER_DIRTY: + return AcquiredInfo::SENSOR_DIRTY; + case FINGERPRINT_ACQUIRED_TOO_SLOW: + return AcquiredInfo::TOO_SLOW; + case FINGERPRINT_ACQUIRED_TOO_FAST: + return AcquiredInfo::TOO_FAST; + default: + if (info >= FINGERPRINT_ACQUIRED_VENDOR_BASE) { + // vendor specific code. + *vendorCode = info - FINGERPRINT_ACQUIRED_VENDOR_BASE; + return AcquiredInfo::VENDOR; + } + } + LOG(ERROR) << "Unknown acquiredmsg from fingerprint vendor library: " << info; + return AcquiredInfo::INSUFFICIENT; +} + +bool Session::checkSensorLockout() { + LockoutMode lockoutMode = mLockoutTracker.getMode(); + if (lockoutMode == LockoutMode::PERMANENT) { + LOG(ERROR) << "Fail: lockout permanent"; + mCb->onLockoutPermanent(); + mIsLockoutTimerAborted = true; + return true; + } else if (lockoutMode == LockoutMode::TIMED) { + int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft(); + LOG(ERROR) << "Fail: lockout timed " << timeLeft; + mCb->onLockoutTimed(timeLeft); + if (!mIsLockoutTimerStarted) startLockoutTimer(timeLeft); + return true; + } + return false; +} + +void Session::clearLockout(bool clearAttemptCounter) { + mLockoutTracker.reset(clearAttemptCounter); + mCb->onLockoutCleared(); +} + +void Session::startLockoutTimer(int64_t timeout) { + mIsLockoutTimerAborted = false; + std::function action = + std::bind(&Session::lockoutTimerExpired, this); + std::thread([timeout, action]() { + std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); + action(); + }).detach(); + + mIsLockoutTimerStarted = true; +} + +void Session::lockoutTimerExpired() { + if (!mIsLockoutTimerAborted) + clearLockout(false); + + mIsLockoutTimerStarted = false; + mIsLockoutTimerAborted = false; +} + +void Session::notify(const fingerprint_msg_t* msg) { + switch (msg->type) { + case FINGERPRINT_ERROR: { + int32_t vendorCode = 0; + Error result = VendorErrorFilter(msg->data.error, &vendorCode); + LOG(DEBUG) << "onError(" << static_cast(result) << ")"; + mCb->onError(result, vendorCode); + } break; + case FINGERPRINT_ACQUIRED: { + int32_t vendorCode = 0; + AcquiredInfo result = + VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode); + LOG(DEBUG) << "onAcquired(" << static_cast(result) << ")"; + mCb->onAcquired(result, vendorCode); + } break; + case FINGERPRINT_TEMPLATE_ENROLLING: + if (FingerprintHalProperties::uses_percentage_samples().value_or(false)) { + const_cast(msg)->data.enroll.samples_remaining = + 100 - msg->data.enroll.samples_remaining; + } + if (FingerprintHalProperties::cancel_on_enroll_completion().value_or(false)) { + if (msg->data.enroll.samples_remaining == 0) + mHal.ss_fingerprint_cancel(); + } + LOG(DEBUG) << "onEnrollResult(fid=" << msg->data.enroll.finger.fid + << ", gid=" << msg->data.enroll.finger.gid + << ", rem=" << msg->data.enroll.samples_remaining << ")"; + mCb->onEnrollmentProgress(msg->data.enroll.finger.fid, + msg->data.enroll.samples_remaining); + 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 << ")"; + std::vector enrollments; + enrollments.push_back(msg->data.removed.finger.fid); + mCb->onEnrollmentsRemoved(enrollments); + } 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 hw_auth_token_t hat = msg->data.authenticated.hat; + HardwareAuthToken authToken; + translate(hat, authToken); + + mCb->onAuthenticationSucceeded(msg->data.authenticated.finger.fid, authToken); + mLockoutTracker.reset(true); + } else { + mCb->onAuthenticationFailed(); + mLockoutTracker.addFailedAttempt(); + checkSensorLockout(); + } + } 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 << ")"; + std::vector enrollments; + enrollments.push_back(msg->data.enumerated.finger.fid); + mCb->onEnrollmentsEnumerated(enrollments); + } break; + } } } // namespace fingerprint diff --git a/aidl/fingerprint/Session.h b/aidl/fingerprint/Session.h index 0e314bfd..15dfdcb4 100644 --- a/aidl/fingerprint/Session.h +++ b/aidl/fingerprint/Session.h @@ -7,6 +7,12 @@ #pragma once #include +#include + +#include + +#include "LegacyHAL.h" +#include "LockoutTracker.h" using ::aidl::android::hardware::biometrics::common::ICancellationSignal; using ::aidl::android::hardware::biometrics::common::OperationContext; @@ -19,8 +25,12 @@ namespace hardware { namespace biometrics { namespace fingerprint { +void onClientDeath(void* cookie); + class Session : public BnSession { public: + Session(LegacyHAL hal, int userId, std::shared_ptr cb, + LockoutTracker lockoutTracker); ndk::ScopedAStatus generateChallenge() override; ndk::ScopedAStatus revokeChallenge(int64_t challenge) override; ndk::ScopedAStatus enroll(const HardwareAuthToken& hat, @@ -53,6 +63,39 @@ public: ndk::ScopedAStatus onContextChanged(const OperationContext& context) override; ndk::ScopedAStatus onPointerCancelWithContext(const PointerContext& context) override; ndk::ScopedAStatus setIgnoreDisplayTouches(bool shouldIgnore) override; + + ndk::ScopedAStatus cancel(); + binder_status_t linkToDeath(AIBinder* binder); + bool isClosed(); + void notify( + const fingerprint_msg_t* msg); + +private: + LegacyHAL mHal; + LockoutTracker mLockoutTracker; + bool mClosed = false; + + Error VendorErrorFilter(int32_t error, int32_t* vendorCode); + AcquiredInfo VendorAcquiredFilter(int32_t info, int32_t* vendorCode); + bool checkSensorLockout(); + void clearLockout(bool clearAttemptCounter); + void startLockoutTimer(int64_t timeout); + void lockoutTimerExpired(); + + // lockout timer + bool mIsLockoutTimerStarted = false; + bool mIsLockoutTimerAborted = false; + + // The user ID for which this session was created. + int32_t mUserId; + + // Callback for talking to the framework. This callback must only be called from non-binder + // threads to prevent nested binder calls and consequently a binder thread exhaustion. + // Practically, it means that this callback should always be called from the worker thread. + std::shared_ptr mCb; + + // Binder death handler. + AIBinder_DeathRecipient* mDeathRecipient; }; } // namespace fingerprint diff --git a/aidl/fingerprint/VendorConstants.h b/aidl/fingerprint/VendorConstants.h new file mode 100644 index 00000000..86656b3e --- /dev/null +++ b/aidl/fingerprint/VendorConstants.h @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2020 The LineageOS Project + +#pragma once + +// Fingerprint requests +#define FINGERPRINT_REQUEST_ENROLL_SESSION 1002 +#define FINGERPRINT_REQUEST_ENROLL_TYPE 18 +#define FINGERPRINT_REQUEST_ENUMERATE 11 +#define FINGERPRINT_REQUEST_GET_FP_IDS 1003 +#define FINGERPRINT_REQUEST_GET_MAX_TEMPLATE_NUMBER 1004 +#define FINGERPRINT_REQUEST_GET_SENSOR_INFO 5 +#define FINGERPRINT_REQUEST_GET_SENSOR_STATUS 6 +#define FINGERPRINT_REQUEST_GET_TOUCH_CNT 1007 +#define FINGERPRINT_REQUEST_GET_UNIQUE_ID 7 +#define FINGERPRINT_REQUEST_GET_USERIDS 12 +#define FINGERPRINT_REQUEST_GET_VERSION 4 +#define FINGERPRINT_REQUEST_HAS_FEATURE 1006 +#define FINGERPRINT_REQUEST_LOCKOUT 1001 +#define FINGERPRINT_REQUEST_NAVIGATION_LCD_ONOFF 17 +#define FINGERPRINT_REQUEST_NAVIGATION_MODE_END 16 +#define FINGERPRINT_REQUEST_NAVIGATION_MODE_START 15 +#define FINGERPRINT_REQUEST_PAUSE 0 +#define FINGERPRINT_REQUEST_PROCESS_FIDO 9 +#define FINGERPRINT_REQUEST_REMOVE_FINGER 1000 +#define FINGERPRINT_REQUEST_RESUME 1 +#define FINGERPRINT_REQUEST_SENSOR_TEST_NORMALSCAN 3 +#define FINGERPRINT_REQUEST_SESSION_OPEN 2 +#define FINGERPRINT_REQUEST_SET_ACTIVE_GROUP 8 +#define FINGERPRINT_REQUEST_UPDATE_SID 10 + +#define SEM_REQUEST_FORCE_CBGE 21 +#define SEM_REQUEST_GET_FINGER_ICON_REMAIN_TIME 1010 +#define SEM_REQUEST_GET_SECURITY_LEVEL 30 +#define SEM_REQUEST_GET_SENSOR_TEST_RESULT 19 +#define SEM_REQUEST_GET_TA_VERSION 10000 +#define SEM_REQUEST_GET_TSP_BLOCK_STATUS 0x3F9 +#define SEM_REQUEST_HIDE_INDISPLAY_AUTH_ANIMATION 0x3F4 +#define SEM_REQUEST_INSTALL_TA 10001 +#define SEM_REQUEST_IS_NEW_MATCHER 27 +#define SEM_REQUEST_IS_TEMPLATE_CHANGED 25 +#define SEM_REQUEST_MASK_CTL 0x3F5 +#define SEM_REQUEST_MOVE_INDISPLAY_ICON 0x3F3 +#define SEM_REQUEST_OPTICAL_CALIBRATION 0x3F8 +#define SEM_REQUEST_REMOVE_ALL_USER 0x3F6 +#define SEM_REQUEST_SET_ASP_LEVEL 20 +#define SEM_REQUEST_SET_BOUNCER_SCREEN_STATUS 0x3FA +#define SEM_REQUEST_SET_SCREEN_STATUS 0x3F0 +#define SEM_REQUEST_SHOW_INDISPLAY_AUTH_ANIMATION 1009 +#define SEM_REQUEST_TOUCH_EVENT 22 +#define SEM_REQUEST_TOUCH_SENSITIVE_CHANGE 0x3F7 +#define SEM_REQUEST_UPDATE_MATCHER 28 +#define SEM_REQUEST_VENDOR_EGIS_CALIBRATION 23 +#define SEM_REQUEST_VENDOR_QCOM_REMOVE_CBGE 24 +#define SEM_REQUEST_WIRELESS_CHARGER_STATUS 29 + +// Fingerprint aquired codes +#define SEM_FINGERPRINT_ACQUIRED_DUPLICATED_IMAGE 1002 +#define SEM_FINGERPRINT_ACQUIRED_LIGHT_TOUCH 1003 +#define SEM_FINGERPRINT_ACQUIRED_TSP_BLOCK 1004 +#define SEM_FINGERPRINT_ACQUIRED_TSP_UNBLOCK 1005 +#define SEM_FINGERPRINT_ACQUIRED_WET_FINGER 1001 + +// Fingerprint errors +#define SEM_FINGERPRINT_ERROR_CALIBRATION 1001 +#define SEM_FINGERPRINT_ERROR_DISABLED_BIOMETRICS 5002 +#define SEM_FINGERPRINT_ERROR_INVALID_HW 1005 +#define SEM_FINGERPRINT_ERROR_NEED_TO_RETRY 5000 +#define SEM_FINGERPRINT_ERROR_ONE_HAND_MODE 5001 +#define SEM_FINGERPRINT_ERROR_PATTERN_DETECTED 1007 +#define SEM_FINGERPRINT_ERROR_SERVICE_FAILURE 1003 +#define SEM_FINGERPRINT_ERROR_SMART_VIEW 5003 +#define SEM_FINGERPRINT_ERROR_SYSTEM_FAILURE 1002 +#define SEM_FINGERPRINT_ERROR_TA_UPDATE -100 +#define SEM_FINGERPRINT_ERROR_TEMPLATE_CORRUPTED 1004 +#define SEM_FINGERPRINT_ERROR_TEMPLATE_FORMAT_CHANGED 1006 +#define SEM_FINGERPRINT_ERROR_WIRELESS_CHARGING 5004 + +// Fingerprint events +#define SEM_FINGERPRINT_EVENT_BASE 10000 +#define SEM_FINGERPRINT_EVENT_CAPTURE_COMPLETED 10003 +#define SEM_FINGERPRINT_EVENT_CAPTURE_FAILED 10006 +#define SEM_FINGERPRINT_EVENT_CAPTURE_READY 10001 +#define SEM_FINGERPRINT_EVENT_CAPTURE_STARTED 10002 +#define SEM_FINGERPRINT_EVENT_CAPTURE_SUCCESS 10005 +#define SEM_FINGERPRINT_EVENT_FACTORY_SNSR_SCRIPT_END 10009 +#define SEM_FINGERPRINT_EVENT_FACTORY_SNSR_SCRIPT_START 10008 +#define SEM_FINGERPRINT_EVENT_FINGER_LEAVE 10004 +#define SEM_FINGERPRINT_EVENT_FINGER_LEAVE_TIMEOUT 10007 +#define SEM_FINGERPRINT_EVENT_GESTURE_DTAP 20003 +#define SEM_FINGERPRINT_EVENT_GESTURE_LPRESS 20004 +#define SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_DOWN 20002 +#define SEM_FINGERPRINT_EVENT_GESTURE_SWIPE_UP 20001 +#define SEM_FINGERPRINT_EVENT_SPEN_CONTROL_OFF 30002 +#define SEM_FINGERPRINT_EVENT_SPEN_CONTROL_ON 30001 + +// Fingerprint sensor status codes +#define SEM_SENSOR_STATUS_CALIBRATION_ERROR 100045 +#define SEM_SENSOR_STATUS_ERROR 100042 +#define SEM_SENSOR_STATUS_OK 100040 +#define SEM_SENSOR_STATUS_WORKING 100041 diff --git a/aidl/fingerprint/fingerprint.sysprop b/aidl/fingerprint/fingerprint.sysprop new file mode 100644 index 00000000..7e3896a6 --- /dev/null +++ b/aidl/fingerprint/fingerprint.sysprop @@ -0,0 +1,78 @@ +# fingerprint.sysprop +# module becomes static class (Java) / namespace (C++) for serving API +module: "android.fingerprint.samsung.FingerprintHalProperties" +owner: Vendor + +# type of fingerprint sensor +prop { + prop_name: "ro.vendor.fingerprint.type" + type: String + scope: Internal + access: Readonly + enum_values: "default|rear|udfps|udfps_optical|side|home" + api_name: "type" +} + +# max enrollments per user (default: 4) +prop { + prop_name: "ro.vendor.fingerprint.max_enrollments" + type: Integer + scope: Internal + access: Readonly + api_name: "max_enrollments_per_user" +} + +# supports navigation gestures +prop { + prop_name: "ro.vendor.fingerprint.supports_gestures" + type: Boolean + scope: Internal + access: Readonly + api_name: "supports_gestures" +} + +# sensor location +# |||display in pixel +prop { + prop_name: "ro.vendor.fingerprint.sensor_location" + type: String + scope: Internal + access: Readonly + api_name: "sensor_location" +} + +# force calibration on enroll +prop { + prop_name: "ro.vendor.fingerprint.force_calibrate" + type: Boolean + scope: Internal + access: Readonly + api_name: "force_calibrate" +} + +# send touch events to HAL +prop { + prop_name: "ro.vendor.fingerprint.request_touch_event" + type: Boolean + scope: Internal + access: Readonly + api_name: "request_touch_event" +} + +# uses percentage samples +prop { + prop_name: "ro.vendor.fingerprint.uses_percentage_samples" + type: Boolean + scope: Internal + access: Readonly + api_name: "uses_percentage_samples" +} + +# cancel on completed enrollment +prop { + prop_name: "ro.vendor.fingerprint.cancel_on_enroll_completion" + type: Boolean + scope: Internal + access: Readonly + api_name: "cancel_on_enroll_completion" +}