You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
10 KiB
275 lines
10 KiB
/*
|
|
* Copyright (C) 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "EventHub.h"
|
|
|
|
#include "UinputDevice.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <inttypes.h>
|
|
#include <linux/uinput.h>
|
|
#include <log/log.h>
|
|
#include <chrono>
|
|
|
|
#define TAG "EventHub_test"
|
|
|
|
using android::createUinputDevice;
|
|
using android::EventHub;
|
|
using android::EventHubInterface;
|
|
using android::InputDeviceIdentifier;
|
|
using android::RawEvent;
|
|
using android::sp;
|
|
using android::UinputHomeKey;
|
|
using std::chrono_literals::operator""ms;
|
|
using std::chrono_literals::operator""s;
|
|
|
|
static constexpr bool DEBUG = false;
|
|
|
|
static void dumpEvents(const std::vector<RawEvent>& events) {
|
|
for (const RawEvent& event : events) {
|
|
if (event.type >= EventHubInterface::FIRST_SYNTHETIC_EVENT) {
|
|
switch (event.type) {
|
|
case EventHubInterface::DEVICE_ADDED:
|
|
ALOGI("Device added: %i", event.deviceId);
|
|
break;
|
|
case EventHubInterface::DEVICE_REMOVED:
|
|
ALOGI("Device removed: %i", event.deviceId);
|
|
break;
|
|
case EventHubInterface::FINISHED_DEVICE_SCAN:
|
|
ALOGI("Finished device scan.");
|
|
break;
|
|
}
|
|
} else {
|
|
ALOGI("Device %" PRId32 " : time = %" PRId64 ", type %i, code %i, value %i",
|
|
event.deviceId, event.when, event.type, event.code, event.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- EventHubTest ---
|
|
class EventHubTest : public testing::Test {
|
|
protected:
|
|
std::unique_ptr<EventHubInterface> mEventHub;
|
|
// We are only going to emulate a single input device currently.
|
|
std::unique_ptr<UinputHomeKey> mKeyboard;
|
|
int32_t mDeviceId;
|
|
|
|
virtual void SetUp() override {
|
|
mEventHub = std::make_unique<EventHub>();
|
|
consumeInitialDeviceAddedEvents();
|
|
mKeyboard = createUinputDevice<UinputHomeKey>();
|
|
ASSERT_NO_FATAL_FAILURE(mDeviceId = waitForDeviceCreation());
|
|
}
|
|
virtual void TearDown() override {
|
|
mKeyboard.reset();
|
|
waitForDeviceClose(mDeviceId);
|
|
assertNoMoreEvents();
|
|
}
|
|
|
|
/**
|
|
* Return the device id of the created device.
|
|
*/
|
|
int32_t waitForDeviceCreation();
|
|
void waitForDeviceClose(int32_t deviceId);
|
|
void consumeInitialDeviceAddedEvents();
|
|
void assertNoMoreEvents();
|
|
/**
|
|
* Read events from the EventHub.
|
|
*
|
|
* If expectedEvents is set, wait for a significant period of time to try and ensure that
|
|
* the expected number of events has been read. The number of returned events
|
|
* may be smaller (if timeout has been reached) or larger than expectedEvents.
|
|
*
|
|
* If expectedEvents is not set, return all of the immediately available events.
|
|
*/
|
|
std::vector<RawEvent> getEvents(std::optional<size_t> expectedEvents = std::nullopt);
|
|
};
|
|
|
|
std::vector<RawEvent> EventHubTest::getEvents(std::optional<size_t> expectedEvents) {
|
|
static constexpr size_t EVENT_BUFFER_SIZE = 256;
|
|
std::array<RawEvent, EVENT_BUFFER_SIZE> eventBuffer;
|
|
std::vector<RawEvent> events;
|
|
|
|
while (true) {
|
|
std::chrono::milliseconds timeout = 0s;
|
|
if (expectedEvents) {
|
|
timeout = 2s;
|
|
}
|
|
const size_t count =
|
|
mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
|
|
if (count == 0) {
|
|
break;
|
|
}
|
|
events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
|
|
if (expectedEvents && events.size() >= *expectedEvents) {
|
|
break;
|
|
}
|
|
}
|
|
if (DEBUG) {
|
|
dumpEvents(events);
|
|
}
|
|
return events;
|
|
}
|
|
|
|
/**
|
|
* Since the test runs on a real platform, there will be existing devices
|
|
* in addition to the test devices being added. Therefore, when EventHub is first created,
|
|
* it will return a lot of "device added" type of events.
|
|
*/
|
|
void EventHubTest::consumeInitialDeviceAddedEvents() {
|
|
std::vector<RawEvent> events = getEvents();
|
|
std::set<int32_t /*deviceId*/> existingDevices;
|
|
// All of the events should be DEVICE_ADDED type, except the last one.
|
|
for (size_t i = 0; i < events.size() - 1; i++) {
|
|
const RawEvent& event = events[i];
|
|
EXPECT_EQ(EventHubInterface::DEVICE_ADDED, event.type);
|
|
existingDevices.insert(event.deviceId);
|
|
}
|
|
// None of the existing system devices should be changing while this test is run.
|
|
// Check that the returned device ids are unique for all of the existing devices.
|
|
EXPECT_EQ(existingDevices.size(), events.size() - 1);
|
|
// The last event should be "finished device scan"
|
|
EXPECT_EQ(EventHubInterface::FINISHED_DEVICE_SCAN, events[events.size() - 1].type);
|
|
}
|
|
|
|
int32_t EventHubTest::waitForDeviceCreation() {
|
|
// Wait a little longer than usual, to ensure input device has time to be created
|
|
std::vector<RawEvent> events = getEvents(2);
|
|
if (events.size() != 2) {
|
|
ADD_FAILURE() << "Instead of 2 events, received " << events.size();
|
|
return 0; // this value is unused
|
|
}
|
|
const RawEvent& deviceAddedEvent = events[0];
|
|
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_ADDED), deviceAddedEvent.type);
|
|
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceAddedEvent.deviceId);
|
|
const int32_t deviceId = deviceAddedEvent.deviceId;
|
|
EXPECT_EQ(identifier.name, mKeyboard->getName());
|
|
const RawEvent& finishedDeviceScanEvent = events[1];
|
|
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
|
|
finishedDeviceScanEvent.type);
|
|
return deviceId;
|
|
}
|
|
|
|
void EventHubTest::waitForDeviceClose(int32_t deviceId) {
|
|
std::vector<RawEvent> events = getEvents(2);
|
|
ASSERT_EQ(2U, events.size());
|
|
const RawEvent& deviceRemovedEvent = events[0];
|
|
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::DEVICE_REMOVED), deviceRemovedEvent.type);
|
|
EXPECT_EQ(deviceId, deviceRemovedEvent.deviceId);
|
|
const RawEvent& finishedDeviceScanEvent = events[1];
|
|
EXPECT_EQ(static_cast<int32_t>(EventHubInterface::FINISHED_DEVICE_SCAN),
|
|
finishedDeviceScanEvent.type);
|
|
}
|
|
|
|
void EventHubTest::assertNoMoreEvents() {
|
|
std::vector<RawEvent> events = getEvents();
|
|
ASSERT_TRUE(events.empty());
|
|
}
|
|
|
|
/**
|
|
* Ensure that input_events are generated with monotonic clock.
|
|
* That means input_event should receive a timestamp that is in the future of the time
|
|
* before the event was sent.
|
|
* Input system uses CLOCK_MONOTONIC everywhere in the code base.
|
|
*/
|
|
TEST_F(EventHubTest, InputEvent_TimestampIsMonotonic) {
|
|
nsecs_t lastEventTime = systemTime(SYSTEM_TIME_MONOTONIC);
|
|
ASSERT_NO_FATAL_FAILURE(mKeyboard->pressAndReleaseHomeKey());
|
|
|
|
std::vector<RawEvent> events = getEvents(4);
|
|
ASSERT_EQ(4U, events.size()) << "Expected to receive 2 keys and 2 syncs, total of 4 events";
|
|
for (const RawEvent& event : events) {
|
|
// Cannot use strict comparison because the events may happen too quickly
|
|
ASSERT_LE(lastEventTime, event.when) << "Event must have occurred after the key was sent";
|
|
ASSERT_LT(std::chrono::nanoseconds(event.when - lastEventTime), 100ms)
|
|
<< "Event times are too far apart";
|
|
lastEventTime = event.when; // Ensure all returned events are monotonic
|
|
}
|
|
}
|
|
|
|
// --- BitArrayTest ---
|
|
class BitArrayTest : public testing::Test {
|
|
protected:
|
|
static constexpr size_t SINGLE_ELE_BITS = 32UL;
|
|
static constexpr size_t MULTI_ELE_BITS = 256UL;
|
|
|
|
virtual void SetUp() override {
|
|
mBitmaskSingle.loadFromBuffer(mBufferSingle);
|
|
mBitmaskMulti.loadFromBuffer(mBufferMulti);
|
|
}
|
|
|
|
android::BitArray<SINGLE_ELE_BITS> mBitmaskSingle;
|
|
android::BitArray<MULTI_ELE_BITS> mBitmaskMulti;
|
|
|
|
private:
|
|
const typename android::BitArray<SINGLE_ELE_BITS>::Buffer mBufferSingle = {
|
|
0x800F0F0FUL // bit 0 - 31
|
|
};
|
|
const typename android::BitArray<MULTI_ELE_BITS>::Buffer mBufferMulti = {
|
|
0xFFFFFFFFUL, // bit 0 - 31
|
|
0x01000001UL, // bit 32 - 63
|
|
0x00000000UL, // bit 64 - 95
|
|
0x80000000UL, // bit 96 - 127
|
|
0x00000000UL, // bit 128 - 159
|
|
0x00000000UL, // bit 160 - 191
|
|
0x80000008UL, // bit 192 - 223
|
|
0x00000000UL, // bit 224 - 255
|
|
};
|
|
};
|
|
|
|
TEST_F(BitArrayTest, SetBit) {
|
|
ASSERT_TRUE(mBitmaskSingle.test(0));
|
|
ASSERT_TRUE(mBitmaskSingle.test(31));
|
|
ASSERT_FALSE(mBitmaskSingle.test(7));
|
|
|
|
ASSERT_TRUE(mBitmaskMulti.test(32));
|
|
ASSERT_TRUE(mBitmaskMulti.test(56));
|
|
ASSERT_FALSE(mBitmaskMulti.test(192));
|
|
ASSERT_TRUE(mBitmaskMulti.test(223));
|
|
ASSERT_FALSE(mBitmaskMulti.test(255));
|
|
}
|
|
|
|
TEST_F(BitArrayTest, AnyBit) {
|
|
ASSERT_TRUE(mBitmaskSingle.any(31, 32));
|
|
ASSERT_FALSE(mBitmaskSingle.any(12, 16));
|
|
|
|
ASSERT_TRUE(mBitmaskMulti.any(31, 32));
|
|
ASSERT_FALSE(mBitmaskMulti.any(33, 33));
|
|
ASSERT_TRUE(mBitmaskMulti.any(32, 55));
|
|
ASSERT_TRUE(mBitmaskMulti.any(33, 57));
|
|
ASSERT_FALSE(mBitmaskMulti.any(33, 55));
|
|
ASSERT_FALSE(mBitmaskMulti.any(130, 190));
|
|
|
|
ASSERT_FALSE(mBitmaskMulti.any(128, 195));
|
|
ASSERT_TRUE(mBitmaskMulti.any(128, 196));
|
|
ASSERT_TRUE(mBitmaskMulti.any(128, 224));
|
|
ASSERT_FALSE(mBitmaskMulti.any(255, 256));
|
|
}
|
|
|
|
TEST_F(BitArrayTest, SetBit_InvalidBitIndex) {
|
|
ASSERT_FALSE(mBitmaskSingle.test(32));
|
|
ASSERT_FALSE(mBitmaskMulti.test(256));
|
|
}
|
|
|
|
TEST_F(BitArrayTest, AnyBit_InvalidBitIndex) {
|
|
ASSERT_FALSE(mBitmaskSingle.any(32, 32));
|
|
ASSERT_FALSE(mBitmaskSingle.any(33, 34));
|
|
|
|
ASSERT_FALSE(mBitmaskMulti.any(256, 256));
|
|
ASSERT_FALSE(mBitmaskMulti.any(257, 258));
|
|
ASSERT_FALSE(mBitmaskMulti.any(0, 0));
|
|
}
|