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

Commit 7ff19a10 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

TouchInputMapper: Only use SOURCE_BLUETOOTH_STYLUS when fusion possible

TouchInputMapper can fuse touch pointers with pressure reported by an
external stylus using bluetooth. The pointer fusion can only happen when
the external styus can report pressure. If the external stylus does not
report pressure, there will be no stylus fusion, so do not add
SOURCE_BLUETOOTH_STYLUS to the touchscreen's InputDevice in this case.

Bug: 346797989
Test: atest inputflinger_tests
Flag: EXEMPT bugfix
Change-Id: Idd84cdb77fb3b59cbe314aeedca9d6a0da4affc3
parent 2526c331
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const {

void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
    InputMapper::populateDeviceInfo(info);
    if (mRawPressureAxis) {
    if (mRawPressureAxis || mTouchButtonAccumulator.hasButtonTouch()) {
        info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f,
                            0.0f, 0.0f);
    }
+18 −7
Original line number Diff line number Diff line
@@ -149,7 +149,10 @@ uint32_t TouchInputMapper::getSources() const {
    // The SOURCE_BLUETOOTH_STYLUS is added to events dynamically if the current stream is modified
    // by the external stylus state. That's why we don't add it directly to mSource during
    // configuration.
    return mSource | (hasExternalStylus() ? AINPUT_SOURCE_BLUETOOTH_STYLUS : 0);
    return mSource |
            (mExternalStylusPresence == ExternalStylusPresence::TOUCH_FUSION
                     ? AINPUT_SOURCE_BLUETOOTH_STYLUS
                     : 0);
}

void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
@@ -270,8 +273,8 @@ void TouchInputMapper::dump(std::string& dump) {
    }

    dump += INDENT3 "Stylus Fusion:\n";
    dump += StringPrintf(INDENT4 "ExternalStylusConnected: %s\n",
                         toString(mExternalStylusConnected));
    dump += StringPrintf(INDENT4 "ExternalStylusPresence: %s\n",
                         ftl::enum_string(mExternalStylusPresence).c_str());
    dump += StringPrintf(INDENT4 "Fused External Stylus Pointer ID: %s\n",
                         toString(mFusedStylusPointerId).c_str());
    dump += StringPrintf(INDENT4 "External Stylus Data Timeout: %" PRId64 "\n",
@@ -356,11 +359,19 @@ std::list<NotifyArgs> TouchInputMapper::reconfigure(nsecs_t when,
void TouchInputMapper::resolveExternalStylusPresence() {
    std::vector<InputDeviceInfo> devices;
    getContext()->getExternalStylusDevices(devices);
    mExternalStylusConnected = !devices.empty();

    if (!mExternalStylusConnected) {
    if (devices.empty()) {
        mExternalStylusPresence = ExternalStylusPresence::NONE;
        resetExternalStylus();
        return;
    }
    mExternalStylusPresence =
            std::any_of(devices.begin(), devices.end(),
                        [](const auto& info) {
                            return info.getMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
                                                       AINPUT_SOURCE_STYLUS) != nullptr;
                        })
            ? ExternalStylusPresence::TOUCH_FUSION
            : ExternalStylusPresence::BUTTON_FUSION;
}

TouchInputMapper::Parameters TouchInputMapper::computeParameters(
@@ -520,7 +531,7 @@ void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
}

bool TouchInputMapper::hasExternalStylus() const {
    return mExternalStylusConnected;
    return mExternalStylusPresence != ExternalStylusPresence::NONE;
}

/**
+10 −2
Original line number Diff line number Diff line
@@ -365,6 +365,16 @@ protected:
    RawState mLastRawState;
    CookedState mLastCookedState;

    enum class ExternalStylusPresence {
        // No external stylus connected.
        NONE,
        // An external stylus that can report touch/pressure that can be fused with the touchscreen.
        TOUCH_FUSION,
        // An external stylus that can only report buttons.
        BUTTON_FUSION,
        ftl_last = BUTTON_FUSION,
    };
    ExternalStylusPresence mExternalStylusPresence{ExternalStylusPresence::NONE};
    // State provided by an external stylus
    StylusState mExternalStylusState;
    // If an external stylus is capable of reporting pointer-specific data like pressure, we will
@@ -460,8 +470,6 @@ private:
    float mTiltYCenter;
    float mTiltYScale;

    bool mExternalStylusConnected;

    // Oriented motion ranges for input device info.
    struct OrientedRanges {
        InputDeviceInfo::MotionRange x;
+21 −3
Original line number Diff line number Diff line
@@ -6675,15 +6675,27 @@ INSTANTIATE_TEST_SUITE_P(TouchscreenPrecisionTests, TouchscreenPrecisionTestsFix

class ExternalStylusFusionTest : public SingleTouchInputMapperTest {
public:
    SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
    void SetUp() override {
        SingleTouchInputMapperTest::SetUp();
        mExternalStylusDeviceInfo = {};
        mStylusState = {};
    }

    SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) {
        addConfigurationProperty("touch.deviceType", "touchScreen");
        prepareDisplay(ui::ROTATION_0);
        prepareButtons();
        prepareAxes(POSITION);
        auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();

        mStylusState.when = ARBITRARY_TIME;
        if (supportsPressure) {
            mExternalStylusDeviceInfo.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE,
                                                     AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f,
                                                     0.0f);
            mStylusState.pressure = 0.f;
        }

        mStylusState.when = ARBITRARY_TIME;
        mStylusState.toolType = ToolType::STYLUS;
        mReader->getContext()->setExternalStylusDevices({mExternalStylusDeviceInfo});
        configureDevice(InputReaderConfiguration::Change::EXTERNAL_STYLUS_PRESENCE);
@@ -6791,11 +6803,17 @@ private:
    InputDeviceInfo mExternalStylusDeviceInfo{};
};

TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
}

TEST_F(ExternalStylusFusionTest, DoesNotUseBluetoothStylusSourceWithoutPressure) {
    SingleTouchInputMapper& mapper =
            initializeInputMapperWithExternalStylus(/*supportsPressure=*/false);
    ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
}

TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));