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

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

Address additional comments: Pointer icon refactor for touch/stylus

Bug: 293587049
Test: atest inputflinger_tests
Change-Id: Ic628105276fb06770932f05907598e95fcc1cafb
parent d6fe27b5
Loading
Loading
Loading
Loading
+14 −57
Original line number Diff line number Diff line
@@ -45,7 +45,11 @@ bool isStylusHoverEvent(const NotifyMotionArgs& args) {

PointerChoreographer::PointerChoreographer(InputListenerInterface& listener,
                                           PointerChoreographerPolicyInterface& policy)
      : mNextListener(listener),
      : mTouchControllerConstructor([this]() REQUIRES(mLock) {
            return mPolicy.createPointerController(
                    PointerControllerInterface::ControllerType::TOUCH);
        }),
        mNextListener(listener),
        mPolicy(policy),
        mDefaultMouseDisplayId(ADISPLAY_ID_DEFAULT),
        mNotifiedPointerDisplayId(ADISPLAY_ID_NONE),
@@ -141,8 +145,7 @@ void PointerChoreographer::processTouchscreenAndStylusEventLocked(const NotifyMo
    }

    // Get the touch pointer controller for the device, or create one if it doesn't exist.
    auto [it, _] =
            mTouchPointersByDevice.try_emplace(args.deviceId, getTouchControllerConstructor());
    auto [it, _] = mTouchPointersByDevice.try_emplace(args.deviceId, mTouchControllerConstructor);

    PointerControllerInterface& pc = *it->second;

@@ -213,28 +216,8 @@ void PointerChoreographer::notifyDeviceReset(const NotifyDeviceResetArgs& args)

void PointerChoreographer::processDeviceReset(const NotifyDeviceResetArgs& args) {
    std::scoped_lock _l(mLock);

    const InputDeviceInfo* info = findInputDeviceLocked(args.deviceId);
    if (info == nullptr) {
        return;
    }

    const uint32_t sources = info->getSources();
    const int32_t displayId = info->getAssociatedDisplayId();
    if (isFromSource(sources, AINPUT_SOURCE_TOUCHSCREEN) && mShowTouchesEnabled &&
        displayId != ADISPLAY_ID_NONE) {
        if (const auto it = mTouchPointersByDevice.find(args.deviceId);
            it != mTouchPointersByDevice.end()) {
            it->second->clearSpots();
        }
    }
    if (isFromSource(info->getSources(), AINPUT_SOURCE_STYLUS) && mStylusPointerIconEnabled &&
        displayId != ADISPLAY_ID_NONE) {
        if (const auto it = mStylusPointersByDevice.find(args.deviceId);
            it != mStylusPointersByDevice.end()) {
            it->second->fade(PointerControllerInterface::Transition::IMMEDIATE);
        }
    }
    mTouchPointersByDevice.erase(args.deviceId);
    mStylusPointersByDevice.erase(args.deviceId);
}

void PointerChoreographer::notifyPointerCaptureChanged(
@@ -288,12 +271,9 @@ int32_t PointerChoreographer::getTargetMouseDisplayLocked(int32_t associatedDisp
}

InputDeviceInfo* PointerChoreographer::findInputDeviceLocked(DeviceId deviceId) {
    for (auto& info : mInputDeviceInfos) {
        if (info.getId() == deviceId) {
            return &info;
        }
    }
    return nullptr;
    auto it = std::find_if(mInputDeviceInfos.begin(), mInputDeviceInfos.end(),
                           [deviceId](const auto& info) { return info.getId() == deviceId; });
    return it != mInputDeviceInfos.end() ? &(*it) : nullptr;
}

void PointerChoreographer::updatePointerControllersLocked() {
@@ -321,30 +301,14 @@ void PointerChoreographer::updatePointerControllersLocked() {
    }

    // Remove PointerControllers no longer needed.
    // This has the side-effect of fading pointers or clearing spots before removal.
    std::erase_if(mMousePointersByDisplay, [&mouseDisplaysToKeep](const auto& pair) {
        auto& [displayId, controller] = pair;
        if (mouseDisplaysToKeep.find(displayId) == mouseDisplaysToKeep.end()) {
            controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
            return true;
        }
        return false;
        return mouseDisplaysToKeep.find(pair.first) == mouseDisplaysToKeep.end();
    });
    std::erase_if(mTouchPointersByDevice, [&touchDevicesToKeep](const auto& pair) {
        auto& [deviceId, controller] = pair;
        if (touchDevicesToKeep.find(deviceId) == touchDevicesToKeep.end()) {
            controller->clearSpots();
            return true;
        }
        return false;
        return touchDevicesToKeep.find(pair.first) == touchDevicesToKeep.end();
    });
    std::erase_if(mStylusPointersByDevice, [&stylusDevicesToKeep](const auto& pair) {
        auto& [deviceId, controller] = pair;
        if (stylusDevicesToKeep.find(deviceId) == stylusDevicesToKeep.end()) {
            controller->fade(PointerControllerInterface::Transition::IMMEDIATE);
            return true;
        }
        return false;
        return stylusDevicesToKeep.find(pair.first) == stylusDevicesToKeep.end();
    });

    // Notify the policy if there's a change on the pointer display ID.
@@ -449,13 +413,6 @@ PointerChoreographer::ControllerConstructor PointerChoreographer::getMouseContro
    return ConstructorDelegate(std::move(ctor));
}

PointerChoreographer::ControllerConstructor PointerChoreographer::getTouchControllerConstructor() {
    std::function<std::shared_ptr<PointerControllerInterface>()> ctor = [this]() REQUIRES(mLock) {
        return mPolicy.createPointerController(PointerControllerInterface::ControllerType::TOUCH);
    };
    return ConstructorDelegate(std::move(ctor));
}

PointerChoreographer::ControllerConstructor PointerChoreographer::getStylusControllerConstructor(
        int32_t displayId) {
    std::function<std::shared_ptr<PointerControllerInterface>()> ctor =
+1 −1
Original line number Diff line number Diff line
@@ -105,8 +105,8 @@ private:

    using ControllerConstructor =
            ConstructorDelegate<std::function<std::shared_ptr<PointerControllerInterface>()>>;
    ControllerConstructor mTouchControllerConstructor GUARDED_BY(mLock);
    ControllerConstructor getMouseControllerConstructor(int32_t displayId) REQUIRES(mLock);
    ControllerConstructor getTouchControllerConstructor() REQUIRES(mLock);
    ControllerConstructor getStylusControllerConstructor(int32_t displayId) REQUIRES(mLock);

    std::mutex mLock;
+6 −0
Original line number Diff line number Diff line
@@ -57,6 +57,12 @@ void FakePointerController::assertPosition(float x, float y) {
    ASSERT_NEAR(y, actualY, 1);
}

void FakePointerController::assertSpotCount(int32_t displayId, int32_t count) {
    auto it = mSpotsByDisplay.find(displayId);
    ASSERT_TRUE(it != mSpotsByDisplay.end()) << "Spots not found for display " << displayId;
    ASSERT_EQ(static_cast<size_t>(count), it->second.size());
}

bool FakePointerController::isPointerShown() {
    return mIsPointerShown;
}
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ public:
    void setDisplayViewport(const DisplayViewport& viewport) override;

    void assertPosition(float x, float y);
    void assertSpotCount(int32_t displayId, int32_t count);
    bool isPointerShown();

private:
+14 −40
Original line number Diff line number Diff line
@@ -589,7 +589,6 @@ TEST_F(PointerChoreographerTest, WhenTouchEventOccursCreatesPointerController) {
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
    mChoreographer.setShowTouchesEnabled(true);
    assertPointerControllerNotCreated();

    // Emit touch event. Now PointerController should be created.
    mChoreographer.notifyMotion(
@@ -624,7 +623,6 @@ TEST_F(PointerChoreographerTest, WhenTouchDeviceIsRemovedRemovesPointerControlle
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID)}});
    mChoreographer.setShowTouchesEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .pointer(FIRST_TOUCH_POINTER)
@@ -670,9 +668,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpots) {
                    .displayId(DISPLAY_ID)
                    .build());
    auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
    auto it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(1), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 1);

    // Emit second pointer down.
    mChoreographer.notifyMotion(
@@ -684,9 +680,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpots) {
                    .deviceId(DEVICE_ID)
                    .displayId(DISPLAY_ID)
                    .build());
    it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(2), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 2);

    // Emit second pointer up.
    mChoreographer.notifyMotion(
@@ -698,9 +692,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpots) {
                    .deviceId(DEVICE_ID)
                    .displayId(DISPLAY_ID)
                    .build());
    it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(1), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 1);

    // Emit first pointer up.
    mChoreographer.notifyMotion(
@@ -709,9 +701,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpots) {
                    .deviceId(DEVICE_ID)
                    .displayId(DISPLAY_ID)
                    .build());
    it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(0), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 0);
}

