aidl: fingerprint: Initial samsung implementation

Change-Id: I2685b176a1b4fb2b094ff58e911997084e42a879
urubino
Tim Zimmermann 4 months ago
parent 37b235d802
commit b7dca1207d
No known key found for this signature in database
GPG Key ID: 6DC21A63F819C5EF
  1. 13
      aidl/fingerprint/Android.bp
  2. 27
      aidl/fingerprint/CancellationSignal.cpp
  3. 34
      aidl/fingerprint/CancellationSignal.h
  4. 210
      aidl/fingerprint/Fingerprint.cpp
  5. 19
      aidl/fingerprint/Fingerprint.h
  6. 50
      aidl/fingerprint/Legacy2Aidl.h
  7. 79
      aidl/fingerprint/LegacyHAL.cpp
  8. 42
      aidl/fingerprint/LegacyHAL.h
  9. 63
      aidl/fingerprint/LockoutTracker.cpp
  10. 42
      aidl/fingerprint/LockoutTracker.h
  11. 383
      aidl/fingerprint/Session.cpp
  12. 43
      aidl/fingerprint/Session.h
  13. 101
      aidl/fingerprint/VendorConstants.h
  14. 78
      aidl/fingerprint/fingerprint.sysprop

@ -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,
}

@ -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

@ -0,0 +1,34 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <aidl/android/hardware/biometrics/common/BnCancellationSignal.h>
#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

@ -5,21 +5,219 @@
*/
#include "Fingerprint.h"
#include "VendorConstants.h"
#include <fingerprint.sysprop.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <fcntl.h>
#include <linux/uinput.h>
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<SensorProps>* /*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<ISessionCallback>& /*cb*/,
std::shared_ptr<ISession>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ndk::ScopedAStatus Fingerprint::getSensorProps(std::vector<SensorProps>* out) {
std::vector<common::ComponentInfo> 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<std::string> 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<ISessionCallback>& cb,
std::shared_ptr<ISession>* out) {
CHECK(mSession == nullptr || mSession->isClosed()) << "Open session already exists!";
mSession = SharedRefBase::make<Session>(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

@ -8,6 +8,10 @@
#include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
#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<SensorProps>* _aidl_return) override;
ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
const std::shared_ptr<ISessionCallback>& cb,
std::shared_ptr<ISession>* 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<Session> mSession;
};
} // namespace fingerprint

@ -0,0 +1,50 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
#include <hardware/hw_auth_token.h>
#include <endian.h>
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<uint32_t>(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<keymaster::HardwareAuthenticatorType>(
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

@ -0,0 +1,79 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "Fingerprint.h"
#include <android-base/logging.h>
#include <dlfcn.h>
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<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"));
ss_fingerprint_request = reinterpret_cast<typeof(ss_fingerprint_request)>(
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

@ -0,0 +1,42 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <hardware/fingerprint.h>
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

@ -0,0 +1,63 @@
/*
* Copyright (C) 2024 The LineageOS Project
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "Fingerprint.h"
#include "LockoutTracker.h"
#include <util/Util.h>
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

@ -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

@ -4,7 +4,19 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "CancellationSignal.h"
#include "Legacy2Aidl.h"
#include "Session.h"
#include "VendorConstants.h"
#include <fingerprint.sysprop.h>
#include <android-base/logging.h>
#include <endian.h>
#include <thread>
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<Session*>(cookie);
if (session && !session->isClosed()) {
session->close();
}
}
Session::Session(LegacyHAL hal, int userId, std::shared_ptr<ISessionCallback> 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<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ndk::ScopedAStatus Session::enroll(const HardwareAuthToken& hat,
std::shared_ptr<ICancellationSignal>* 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<CancellationSignal>(this);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::authenticate(int64_t /*operationId*/,
std::shared_ptr<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ndk::ScopedAStatus Session::authenticate(int64_t operationId,
std::shared_ptr<ICancellationSignal>* 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<CancellationSignal>(this);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ndk::ScopedAStatus Session::detectInteraction(std::shared_ptr<ICancellationSignal>* out) {
LOG(INFO) << "detectInteraction";
LOG(DEBUG) << "Detect interaction is not supported";
mCb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
*out = SharedRefBase::make<CancellationSignal>(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<int32_t>& /*enrollmentIds*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
ndk::ScopedAStatus Session::removeEnrollments(const std::vector<int32_t>& 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<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
int64_t operationId, const OperationContext& /*context*/,
std::shared_ptr<ICancellationSignal>* 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<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
std::shared_ptr<ICancellationSignal>* out) {
return enroll(hat, out);
}
ndk::ScopedAStatus Session::detectInteractionWithContext(const OperationContext& /*context*/,
std::shared_ptr<ICancellationSignal>* /*out*/) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
std::shared_ptr<ICancellationSignal>* 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<void()> 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<int>(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<int>(result) << ")";
mCb->onAcquired(result, vendorCode);
} break;
case FINGERPRINT_TEMPLATE_ENROLLING:
if (FingerprintHalProperties::uses_percentage_samples().value_or(false)) {
const_cast<fingerprint_msg_t*>(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<int> 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<int> enrollments;
enrollments.push_back(msg->data.enumerated.finger.fid);
mCb->onEnrollmentsEnumerated(enrollments);
} break;
}
}
} // namespace fingerprint

@ -7,6 +7,12 @@
#pragma once
#include <aidl/android/hardware/biometrics/fingerprint/BnSession.h>
#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
#include <hardware/fingerprint.h>
#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<ISessionCallback> 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<ISessionCallback> mCb;
// Binder death handler.
AIBinder_DeathRecipient* mDeathRecipient;
};
} // namespace fingerprint

@ -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

@ -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
# <x>|<y>|<radius>|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"
}
Loading…
Cancel
Save