/* * Copyright (C) 2024 The LineageOS Project * * SPDX-License-Identifier: Apache-2.0 */ #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); 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::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 } // namespace biometrics } // namespace hardware } // namespace android } // namespace aidl