Merge changes I2a4359de,I08376f69 into main
* changes:
Revert "Disable stylus integration tests temporarily"
EventHub: Track the global key and switch states for enabled devices
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 4d0e13e..4e72c4c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -538,7 +538,8 @@
associatedDevice(std::move(assocDev)),
controllerNumber(0),
enabled(true),
- isVirtual(fd < 0) {}
+ isVirtual(fd < 0),
+ currentFrameDropped(false) {}
EventHub::Device::~Device() {
close();
@@ -612,6 +613,18 @@
}
bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
ALOGI("usingClockIoctl=%s", toString(usingClockIoctl));
+
+ // Query the initial state of keys and switches, which is tracked by EventHub.
+ readDeviceState();
+}
+
+void EventHub::Device::readDeviceState() {
+ if (readDeviceBitMask(EVIOCGKEY(0), keyState) < 0) {
+ ALOGD("Unable to query the global key state for %s: %s", path.c_str(), strerror(errno));
+ }
+ if (readDeviceBitMask(EVIOCGSW(0), swState) < 0) {
+ ALOGD("Unable to query the global switch state for %s: %s", path.c_str(), strerror(errno));
+ }
}
bool EventHub::Device::hasKeycodeLocked(int keycode) const {
@@ -729,6 +742,48 @@
return NAME_NOT_FOUND;
}
+void EventHub::Device::trackInputEvent(const struct input_event& event) {
+ switch (event.type) {
+ case EV_KEY: {
+ LOG_ALWAYS_FATAL_IF(!currentFrameDropped &&
+ !keyState.set(static_cast<size_t>(event.code),
+ event.value != 0),
+ "%s: received invalid EV_KEY event code: %s", __func__,
+ InputEventLookup::getLinuxEvdevLabel(EV_KEY, event.code, 1)
+ .code.c_str());
+ break;
+ }
+ case EV_SW: {
+ LOG_ALWAYS_FATAL_IF(!currentFrameDropped &&
+ !swState.set(static_cast<size_t>(event.code),
+ event.value != 0),
+ "%s: received invalid EV_SW event code: %s", __func__,
+ InputEventLookup::getLinuxEvdevLabel(EV_SW, event.code, 1)
+ .code.c_str());
+ break;
+ }
+ case EV_SYN: {
+ switch (event.code) {
+ case SYN_REPORT:
+ currentFrameDropped = false;
+ break;
+ case SYN_DROPPED:
+ // When we receive SYN_DROPPED, all events in the current frame should be
+ // dropped. We query the state of the device to synchronize our device state
+ // with the kernel's to account for the dropped events.
+ currentFrameDropped = true;
+ readDeviceState();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
/**
* Get the capabilities for the current process.
* Crashes the system if unable to create / check / destroy the capabilities object.
@@ -962,38 +1017,34 @@
}
int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- if (scanCode >= 0 && scanCode <= KEY_MAX) {
- std::scoped_lock _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != nullptr && device->hasValidFd() && device->keyBitmask.test(scanCode)) {
- if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
- return device->keyState.test(scanCode) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
+ if (scanCode < 0 || scanCode > KEY_MAX) {
+ return AKEY_STATE_UNKNOWN;
}
- return AKEY_STATE_UNKNOWN;
+ std::scoped_lock _l(mLock);
+ const Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr || !device->hasValidFd() || !device->keyBitmask.test(scanCode)) {
+ return AKEY_STATE_UNKNOWN;
+ }
+ return device->keyState.test(scanCode) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
std::scoped_lock _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
- std::vector<int32_t> scanCodes = device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode);
- if (scanCodes.size() != 0) {
- if (device->readDeviceBitMask(EVIOCGKEY(0), device->keyState) >= 0) {
- for (size_t i = 0; i < scanCodes.size(); i++) {
- int32_t sc = scanCodes[i];
- if (sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc)) {
- return AKEY_STATE_DOWN;
- }
- }
- return AKEY_STATE_UP;
- }
- }
+ const Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr || !device->hasValidFd() || !device->keyMap.haveKeyLayout()) {
+ return AKEY_STATE_UNKNOWN;
}
- return AKEY_STATE_UNKNOWN;
+ const std::vector<int32_t> scanCodes =
+ device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode);
+ if (scanCodes.empty()) {
+ return AKEY_STATE_UNKNOWN;
+ }
+ return std::any_of(scanCodes.begin(), scanCodes.end(),
+ [&device](const int32_t sc) {
+ return sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc);
+ })
+ ? AKEY_STATE_DOWN
+ : AKEY_STATE_UP;
}
int32_t EventHub::getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const {
@@ -1037,17 +1088,15 @@
}
int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
- if (sw >= 0 && sw <= SW_MAX) {
- std::scoped_lock _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device != nullptr && device->hasValidFd() && device->swBitmask.test(sw)) {
- if (device->readDeviceBitMask(EVIOCGSW(0), device->swState) >= 0) {
- return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
+ if (sw < 0 || sw > SW_MAX) {
+ return AKEY_STATE_UNKNOWN;
}
- return AKEY_STATE_UNKNOWN;
+ std::scoped_lock _l(mLock);
+ const Device* device = getDeviceLocked(deviceId);
+ if (device == nullptr || !device->hasValidFd() || !device->swBitmask.test(sw)) {
+ return AKEY_STATE_UNKNOWN;
+ }
+ return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
}
status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
@@ -1922,6 +1971,7 @@
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];
+ device->trackInputEvent(iev);
events.push_back({
.when = processEventTimestamp(iev),
.readTime = systemTime(SYSTEM_TIME_MONOTONIC),
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 024187f..6e647db 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -411,7 +411,17 @@
* Note the parameter "bit" is an index to the bit, 0 <= bit < BITS.
*/
inline bool test(size_t bit) const {
- return (bit < BITS) ? mData[bit / WIDTH].test(bit % WIDTH) : false;
+ return (bit < BITS) && mData[bit / WIDTH].test(bit % WIDTH);
+ }
+ /* Sets the given bit in the bit array to given value.
+ * Returns true if the given bit is a valid index and thus was set successfully.
+ */
+ inline bool set(size_t bit, bool value) {
+ if (bit >= BITS) {
+ return false;
+ }
+ mData[bit / WIDTH].set(bit % WIDTH, value);
+ return true;
}
/* Returns total number of bytes needed for the array */
inline size_t bytes() { return (BITS + CHAR_BIT - 1) / CHAR_BIT; }
@@ -653,6 +663,10 @@
void setLedForControllerLocked();
status_t mapLed(int32_t led, int32_t* outScanCode) const;
void setLedStateLocked(int32_t led, bool on);
+
+ bool currentFrameDropped;
+ void trackInputEvent(const struct input_event& event);
+ void readDeviceState();
};
/**
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index e751c89..477beaf 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1886,7 +1886,7 @@
::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
-TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsGenerateKeyEvents) {
+TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
const auto stylusId = TestFixture::mStylusInfo.getId();
TestFixture::mStylus->pressKey(BTN_STYLUS);
@@ -1900,7 +1900,7 @@
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsSurroundingTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -1946,7 +1946,7 @@
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsSurroundingHoveringTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -2022,7 +2022,7 @@
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsWithinTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -2076,7 +2076,7 @@
WithDeviceId(touchscreenId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonMotionEventsDisabled) {
+TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
TestFixture::mReader->requestRefreshConfiguration(
InputReaderConfiguration::Change::STYLUS_BUTTON_REPORTING);
@@ -2133,7 +2133,7 @@
// ongoing stylus gesture that is being emitted by the touchscreen.
using ExternalStylusIntegrationTest = TouchIntegrationTest;
-TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureReported) {
+TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus capable of reporting pressure data that
@@ -2179,7 +2179,7 @@
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
}
-TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureNotReported) {
+TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus capable of reporting pressure data that
@@ -2247,7 +2247,7 @@
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
}
-TEST_F(ExternalStylusIntegrationTest, DISABLED_UnfusedExternalStylus) {
+TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus device that does not support pressure. It should not affect any