Return events from EventHub
Rather than filling some buffer, EventHub will now return events
explicitly. This will simplify the interface and avoid storing the
buffer when no events are being actively produced.
Bug: 211379801
Test: atest libinput_tests inputflinger_tests
Change-Id: Ic4ba7789f899b2de9fbe5a0abe54475b74eb5f82
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 5351a51..5c24244 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -76,6 +76,8 @@
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+static constexpr size_t EVENT_BUFFER_SIZE = 256;
+
// Mapping for input battery class node IDs lookup.
// https://www.kernel.org/doc/Documentation/power/power_supply_class.txt
static const std::unordered_map<std::string, InputBatteryClass> BATTERY_CLASSES =
@@ -1633,14 +1635,13 @@
return std::nullopt;
}
-size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
- ALOG_ASSERT(bufferSize >= 1);
-
+std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
std::scoped_lock _l(mLock);
+ constexpr size_t bufferSize = EVENT_BUFFER_SIZE;
struct input_event readBuffer[bufferSize];
- RawEvent* event = buffer;
+ std::vector<RawEvent> events;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
@@ -1661,15 +1662,17 @@
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
std::unique_ptr<Device> device = std::move(*it);
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
- event->when = now;
- event->deviceId = (device->id == mBuiltInKeyboardId)
+ const int32_t deviceId = (device->id == mBuiltInKeyboardId)
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
: device->id;
- event->type = DEVICE_REMOVED;
- event += 1;
+ events.push_back({
+ .when = now,
+ .deviceId = deviceId,
+ .type = DEVICE_REMOVED,
+ });
it = mClosingDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
+ if (events.size() == capacity) {
break;
}
}
@@ -1684,10 +1687,12 @@
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- event->type = DEVICE_ADDED;
- event += 1;
+ const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
+ events.push_back({
+ .when = now,
+ .deviceId = deviceId,
+ .type = DEVICE_ADDED,
+ });
// Try to find a matching video device by comparing device names
for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
@@ -1705,17 +1710,18 @@
ALOGW("Device id %d exists, replaced.", device->id);
}
mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
+ if (events.size() == capacity) {
break;
}
}
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
- event->when = now;
- event->type = FINISHED_DEVICE_SCAN;
- event += 1;
- if (--capacity == 0) {
+ events.push_back({
+ .when = now,
+ .type = FINISHED_DEVICE_SCAN,
+ });
+ if (events.size() == capacity) {
break;
}
}
@@ -1794,21 +1800,21 @@
} else if ((readSize % sizeof(struct input_event)) != 0) {
ALOGE("could not get event (wrong size: %d)", readSize);
} else {
- int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
+ const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- size_t count = size_t(readSize) / sizeof(struct input_event);
+ const size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
- event->when = processEventTimestamp(iev);
- event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
- event->deviceId = deviceId;
- event->type = iev.type;
- event->code = iev.code;
- event->value = iev.value;
- event += 1;
- capacity -= 1;
+ events.push_back({
+ .when = processEventTimestamp(iev),
+ .readTime = systemTime(SYSTEM_TIME_MONOTONIC),
+ .deviceId = deviceId,
+ .type = iev.type,
+ .code = iev.code,
+ .value = iev.value,
+ });
}
- if (capacity == 0) {
+ if (events.size() >= capacity) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
@@ -1844,7 +1850,7 @@
}
// Return now if we have collected any events or if we were explicitly awoken.
- if (event != buffer || awoken) {
+ if (!events.empty() || awoken) {
break;
}
@@ -1890,7 +1896,7 @@
}
// All done, return the number of events we read.
- return event - buffer;
+ return events;
}
std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 4c38ce8..8650876 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -120,14 +120,14 @@
}
} // release lock
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
+ std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
- if (count) {
- processEventsLocked(mEventBuffer, count);
+ if (!events.empty()) {
+ processEventsLocked(events.data(), events.size());
}
if (mNextTimeout != LLONG_MAX) {
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 6b8cc25..2eeb3f4 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -282,7 +282,7 @@
*
* Returns the number of events obtained, or 0 if the timeout expired.
*/
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
+ virtual std::vector<RawEvent> getEvents(int timeoutMillis) = 0;
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
int32_t deviceId, int32_t absCode) const = 0;
@@ -500,7 +500,7 @@
bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const override final;
- size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override final;
+ std::vector<RawEvent> getEvents(int timeoutMillis) override final;
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override final;
bool hasScanCode(int32_t deviceId, int32_t scanCode) const override final;
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index fbce87f..012d43f 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -170,10 +170,6 @@
InputReaderConfiguration mConfig GUARDED_BY(mLock);
- // The event queue.
- static const int EVENT_BUFFER_SIZE = 256;
- RawEvent mEventBuffer[EVENT_BUFFER_SIZE] GUARDED_BY(mLock);
-
// An input device can represent a collection of EventHub devices. This map provides a way
// to lookup the input device instance from the EventHub device id.
std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index 6ef6e44..9380c71 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -99,8 +99,6 @@
};
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) {
@@ -108,12 +106,12 @@
if (expectedEvents) {
timeout = 2s;
}
- const size_t count =
- mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
- if (count == 0) {
+
+ std::vector<RawEvent> newEvents = mEventHub->getEvents(timeout.count());
+ if (newEvents.empty()) {
break;
}
- events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
+ events.insert(events.end(), newEvents.begin(), newEvents.end());
if (expectedEvents && events.size() >= *expectedEvents) {
break;
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index f1f1abd..b36b498 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -826,15 +826,14 @@
mExcludedDevices = devices;
}
- size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+ std::vector<RawEvent> getEvents(int) override {
std::scoped_lock lock(mLock);
- const size_t filledSize = std::min(mEvents.size(), bufferSize);
- std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+ std::vector<RawEvent> buffer;
+ std::swap(buffer, mEvents);
- mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
mEventsCondition.notify_all();
- return filledSize;
+ return buffer;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index f5bd297..a9f5a3a 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -169,7 +169,6 @@
std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
std::unique_ptr<FuzzInputReader> reader =
std::make_unique<FuzzInputReader>(fuzzEventHub, fuzzPolicy, fuzzListener);
- fuzzEventHub->addEvents(fdp);
size_t patternCount = fdp->ConsumeIntegralInRange<size_t>(1, 260);
VibrationSequence pattern(patternCount);
for (size_t i = 0; i < patternCount; ++i) {
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 53a7b16..03c2266 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -114,30 +114,12 @@
InputDeviceIdentifier mIdentifier;
std::vector<TouchVideoFrame> mVideoFrames;
PropertyMap mFuzzConfig;
- size_t mCount = 0;
- std::array<RawEvent, kMaxSize> mBuf;
std::shared_ptr<FuzzedDataProvider> mFdp;
public:
FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {}
~FuzzEventHub() {}
void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); }
- void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) {
- mCount = fdp->ConsumeIntegralInRange<size_t>(0, kMaxSize);
-
- for (size_t i = 0; i < mCount; ++i) {
- int32_t type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes)
- : fdp->ConsumeIntegral<int32_t>();
- int32_t code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes)
- : fdp->ConsumeIntegral<int32_t>();
- mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(),
- fdp->ConsumeIntegral<nsecs_t>(),
- fdp->ConsumeIntegral<int32_t>(),
- type,
- code,
- fdp->ConsumeIntegral<int32_t>()};
- }
- }
ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
return ftl::Flags<InputDeviceClass>(mFdp->ConsumeIntegral<uint32_t>());
@@ -168,10 +150,24 @@
return mFdp->ConsumeIntegral<status_t>();
}
void setExcludedDevices(const std::vector<std::string>& devices) override {}
- size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override {
- for (size_t i = 0; i < mCount; ++i) buffer[i] = mBuf[i];
-
- return mCount;
+ std::vector<RawEvent> getEvents(int timeoutMillis) override {
+ std::vector<RawEvent> events;
+ const size_t count = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxSize);
+ for (size_t i = 0; i < count; ++i) {
+ int32_t type = mFdp->ConsumeBool() ? mFdp->PickValueInArray(kValidTypes)
+ : mFdp->ConsumeIntegral<int32_t>();
+ int32_t code = mFdp->ConsumeBool() ? mFdp->PickValueInArray(kValidCodes)
+ : mFdp->ConsumeIntegral<int32_t>();
+ events.push_back({
+ .when = mFdp->ConsumeIntegral<nsecs_t>(),
+ .readTime = mFdp->ConsumeIntegral<nsecs_t>(),
+ .deviceId = mFdp->ConsumeIntegral<int32_t>(),
+ .type = type,
+ .code = code,
+ .value = mFdp->ConsumeIntegral<int32_t>(),
+ });
+ }
+ return events;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; }