TEST_F(PointerChoreographerTest, TouchSetsSpotsForStylusEvent) {
@@ -729,9 +719,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpotsForStylusEvent) {
                                        .displayId(DISPLAY_ID)
                                        .build());
    auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
    auto it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(1), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 1);
}

TEST_F(PointerChoreographerTest, TouchSetsSpotsForTwoDisplays) {
@@ -751,9 +739,7 @@ TEST_F(PointerChoreographerTest, TouchSetsSpotsForTwoDisplays) {
                    .displayId(DISPLAY_ID)
                    .build());
    auto firstDisplayPc = assertPointerControllerCreated(ControllerType::TOUCH);
    auto firstSpotsIt = firstDisplayPc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(firstSpotsIt != firstDisplayPc->getSpots().end());
    ASSERT_EQ(size_t(1), firstSpotsIt->second.size());
    firstDisplayPc->assertSpotCount(DISPLAY_ID, 1);

    // Emit touch events with second device.
    mChoreographer.notifyMotion(
@@ -774,14 +760,10 @@ TEST_F(PointerChoreographerTest, TouchSetsSpotsForTwoDisplays) {
    auto secondDisplayPc = assertPointerControllerCreated(ControllerType::TOUCH);

    // Check if the spots are set for the second device.
    auto secondSpotsIt = secondDisplayPc->getSpots().find(ANOTHER_DISPLAY_ID);
    ASSERT_TRUE(secondSpotsIt != secondDisplayPc->getSpots().end());
    ASSERT_EQ(size_t(2), secondSpotsIt->second.size());
    secondDisplayPc->assertSpotCount(ANOTHER_DISPLAY_ID, 2);

    // Check if there's no change on the spot of the first device.
    firstSpotsIt = firstDisplayPc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(firstSpotsIt != firstDisplayPc->getSpots().end());
    ASSERT_EQ(size_t(1), firstSpotsIt->second.size());
    firstDisplayPc->assertSpotCount(DISPLAY_ID, 1);
}

TEST_F(PointerChoreographerTest, WhenTouchDeviceIsResetClearsSpots) {
@@ -796,14 +778,11 @@ TEST_F(PointerChoreographerTest, WhenTouchDeviceIsResetClearsSpots) {
                    .displayId(DISPLAY_ID)
                    .build());
    auto pc = assertPointerControllerCreated(ControllerType::TOUCH);
    auto it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it != pc->getSpots().end());
    ASSERT_EQ(size_t(1), it->second.size());
    pc->assertSpotCount(DISPLAY_ID, 1);

    // Reset the device and see there's no spot.
    // Reset the device and ensure the touch pointer controller was removed.
    mChoreographer.notifyDeviceReset(NotifyDeviceResetArgs(/*id=*/1, /*eventTime=*/0, DEVICE_ID));
    it = pc->getSpots().find(DISPLAY_ID);
    ASSERT_TRUE(it == pc->getSpots().end());
    assertPointerControllerRemoved(pc);
}

TEST_F(PointerChoreographerTest,
@@ -859,7 +838,6 @@ TEST_F(PointerChoreographerTest, WhenStylusDeviceIsRemovedRemovesPointerControll
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
    mChoreographer.setStylusPointerIconEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                    .pointer(STYLUS_POINTER)
@@ -878,7 +856,6 @@ TEST_F(PointerChoreographerTest, WhenStylusPointerIconDisabledRemovesPointerCont
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
    mChoreographer.setStylusPointerIconEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                    .pointer(STYLUS_POINTER)
@@ -900,7 +877,6 @@ TEST_F(PointerChoreographerTest, SetsViewportForStylusPointerController) {
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
    mChoreographer.setStylusPointerIconEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                    .pointer(STYLUS_POINTER)
@@ -918,7 +894,6 @@ TEST_F(PointerChoreographerTest, WhenViewportIsSetLaterSetsViewportForStylusPoin
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
    mChoreographer.setStylusPointerIconEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                    .pointer(STYLUS_POINTER)
@@ -943,7 +918,6 @@ TEST_F(PointerChoreographerTest,
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
    mChoreographer.setStylusPointerIconEnabled(true);
    assertPointerControllerNotCreated();
    mChoreographer.notifyMotion(
            MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
                    .pointer(STYLUS_POINTER)
@@ -1056,7 +1030,7 @@ TEST_F(PointerChoreographerTest, StylusHoverManipulatesPointerForTwoDisplays) {
    ASSERT_TRUE(firstDisplayPc->isPointerShown());
}

TEST_F(PointerChoreographerTest, WhenStylusDeviceIsResetFadesPointer) {
TEST_F(PointerChoreographerTest, WhenStylusDeviceIsResetRemovesPointer) {
    // Make sure the PointerController is created and there is a pointer.
    mChoreographer.notifyInputDevicesChanged(
            {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID, AINPUT_SOURCE_STYLUS, DISPLAY_ID)}});
@@ -1071,9 +1045,9 @@ TEST_F(PointerChoreographerTest, WhenStylusDeviceIsResetFadesPointer) {
    auto pc = assertPointerControllerCreated(ControllerType::STYLUS);
    ASSERT_TRUE(pc->isPointerShown());

    // Reset the device and see the pointer disappeared.
    // Reset the device and see the pointer controller was removed.
    mChoreographer.notifyDeviceReset(NotifyDeviceResetArgs(/*id=*/1, /*eventTime=*/0, DEVICE_ID));
    ASSERT_FALSE(pc->isPointerShown());
    assertPointerControllerRemoved(pc);
}

} // namespace android