Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3621859 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Add additional ways to recognize an external stylus

Recognize a keyboard device as an external stylus if it can produce any
of the stylus key codes.

Additionally, add the ability to configure an input device as an
external stylus using an IDC file. This will be necessary to classify
external styluses that report buttons as custom HID usages, since we
don't have a way to tell which HID usages a device supports from
userspace yet.

Bug: 246394583
Test: atest inputflinger_tests
Test: manual, with a Lenovo Precision Pen 3
Change-Id: Ief22aac9537cd168dd43d2a9d63bc0a65f6ba3dc
parent e1a41a84
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -149,6 +149,14 @@ static std::string sha1(const std::string& in) {
    return out;
}

/* The set of all Android key codes that correspond to buttons (bit-switches) on a stylus. */
static constexpr std::array<int32_t, 4> STYLUS_BUTTON_KEYCODES = {
        AKEYCODE_STYLUS_BUTTON_PRIMARY,
        AKEYCODE_STYLUS_BUTTON_SECONDARY,
        AKEYCODE_STYLUS_BUTTON_TERTIARY,
        AKEYCODE_STYLUS_BUTTON_TAIL,
};

/**
 * Return true if name matches "v4l-touch*"
 */
@@ -2189,11 +2197,13 @@ void EventHub::openDeviceLocked(const std::string& devicePath) {
        device->classes |= InputDeviceClass::CURSOR;
    }

    // See if this is a rotary encoder type device.
    // See if the device is specially configured to be of a certain type.
    std::string deviceType;
    if (device->configuration && device->configuration->tryGetProperty("device.type", deviceType)) {
        if (deviceType == "rotaryEncoder") {
            device->classes |= InputDeviceClass::ROTARY_ENCODER;
        } else if (deviceType == "externalStylus") {
            device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
        }
    }

@@ -2298,6 +2308,16 @@ void EventHub::openDeviceLocked(const std::string& devicePath) {
                break;
            }
        }

        // See if this device has any stylus buttons that we would want to fuse with touch data.
        if (!device->classes.any(InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT)) {
            for (int32_t keycode : STYLUS_BUTTON_KEYCODES) {
                if (device->hasKeycodeLocked(keycode)) {
                    device->classes |= InputDeviceClass::EXTERNAL_STYLUS;
                    break;
                }
            }
        }
    }

    // If the device isn't recognized as something we handle, don't monitor it.
+2 −2
Original line number Diff line number Diff line
@@ -2437,8 +2437,8 @@ TEST_F(InputReaderIntegrationTest, ExternalStylusesButtons) {
    const auto device = findDeviceByName(stylus->getName());
    ASSERT_TRUE(device.has_value());

    // An external stylus with buttons should be recognized as a keyboard.
    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, device->getSources())
    // An external stylus with buttons should also be recognized as a keyboard.
    ASSERT_EQ(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_STYLUS, device->getSources())
            << "Unexpected source " << inputEventSourceToString(device->getSources()).c_str();
    ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, device->getKeyboardType());