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

Commit 3bb74671 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Automerger Merge Worker
Browse files

Merge "Stylus fusion: Use SOURCE_BLUETOOTH_STYLUS dynamically for events" into...

Merge "Stylus fusion: Use SOURCE_BLUETOOTH_STYLUS dynamically for events" into udc-qpr-dev am: 6d86aa2d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/24807954



Change-Id: Ib63678373d002aa415c0a58d2f8f1fab68eb1ee3
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents ff3ebb32 6d86aa2d
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -130,7 +130,10 @@ TouchInputMapper::TouchInputMapper(InputDeviceContext& deviceContext,
TouchInputMapper::~TouchInputMapper() {}

uint32_t TouchInputMapper::getSources() const {
    return mSource;
    // 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);
}

void TouchInputMapper::populateDeviceInfo(InputDeviceInfo& info) {
@@ -932,9 +935,6 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded)
        if (hasStylus()) {
            mSource |= AINPUT_SOURCE_STYLUS;
        }
        if (hasExternalStylus()) {
            mSource |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
        }
    } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) {
        mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
        mDeviceMode = DeviceMode::NAVIGATION;
@@ -1653,6 +1653,10 @@ std::list<NotifyArgs> TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t re
                                mSource, mViewport.displayId, policyFlags,
                                mLastCookedState.buttonState, mCurrentCookedState.buttonState);

    if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
        mCurrentStreamModifiedByExternalStylus = false;
    }

    // Clear some transient state.
    mCurrentRawState.rawVScroll = 0;
    mCurrentRawState.rawHScroll = 0;
@@ -1704,6 +1708,10 @@ void TouchInputMapper::applyExternalStylusButtonState(nsecs_t when) {

        mExternalStylusButtonsApplied |= pressedButtons;
        mExternalStylusButtonsApplied &= ~releasedButtons;

        if (mExternalStylusButtonsApplied != 0 || releasedButtons != 0) {
            mCurrentStreamModifiedByExternalStylus = true;
        }
    }
}

@@ -1714,6 +1722,8 @@ void TouchInputMapper::applyExternalStylusTouchState(nsecs_t when) {
        return;
    }

    mCurrentStreamModifiedByExternalStylus = true;

    float pressure = lastPointerData.isTouching(*mFusedStylusPointerId)
            ? lastPointerData.pointerCoordsForId(*mFusedStylusPointerId)
                      .getAxisValue(AMOTION_EVENT_AXIS_PRESSURE)
@@ -3813,6 +3823,9 @@ NotifyMotionArgs TouchInputMapper::dispatchMotion(
            ALOG_ASSERT(false);
        }
    }
    if (mCurrentStreamModifiedByExternalStylus) {
        source |= AINPUT_SOURCE_BLUETOOTH_STYLUS;
    }

    const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
    const bool showDirectStylusPointer = mConfig.stylusPointerIconEnabled &&
+2 −0
Original line number Diff line number Diff line
@@ -357,6 +357,8 @@ protected:
    bool mExternalStylusDataPending;
    // A subset of the buttons in mCurrentRawState that came from an external stylus.
    int32_t mExternalStylusButtonsApplied{0};
    // True if the current cooked pointer data was modified due to the state of an external stylus.
    bool mCurrentStreamModifiedByExternalStylus{false};

    // True if we sent a HOVER_ENTER event.
    bool mSentHoverEnter{false};
+51 −33
Original line number Diff line number Diff line
@@ -91,6 +91,9 @@ static constexpr int32_t ACTION_POINTER_1_DOWN =
static constexpr int32_t ACTION_POINTER_1_UP =
        AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr uint32_t STYLUS_FUSION_SOURCE =
        AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
