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 Original line Diff line number Diff line
@@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const {


void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
    InputMapper::populateDeviceInfo(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,
        info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f,
                            0.0f, 0.0f);
                            0.0f, 0.0f);
    }
    }
+18 −7
Original line number Original line 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
    // 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
    // by the external stylus state. That's why we don't add it directly to mSource during
    // configuration.
    // 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) {
void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
@@ -270,8 +273,8 @@ void TouchInputMapper::dump(std::string& dump) {
    }
    }


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

        mExternalStylusPresence = ExternalStylusPresence::NONE;
    if (!mExternalStylusConnected) {
        resetExternalStylus();
        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(
TouchInputMapper::Parameters TouchInputMapper::computeParameters(
@@ -520,7 +531,7 @@ void TouchInputMapper::dumpRawPointerAxes(std::string& dump) {
}
}


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


/**
/**
+10 −2
Original line number Original line Diff line number Diff line
@@ -365,6 +365,16 @@ protected:
    RawState mLastRawState;
    RawState mLastRawState;
    CookedState mLastCookedState;
    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
    // State provided by an external stylus
    StylusState mExternalStylusState;
    StylusState mExternalStylusState;
    // If an external stylus is capable of reporting pointer-specific data like pressure, we will
    // If an external stylus is capable of reporting pointer-specific data like pressure, we will
@@ -460,8 +470,6 @@ private:
    float mTiltYCenter;
    float mTiltYCenter;
    float mTiltYScale;
    float mTiltYScale;


    bool mExternalStylusConnected;

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


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

    SingleTouchInputMapper& initializeInputMapperWithExternalStylus(bool supportsPressure = true) {
        addConfigurationProperty("touch.deviceType", "touchScreen");
        addConfigurationProperty("touch.deviceType", "touchScreen");
        prepareDisplay(ui::ROTATION_0);
        prepareDisplay(ui::ROTATION_0);
        prepareButtons();
        prepareButtons();
        prepareAxes(POSITION);
        prepareAxes(POSITION);
        auto& mapper = constructAndAddMapper<SingleTouchInputMapper>();
        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.pressure = 0.f;
        }

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


TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSourceWithPressure) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
    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) {
TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));
    ASSERT_NO_FATAL_FAILURE(testUnsuccessfulFusionGesture(mapper));