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

Commit 0b71d9b3 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Add TouchIntegrationTest tests" into rvc-dev am: f49a7c47

Change-Id: I08b75d61b2d12df64db12aba0eb280482aa99b36
parents b29b62f7 f49a7c47
Loading
Loading
Loading
Loading
+130 −2
Original line number Original line Diff line number Diff line
@@ -1748,7 +1748,7 @@ protected:


    virtual void SetUp() override {
    virtual void SetUp() override {
        mFakePolicy = new FakeInputReaderPolicy();
        mFakePolicy = new FakeInputReaderPolicy();
        mTestListener = new TestInputListener();
        mTestListener = new TestInputListener(50ms);


        mReader = new InputReader(std::make_shared<EventHub>(), mFakePolicy, mTestListener);
        mReader = new InputReader(std::make_shared<EventHub>(), mFakePolicy, mTestListener);
        ASSERT_EQ(mReader->start(), OK);
        ASSERT_EQ(mReader->start(), OK);
@@ -1847,6 +1847,135 @@ TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
    ASSERT_LE(prevTimestamp, keyArgs.eventTime);
    ASSERT_LE(prevTimestamp, keyArgs.eventTime);
}
}


// --- TouchProcessTest ---
class TouchIntegrationTest : public InputReaderIntegrationTest {
protected:
    static const int32_t FIRST_SLOT = 0;
    static const int32_t SECOND_SLOT = 1;
    static const int32_t FIRST_TRACKING_ID = 0;
    static const int32_t SECOND_TRACKING_ID = 1;
    const std::string UNIQUE_ID = "local:0";

    virtual void SetUp() override {
        InputReaderIntegrationTest::SetUp();
        // At least add an internal display.
        setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
                                     DISPLAY_ORIENTATION_0, UNIQUE_ID, NO_PORT,
                                     ViewportType::VIEWPORT_INTERNAL);

        mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
        ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
        ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
    }

    void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
                                      int32_t orientation, const std::string& uniqueId,
                                      std::optional<uint8_t> physicalPort,
                                      ViewportType viewportType) {
        mFakePolicy->addDisplayViewport(displayId, width, height, orientation, uniqueId,
                                        physicalPort, viewportType);
        mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
    }

    std::unique_ptr<UinputTouchScreen> mDevice;
};

TEST_F(TouchIntegrationTest, InputEvent_ProcessSingleTouch) {
    NotifyMotionArgs args;
    const Point centerPoint = mDevice->getCenterPoint();

    // ACTION_DOWN
    mDevice->sendDown(centerPoint);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);

    // ACTION_MOVE
    mDevice->sendMove(centerPoint + Point(1, 1));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);

    // ACTION_UP
    mDevice->sendUp();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
}

TEST_F(TouchIntegrationTest, InputEvent_ProcessMultiTouch) {
    NotifyMotionArgs args;
    const Point centerPoint = mDevice->getCenterPoint();

    // ACTION_DOWN
    mDevice->sendDown(centerPoint);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);

    // ACTION_POINTER_DOWN (Second slot)
    const Point secondPoint = centerPoint + Point(100, 100);
    mDevice->sendSlot(SECOND_SLOT);
    mDevice->sendTrackingId(SECOND_TRACKING_ID);
    mDevice->sendDown(secondPoint + Point(1, 1));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
              args.action);

    // ACTION_MOVE (Second slot)
    mDevice->sendMove(secondPoint);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);

    // ACTION_POINTER_UP (Second slot)
    mDevice->sendUp();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
              args.action);

    // ACTION_UP
    mDevice->sendSlot(FIRST_SLOT);
    mDevice->sendUp();
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
}

TEST_F(TouchIntegrationTest, InputEvent_ProcessPalm) {
    NotifyMotionArgs args;
    const Point centerPoint = mDevice->getCenterPoint();

    // ACTION_DOWN
    mDevice->sendDown(centerPoint);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);

    // ACTION_POINTER_DOWN (Second slot)
    const Point secondPoint = centerPoint + Point(100, 100);
    mDevice->sendSlot(SECOND_SLOT);
    mDevice->sendTrackingId(SECOND_TRACKING_ID);
    mDevice->sendDown(secondPoint);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
              args.action);

    // ACTION_MOVE (Second slot)
    mDevice->sendMove(secondPoint + Point(1, 1));
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);

    // Send MT_TOOL_PALM, which indicates that the touch IC has determined this to be a grip event.
    // Expect to receive ACTION_CANCEL, to abort the entire gesture.
    mDevice->sendToolType(MT_TOOL_PALM);
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(&args));
    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, args.action);

    // ACTION_POINTER_UP (Second slot)
    mDevice->sendUp();

    // ACTION_UP
    mDevice->sendSlot(FIRST_SLOT);
    mDevice->sendUp();

    // Expect no event received after abort the entire gesture.
    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
}