// Minimum timestamp separation between subsequent input events from a Bluetooth device.
static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
// Maximum smoothing time delta so that we don't generate events too far into the future.
@@ -2222,6 +2225,22 @@ TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonMotionEventsDisable
// ongoing stylus gesture that is being emitted by the touchscreen.
using ExternalStylusIntegrationTest = BaseTouchIntegrationTest;
TEST_F(ExternalStylusIntegrationTest, ExternalStylusConnectionChangesTouchscreenSource) {
    // Create an external stylus capable of reporting pressure data that
    // should be fused with a touch pointer.
    std::unique_ptr<UinputExternalStylusWithPressure> stylus =
            createUinputDevice<UinputExternalStylusWithPressure>();
    ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
    const auto stylusInfo = findDeviceByName(stylus->getName());
    ASSERT_TRUE(stylusInfo);
    // Connecting an external stylus changes the source of the touchscreen.
    const auto deviceInfo = findDeviceByName(mDevice->getName());
    ASSERT_TRUE(deviceInfo);
    ASSERT_TRUE(isFromSource(deviceInfo->getSources(), STYLUS_FUSION_SOURCE));
}
TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureReported) {
    const Point centerPoint = mDevice->getCenterPoint();
@@ -2251,17 +2270,17 @@ TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureReport
    mDevice->sendDown(centerPoint);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                  WithToolType(ToolType::STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId), WithPressure(100.f / RAW_PRESSURE_MAX))));
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithToolType(ToolType::STYLUS),
                  WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
                  WithPressure(100.f / RAW_PRESSURE_MAX))));
    // Change the pressure on the external stylus, and ensure the touchscreen generates a MOVE
    // event with the updated pressure.
    stylus->setPressure(200);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE),
                  WithToolType(ToolType::STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId), WithPressure(200.f / RAW_PRESSURE_MAX))));
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_MOVE), WithToolType(ToolType::STYLUS),
                  WithButtonState(0), WithSource(STYLUS_FUSION_SOURCE), WithDeviceId(touchscreenId),
                  WithPressure(200.f / RAW_PRESSURE_MAX))));
    // The external stylus did not generate any events.
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
@@ -2306,8 +2325,8 @@ TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureNotRep
    // it shows up as a finger pointer.
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                  WithToolType(ToolType::FINGER), WithDeviceId(touchscreenId),
                  WithPressure(1.f))));
                  WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
                  WithToolType(ToolType::FINGER), WithDeviceId(touchscreenId), WithPressure(1.f))));
    // Change the pressure on the external stylus. Since the pressure was not present at the start
    // of the gesture, it is ignored for now.
@@ -2319,6 +2338,7 @@ TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureNotRep
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
                  WithSource(AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS),
                  WithToolType(ToolType::FINGER))));
    // Start a new gesture. Since we have a valid pressure value, it shows up as a stylus.
@@ -2327,9 +2347,9 @@ TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureNotRep
    mDevice->sendDown(centerPoint);
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                  WithToolType(ToolType::STYLUS), WithButtonState(0),
                  WithDeviceId(touchscreenId), WithPressure(200.f / RAW_PRESSURE_MAX))));
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(STYLUS_FUSION_SOURCE),
                  WithToolType(ToolType::STYLUS), WithButtonState(0), WithDeviceId(touchscreenId),
                  WithPressure(200.f / RAW_PRESSURE_MAX))));
    // The external stylus did not generate any events.
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
@@ -2361,10 +2381,11 @@ TEST_F(ExternalStylusIntegrationTest, DISABLED_UnfusedExternalStylus) {
            std::chrono::milliseconds(ns2ms(EXTERNAL_STYLUS_DATA_TIMEOUT));
    mDevice->sendSync();
    ASSERT_NO_FATAL_FAILURE(
            mTestListener
                    ->assertNotifyMotionWasCalled(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
                                                        WithToolType(
                                                                ToolType::FINGER),
            mTestListener->assertNotifyMotionWasCalled(AllOf(WithMotionAction(
                                                                     AMOTION_EVENT_ACTION_DOWN),
                                                             WithToolType(ToolType::FINGER),
                                                             WithSource(AINPUT_SOURCE_TOUCHSCREEN |
                                                                        AINPUT_SOURCE_STYLUS),
                                                             WithButtonState(0),
                                                             WithDeviceId(touchscreenId),
                                                             WithPressure(1.f)),
@@ -7400,12 +7421,10 @@ public:
protected:
    StylusState mStylusState{};
    static constexpr uint32_t EXPECTED_SOURCE =
            AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_BLUETOOTH_STYLUS;
    void testStartFusedStylusGesture(SingleTouchInputMapper& mapper) {
        auto toolTypeSource =
                AllOf(WithSource(EXPECTED_SOURCE), WithToolType(ToolType::STYLUS));
                AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
        // The first pointer is withheld.
        processDown(mapper, 100, 200);
@@ -7439,7 +7458,7 @@ protected:
        processUp(mapper);
        processSync(mapper);
        ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(EXPECTED_SOURCE),
                AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
                      WithToolType(ToolType::STYLUS))));
        mStylusState.pressure = 0.f;
@@ -7449,8 +7468,10 @@ protected:
    }
    void testUnsuccessfulFusionGesture(SingleTouchInputMapper& mapper) {
        // When stylus fusion is not successful, events should be reported with the original source.
        // In this case, it is from a touchscreen.
        auto toolTypeSource =
                AllOf(WithSource(EXPECTED_SOURCE), WithToolType(ToolType::FINGER));
                AllOf(WithSource(AINPUT_SOURCE_TOUCHSCREEN), WithToolType(ToolType::FINGER));
        // The first pointer is withheld when an external stylus is connected,
        // and a timeout is requested.
@@ -7490,7 +7511,7 @@ private:
TEST_F(ExternalStylusFusionTest, UsesBluetoothStylusSource) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    ASSERT_EQ(EXPECTED_SOURCE, mapper.getSources());
    ASSERT_EQ(STYLUS_FUSION_SOURCE, mapper.getSources());
}
TEST_F(ExternalStylusFusionTest, UnsuccessfulFusion) {
@@ -7507,8 +7528,7 @@ TEST_F(ExternalStylusFusionTest, SuccessfulFusion_TouchFirst) {
// before the touch is reported by the touchscreen.
TEST_F(ExternalStylusFusionTest, SuccessfulFusion_PressureFirst) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    auto toolTypeSource =
            AllOf(WithSource(EXPECTED_SOURCE), WithToolType(ToolType::STYLUS));
    auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
    // The external stylus reports pressure first. It is ignored for now.
    mStylusState.pressure = 1.f;
@@ -7550,8 +7570,7 @@ TEST_F(ExternalStylusFusionTest, FusionIsRepeatedForEachNewGesture) {
TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    auto toolTypeSource =
            AllOf(WithSource(EXPECTED_SOURCE), WithToolType(ToolType::STYLUS));
    auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
    mStylusState.pressure = 0.8f;
    processExternalStylusState(mapper);
@@ -7612,7 +7631,7 @@ TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
    processUp(mapper);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(EXPECTED_SOURCE),
            AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(STYLUS_FUSION_SOURCE),
                  WithToolType(ToolType::STYLUS))));
    ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertTimeoutWasNotRequested());
@@ -7621,7 +7640,7 @@ TEST_F(ExternalStylusFusionTest, FusedPointerReportsPressureChanges) {
TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    auto source = WithSource(EXPECTED_SOURCE);
    auto source = WithSource(STYLUS_FUSION_SOURCE);
    mStylusState.pressure = 1.f;
    mStylusState.toolType = ToolType::ERASER;
@@ -7674,8 +7693,7 @@ TEST_F(ExternalStylusFusionTest, FusedPointerReportsToolTypeChanges) {
TEST_F(ExternalStylusFusionTest, FusedPointerReportsButtons) {
    SingleTouchInputMapper& mapper = initializeInputMapperWithExternalStylus();
    auto toolTypeSource =
            AllOf(WithSource(EXPECTED_SOURCE), WithToolType(ToolType::STYLUS));
    auto toolTypeSource = AllOf(WithSource(STYLUS_FUSION_SOURCE), WithToolType(ToolType::STYLUS));
    ASSERT_NO_FATAL_FAILURE(testStartFusedStylusGesture(mapper));