// --- InputDeviceTest ---
// --- InputDeviceTest ---
class InputDeviceTest : public testing::Test {
class InputDeviceTest : public testing::Test {
protected:
protected:
@@ -7032,5 +7161,4 @@ TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
    ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
}
}

} // namespace android
} // namespace android
+5 −14
Original line number Original line Diff line number Diff line
@@ -19,20 +19,11 @@


#include "TestInputListener.h"
#include "TestInputListener.h"


namespace {

using std::chrono_literals::operator""ms;

// Timeout for waiting for an expected event
static constexpr std::chrono::duration WAIT_TIMEOUT = 5ms;

} // namespace

namespace android {
namespace android {


// --- TestInputListener ---
// --- TestInputListener ---


TestInputListener::TestInputListener() { }
TestInputListener::TestInputListener(const std::chrono::milliseconds timeout) : mTimeout(timeout) {}


TestInputListener::~TestInputListener() { }
TestInputListener::~TestInputListener() { }


@@ -95,9 +86,9 @@ void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string m


    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
    if (queue.empty()) {
    if (queue.empty()) {
        const bool eventReceived =
        const bool eventReceived = mCondition.wait_for(lock, mTimeout, [&queue]() REQUIRES(mLock) {
                mCondition.wait_for(lock, WAIT_TIMEOUT,
            return !queue.empty();
                                    [&queue]() REQUIRES(mLock) { return !queue.empty(); });
        });
        if (!eventReceived) {
        if (!eventReceived) {
            FAIL() << "Timed out waiting for event: " << message.c_str();
            FAIL() << "Timed out waiting for event: " << message.c_str();
        }
        }
@@ -114,7 +105,7 @@ void TestInputListener::assertNotCalled(std::string message) {
    base::ScopedLockAssertion assumeLocked(mLock);
    base::ScopedLockAssertion assumeLocked(mLock);


    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
    std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
    const bool eventReceived = mCondition.wait_for(lock, WAIT_TIMEOUT, [&queue]() REQUIRES(mLock) {
    const bool eventReceived = mCondition.wait_for(lock, mTimeout, [&queue]() REQUIRES(mLock) {
        return !queue.empty();
        return !queue.empty();
    });
    });
    if (eventReceived) {
    if (eventReceived) {
+4 −1
Original line number Original line Diff line number Diff line
@@ -21,6 +21,8 @@
#include <gtest/gtest.h>
#include <gtest/gtest.h>
#include "InputListener.h"
#include "InputListener.h"


using std::chrono_literals::operator""ms;

namespace android {
namespace android {


// --- TestInputListener ---
// --- TestInputListener ---
@@ -30,7 +32,7 @@ protected:
    virtual ~TestInputListener();
    virtual ~TestInputListener();


public:
public:
    TestInputListener();
    TestInputListener(const std::chrono::milliseconds timeout = 5ms);


    void assertNotifyConfigurationChangedWasCalled(
    void assertNotifyConfigurationChangedWasCalled(
            NotifyConfigurationChangedArgs* outEventArgs = nullptr);
            NotifyConfigurationChangedArgs* outEventArgs = nullptr);
@@ -73,6 +75,7 @@ private:


    std::mutex mLock;
    std::mutex mLock;
    std::condition_variable mCondition;
    std::condition_variable mCondition;
    const std::chrono::milliseconds mTimeout;


    std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
    std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
               std::vector<NotifyDeviceResetArgs>,          //
               std::vector<NotifyDeviceResetArgs>,          //
+68 −1
Original line number Original line Diff line number Diff line
@@ -127,4 +127,71 @@ void UinputHomeKey::pressAndReleaseHomeKey() {
    EXPECT_NO_FATAL_FAILURE(pressAndReleaseKey(KEY_HOME));
    EXPECT_NO_FATAL_FAILURE(pressAndReleaseKey(KEY_HOME));
}
}


// --- UinputTouchScreen ---
UinputTouchScreen::UinputTouchScreen(const Rect* size)
      : UinputDevice(UinputTouchScreen::DEVICE_NAME), mSize(*size) {}

void UinputTouchScreen::configureDevice(int fd, uinput_user_dev* device) {
    // Setup the touch screen device
    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_EVBIT, EV_REL);
    ioctl(fd, UI_SET_EVBIT, EV_ABS);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
    ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE);
    ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
    ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH);

    device->absmin[ABS_MT_SLOT] = RAW_SLOT_MIN;
    device->absmax[ABS_MT_SLOT] = RAW_SLOT_MAX;
    device->absmin[ABS_MT_TOUCH_MAJOR] = RAW_TOUCH_MIN;
    device->absmax[ABS_MT_TOUCH_MAJOR] = RAW_TOUCH_MAX;
    device->absmin[ABS_MT_POSITION_X] = mSize.left;
    device->absmax[ABS_MT_POSITION_X] = mSize.right - 1;
    device->absmin[ABS_MT_POSITION_Y] = mSize.top;
    device->absmax[ABS_MT_POSITION_Y] = mSize.bottom - 1;
    device->absmin[ABS_MT_TRACKING_ID] = RAW_ID_MIN;
    device->absmax[ABS_MT_TRACKING_ID] = RAW_ID_MAX;
}

void UinputTouchScreen::sendSlot(int32_t slot) {
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_SLOT, slot));
}

void UinputTouchScreen::sendTrackingId(int32_t trackingId) {
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TRACKING_ID, trackingId));
}

void UinputTouchScreen::sendDown(const Point& point) {
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 1));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
}

void UinputTouchScreen::sendMove(const Point& point) {
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
}

void UinputTouchScreen::sendUp() {
    sendTrackingId(0xffffffff);
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_KEY, BTN_TOUCH, 0));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
}

void UinputTouchScreen::sendToolType(int32_t toolType) {
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_ABS, ABS_MT_TOOL_TYPE, toolType));
    EXPECT_NO_FATAL_FAILURE(injectEvent(EV_SYN, SYN_REPORT, 0));
}

// Get the center x, y base on the range definition.
const Point UinputTouchScreen::getCenterPoint() {
    return Point(mSize.left + mSize.width() / 2, mSize.top + mSize.height() / 2);
}

} // namespace android
} // namespace android
+36 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@
#include <inttypes.h>
#include <inttypes.h>
#include <linux/uinput.h>
#include <linux/uinput.h>
#include <log/log.h>
#include <log/log.h>
#include <ui/Point.h>
#include <ui/Rect.h>


#include <memory>
#include <memory>


@@ -106,6 +108,40 @@ private:
    UinputHomeKey();
    UinputHomeKey();
};
};


// --- UinputTouchScreen ---
// A touch screen device with specific size.
class UinputTouchScreen : public UinputDevice {
public:
    static constexpr const char* DEVICE_NAME = "Test Touch Screen";
    static const int32_t RAW_TOUCH_MIN = 0;
    static const int32_t RAW_TOUCH_MAX = 31;
    static const int32_t RAW_ID_MIN = 0;
    static const int32_t RAW_ID_MAX = 9;
    static const int32_t RAW_SLOT_MIN = 0;
    static const int32_t RAW_SLOT_MAX = 9;
    static const int32_t RAW_PRESSURE_MIN = 0;
    static const int32_t RAW_PRESSURE_MAX = 255;

    template <class D, class... Ts>
    friend std::unique_ptr<D> createUinputDevice(Ts... args);

    void sendSlot(int32_t slot);
    void sendTrackingId(int32_t trackingId);
    void sendDown(const Point& point);
    void sendMove(const Point& point);
    void sendUp();
    void sendToolType(int32_t toolType);

    const Point getCenterPoint();

protected:
    UinputTouchScreen(const Rect* size);

private:
    void configureDevice(int fd, uinput_user_dev* device) override;
    const Rect mSize;
};

} // namespace android
} // namespace android


#endif // _UI_TEST_INPUT_UINPUT_INJECTOR_H
#endif // _UI_TEST_INPUT_UINPUT_INJECTOR_H