Loading services/inputflinger/reader/EventHub.cpp +52 −102 Original line number Diff line number Diff line Loading @@ -43,22 +43,11 @@ #include <utils/Errors.h> #include <utils/Log.h> #include <utils/Timers.h> #include <utils/threads.h> #include <filesystem> #include "EventHub.h" /* this macro is used to tell if "bit" is set in "array" * it selects a byte from the array, and does a boolean AND * operation with a byte that only has the relevant bit set. * eg. to check for the 12th bit, we do (array[1] & 1<<4) */ #define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8))) /* this macro computes the number of bytes needed to represent a bit array of the specified size */ #define sizeof_bit_array(bits) (((bits) + 7) / 8) #define INDENT " " #define INDENT2 " " #define INDENT3 " " Loading Loading @@ -193,15 +182,7 @@ EventHub::Device::Device(int fd, int32_t id, const std::string& path, ffEffectId(-1), controllerNumber(0), enabled(true), isVirtual(fd < 0) { memset(keyBitmask, 0, sizeof(keyBitmask)); memset(absBitmask, 0, sizeof(absBitmask)); memset(relBitmask, 0, sizeof(relBitmask)); memset(swBitmask, 0, sizeof(swBitmask)); memset(ledBitmask, 0, sizeof(ledBitmask)); memset(ffBitmask, 0, sizeof(ffBitmask)); memset(propBitmask, 0, sizeof(propBitmask)); } isVirtual(fd < 0) {} EventHub::Device::~Device() { close(); Loading Loading @@ -391,7 +372,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) { if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) { struct input_absinfo info; if (ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis, Loading @@ -418,9 +399,7 @@ bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { return test_bit(axis, device->relBitmask); } return device != nullptr ? device->relBitmask.test(axis) : false; } return false; } Loading @@ -430,9 +409,7 @@ bool EventHub::hasInputProperty(int32_t deviceId, int property) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { return test_bit(property, device->propBitmask); } return device != nullptr ? device->propBitmask.test(property) : false; } return false; } Loading @@ -442,11 +419,9 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; 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; } } } Loading @@ -457,16 +432,14 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) { std::vector<int32_t> scanCodes; device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); if (scanCodes.size() != 0) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 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 && test_bit(sc, keyState)) { if (sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc)) { return AKEY_STATE_DOWN; } } Loading @@ -482,11 +455,9 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) { uint8_t swState[sizeof_bit_array(SW_MAX + 1)]; memset(swState, 0, sizeof(swState)); if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) { return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; 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; } } } Loading @@ -500,7 +471,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) { if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) { struct input_absinfo info; if (ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis, Loading @@ -520,7 +491,7 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->keyMap.haveKeyLayout()) { std::vector<int32_t> scanCodes; for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { scanCodes.clear(); Loading @@ -531,7 +502,7 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in // check the possible scan codes identified by the layout map against the // map of codes actually emitted by the driver for (size_t sc = 0; sc < scanCodes.size(); sc++) { if (test_bit(scanCodes[sc], device->keyBitmask)) { if (device->keyBitmask.test(scanCodes[sc])) { outFlags[codeIndex] = 1; break; } Loading @@ -549,7 +520,7 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, Device* device = getDeviceLocked(deviceId); status_t status = NAME_NOT_FOUND; if (device) { if (device != nullptr) { // Check the key character map first. sp<KeyCharacterMap> kcm = device->getKeyCharacterMap(); if (kcm != nullptr) { Loading Loading @@ -588,7 +559,7 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->keyMap.haveKeyLayout()) { status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; Loading @@ -607,10 +578,8 @@ void EventHub::setExcludedDevices(const std::vector<std::string>& devices) { bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && scanCode >= 0 && scanCode <= KEY_MAX) { if (test_bit(scanCode, device->keyBitmask)) { return true; } if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) { return device->keyBitmask.test(scanCode); } return false; } Loading @@ -619,10 +588,8 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); int32_t sc; if (device && mapLed(device, led, &sc) == NO_ERROR) { if (test_bit(sc, device->ledBitmask)) { return true; } if (device != nullptr && mapLed(device, led, &sc) == NO_ERROR) { return device->ledBitmask.test(sc); } return false; } Loading @@ -635,7 +602,7 @@ void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) { int32_t sc; if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) { if (device != nullptr && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) { struct input_event ev; ev.time.tv_sec = 0; ev.time.tv_usec = 0; Loading @@ -656,7 +623,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->virtualKeyMap) { if (device != nullptr && device->virtualKeyMap) { const std::vector<VirtualKeyDefinition> virtualKeys = device->virtualKeyMap->getVirtualKeys(); outVirtualKeys.insert(outVirtualKeys.end(), virtualKeys.begin(), virtualKeys.end()); Loading @@ -666,7 +633,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { if (device != nullptr) { return device->getKeyCharacterMap(); } return nullptr; Loading @@ -675,7 +642,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { if (device != nullptr) { if (map != device->overlayKeyMap) { device->overlayKeyMap = map; device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map); Loading Loading @@ -738,7 +705,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd()) { if (device != nullptr && device->hasValidFd()) { ff_effect effect; memset(&effect, 0, sizeof(effect)); effect.type = FF_RUMBLE; Loading Loading @@ -772,7 +739,7 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { void EventHub::cancelVibrate(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd()) { if (device != nullptr && device->hasValidFd()) { if (device->ffEffectPlaying) { device->ffEffectPlaying = false; Loading Loading @@ -1089,7 +1056,7 @@ std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (!device || !device->videoDevice) { if (device == nullptr || !device->videoDevice) { return {}; } return device->videoDevice->consumeFrames(); Loading Loading @@ -1126,17 +1093,6 @@ void EventHub::scanDevicesLocked() { // ---------------------------------------------------------------------------- static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) { const uint8_t* end = array + endIndex; array += startIndex; while (array != end) { if (*(array++) != 0) { return true; } } return false; } static const int32_t GAMEPAD_KEYCODES[] = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // Loading Loading @@ -1306,31 +1262,27 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { loadConfigurationLocked(device); // Figure out the kinds of events the device reports. ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask); ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask); ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask); ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask); ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask); ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask); ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask); device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask); // See if this is a keyboard. Ignore everything in the button range except for // joystick and gamepad buttons which are handled like keyboards for the most part. bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_WHEEL), sizeof_bit_array(KEY_MAX + 1)); bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), sizeof_bit_array(BTN_MOUSE)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK), sizeof_bit_array(BTN_DIGI)); device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1); bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) || device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI); if (haveKeyboardKeys || haveGamepadButtons) { device->classes |= INPUT_DEVICE_CLASS_KEYBOARD; } // See if this is a cursor device such as a trackball or mouse. if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) && test_bit(REL_Y, device->relBitmask)) { if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) && device->relBitmask.test(REL_Y)) { device->classes |= INPUT_DEVICE_CLASS_CURSOR; } Loading @@ -1345,22 +1297,20 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { // See if this is a touch pad. // Is this a new modern multi-touch driver? if (test_bit(ABS_MT_POSITION_X, device->absBitmask) && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) { if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) { // Some joysticks such as the PS3 controller report axes that conflict // with the ABS_MT range. Try to confirm that the device really is // a touch screen. if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) { if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) { device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT; } // Is this an old style single-touch driver? } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) && test_bit(ABS_Y, device->absBitmask)) { } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) && device->absBitmask.test(ABS_Y)) { device->classes |= INPUT_DEVICE_CLASS_TOUCH; // Is this a BT stylus? } else if ((test_bit(ABS_PRESSURE, device->absBitmask) || test_bit(BTN_TOUCH, device->keyBitmask)) && !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) { } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) && !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) { device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS; // Keyboard will try to claim some of the buttons but we really want to reserve those so we // can fuse it with the touch screen data, so just take them back. Note this means an Loading @@ -1374,7 +1324,7 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { if (haveGamepadButtons) { uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK; for (int i = 0; i <= ABS_MAX; i++) { if (test_bit(i, device->absBitmask) && if (device->absBitmask.test(i) && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) { device->classes = assumedClasses; break; Loading @@ -1384,14 +1334,14 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { // Check whether this device has switches. for (int i = 0; i <= SW_MAX; i++) { if (test_bit(i, device->swBitmask)) { if (device->swBitmask.test(i)) { device->classes |= INPUT_DEVICE_CLASS_SWITCH; break; } } // Check whether this device supports the vibrator. if (test_bit(FF_RUMBLE, device->ffBitmask)) { if (device->ffBitmask.test(FF_RUMBLE)) { device->classes |= INPUT_DEVICE_CLASS_VIBRATOR; } Loading Loading @@ -1703,7 +1653,7 @@ bool EventHub::hasKeycodeLocked(Device* device, int keycode) const { const size_t N = scanCodes.size(); for (size_t i = 0; i < N && i <= KEY_MAX; i++) { int32_t sc = scanCodes[i]; if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) { if (sc >= 0 && sc <= KEY_MAX && device->keyBitmask.test(sc)) { return true; } } Loading @@ -1718,7 +1668,7 @@ status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) con int32_t scanCode; if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) { if (scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) { if (scanCode >= 0 && scanCode <= LED_MAX && device->ledBitmask.test(scanCode)) { *outScanCode = scanCode; return NO_ERROR; } Loading services/inputflinger/reader/include/EventHub.h +96 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef _RUNTIME_EVENT_HUB_H #define _RUNTIME_EVENT_HUB_H #include <bitset> #include <climits> #include <vector> #include <input/Input.h> Loading @@ -38,11 +40,6 @@ #include "TouchVideoDevice.h" /* Convenience constants. */ #define BTN_FIRST 0x100 // first button code #define BTN_LAST 0x15f // last button code namespace android { /* Loading Loading @@ -256,6 +253,76 @@ public: virtual status_t disableDevice(int32_t deviceId) = 0; }; template <std::size_t BITS> class BitArray { /* Array element type and vector of element type. */ using Element = std::uint32_t; /* Number of bits in each BitArray element. */ static constexpr size_t WIDTH = sizeof(Element) * CHAR_BIT; /* Number of elements to represent a bit array of the specified size of bits. */ static constexpr size_t COUNT = (BITS + WIDTH - 1) / WIDTH; public: /* BUFFER type declaration for BitArray */ using Buffer = std::array<Element, COUNT>; /* To tell if a bit is set in array, it selects an element from the array, and test * if the relevant bit set. * 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; } /* Returns total number of bytes needed for the array */ inline size_t bytes() { return (BITS + CHAR_BIT - 1) / CHAR_BIT; } /* Returns true if array contains any non-zero bit from the range defined by start and end * bit index [startIndex, endIndex). */ bool any(size_t startIndex, size_t endIndex) { if (startIndex >= endIndex || startIndex > BITS || endIndex > BITS + 1) { ALOGE("Invalid start/end index. start = %zu, end = %zu, total bits = %zu", startIndex, endIndex, BITS); return false; } size_t se = startIndex / WIDTH; // Start of element size_t ee = endIndex / WIDTH; // End of element size_t si = startIndex % WIDTH; // Start index in start element size_t ei = endIndex % WIDTH; // End index in end element // Need to check first unaligned bitset for any non zero bit if (si > 0) { size_t nBits = se == ee ? ei - si : WIDTH - si; // Generate the mask of interested bit range Element mask = ((1 << nBits) - 1) << si; if (mData[se++].to_ulong() & mask) { return true; } } // Check whole bitset for any bit set for (; se < ee; se++) { if (mData[se].any()) { return true; } } // Need to check last unaligned bitset for any non zero bit if (ei > 0 && se <= ee) { // Generate the mask of interested bit range Element mask = (1 << ei) - 1; if (mData[se].to_ulong() & mask) { return true; } } return false; } /* Load bit array values from buffer */ void loadFromBuffer(const Buffer& buffer) { for (size_t i = 0; i < COUNT; i++) { mData[i] = std::bitset<WIDTH>(buffer[i]); } } private: std::array<std::bitset<WIDTH>, COUNT> mData; }; class EventHub : public EventHubInterface { public: EventHub(); Loading Loading @@ -332,13 +399,15 @@ private: uint32_t classes; uint8_t keyBitmask[(KEY_MAX + 1) / 8]; uint8_t absBitmask[(ABS_MAX + 1) / 8]; uint8_t relBitmask[(REL_MAX + 1) / 8]; uint8_t swBitmask[(SW_MAX + 1) / 8]; uint8_t ledBitmask[(LED_MAX + 1) / 8]; uint8_t ffBitmask[(FF_MAX + 1) / 8]; uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8]; BitArray<KEY_MAX> keyBitmask; BitArray<KEY_MAX> keyState; BitArray<ABS_MAX> absBitmask; BitArray<REL_MAX> relBitmask; BitArray<SW_MAX> swBitmask; BitArray<SW_MAX> swState; BitArray<LED_MAX> ledBitmask; BitArray<FF_MAX> ffBitmask; BitArray<INPUT_PROP_MAX> propBitmask; std::string configurationFile; PropertyMap* configuration; Loading Loading @@ -371,6 +440,21 @@ private: } return keyMap.keyCharacterMap; } template <std::size_t N> status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) { if (!hasValidFd()) { return BAD_VALUE; } if ((_IOC_SIZE(ioctlCode) == 0)) { ioctlCode |= _IOC(0, 0, 0, bitArray.bytes()); } typename BitArray<N>::Buffer buffer; status_t ret = ioctl(fd, ioctlCode, buffer.data()); bitArray.loadFromBuffer(buffer); return ret; } }; status_t openDeviceLocked(const std::string& devicePath); Loading services/inputflinger/tests/EventHub_test.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -199,3 +199,76 @@ TEST_F(EventHubTest, InputEvent_TimestampIsMonotonic) { 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)); } Loading
services/inputflinger/reader/EventHub.cpp +52 −102 Original line number Diff line number Diff line Loading @@ -43,22 +43,11 @@ #include <utils/Errors.h> #include <utils/Log.h> #include <utils/Timers.h> #include <utils/threads.h> #include <filesystem> #include "EventHub.h" /* this macro is used to tell if "bit" is set in "array" * it selects a byte from the array, and does a boolean AND * operation with a byte that only has the relevant bit set. * eg. to check for the 12th bit, we do (array[1] & 1<<4) */ #define test_bit(bit, array) ((array)[(bit) / 8] & (1 << ((bit) % 8))) /* this macro computes the number of bytes needed to represent a bit array of the specified size */ #define sizeof_bit_array(bits) (((bits) + 7) / 8) #define INDENT " " #define INDENT2 " " #define INDENT3 " " Loading Loading @@ -193,15 +182,7 @@ EventHub::Device::Device(int fd, int32_t id, const std::string& path, ffEffectId(-1), controllerNumber(0), enabled(true), isVirtual(fd < 0) { memset(keyBitmask, 0, sizeof(keyBitmask)); memset(absBitmask, 0, sizeof(absBitmask)); memset(relBitmask, 0, sizeof(relBitmask)); memset(swBitmask, 0, sizeof(swBitmask)); memset(ledBitmask, 0, sizeof(ledBitmask)); memset(ffBitmask, 0, sizeof(ffBitmask)); memset(propBitmask, 0, sizeof(propBitmask)); } isVirtual(fd < 0) {} EventHub::Device::~Device() { close(); Loading Loading @@ -391,7 +372,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) { if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) { struct input_absinfo info; if (ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis, Loading @@ -418,9 +399,7 @@ bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { return test_bit(axis, device->relBitmask); } return device != nullptr ? device->relBitmask.test(axis) : false; } return false; } Loading @@ -430,9 +409,7 @@ bool EventHub::hasInputProperty(int32_t deviceId, int property) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { return test_bit(property, device->propBitmask); } return device != nullptr ? device->propBitmask.test(property) : false; } return false; } Loading @@ -442,11 +419,9 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(scanCode, device->keyBitmask)) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) { return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; 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; } } } Loading @@ -457,16 +432,14 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->hasValidFd() && device->keyMap.haveKeyLayout()) { std::vector<int32_t> scanCodes; device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); if (scanCodes.size() != 0) { uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)]; memset(keyState, 0, sizeof(keyState)); if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 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 && test_bit(sc, keyState)) { if (sc >= 0 && sc <= KEY_MAX && device->keyState.test(sc)) { return AKEY_STATE_DOWN; } } Loading @@ -482,11 +455,9 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(sw, device->swBitmask)) { uint8_t swState[sizeof_bit_array(SW_MAX + 1)]; memset(swState, 0, sizeof(swState)); if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) { return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP; 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; } } } Loading @@ -500,7 +471,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) { if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) { struct input_absinfo info; if (ioctl(device->fd, EVIOCGABS(axis), &info)) { ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis, Loading @@ -520,7 +491,7 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->keyMap.haveKeyLayout()) { std::vector<int32_t> scanCodes; for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { scanCodes.clear(); Loading @@ -531,7 +502,7 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const in // check the possible scan codes identified by the layout map against the // map of codes actually emitted by the driver for (size_t sc = 0; sc < scanCodes.size(); sc++) { if (test_bit(scanCodes[sc], device->keyBitmask)) { if (device->keyBitmask.test(scanCodes[sc])) { outFlags[codeIndex] = 1; break; } Loading @@ -549,7 +520,7 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, Device* device = getDeviceLocked(deviceId); status_t status = NAME_NOT_FOUND; if (device) { if (device != nullptr) { // Check the key character map first. sp<KeyCharacterMap> kcm = device->getKeyCharacterMap(); if (kcm != nullptr) { Loading Loading @@ -588,7 +559,7 @@ status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxis AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { if (device != nullptr && device->keyMap.haveKeyLayout()) { status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; Loading @@ -607,10 +578,8 @@ void EventHub::setExcludedDevices(const std::vector<std::string>& devices) { bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && scanCode >= 0 && scanCode <= KEY_MAX) { if (test_bit(scanCode, device->keyBitmask)) { return true; } if (device != nullptr && scanCode >= 0 && scanCode <= KEY_MAX) { return device->keyBitmask.test(scanCode); } return false; } Loading @@ -619,10 +588,8 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); int32_t sc; if (device && mapLed(device, led, &sc) == NO_ERROR) { if (test_bit(sc, device->ledBitmask)) { return true; } if (device != nullptr && mapLed(device, led, &sc) == NO_ERROR) { return device->ledBitmask.test(sc); } return false; } Loading @@ -635,7 +602,7 @@ void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) { int32_t sc; if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) { if (device != nullptr && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) { struct input_event ev; ev.time.tv_sec = 0; ev.time.tv_usec = 0; Loading @@ -656,7 +623,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->virtualKeyMap) { if (device != nullptr && device->virtualKeyMap) { const std::vector<VirtualKeyDefinition> virtualKeys = device->virtualKeyMap->getVirtualKeys(); outVirtualKeys.insert(outVirtualKeys.end(), virtualKeys.begin(), virtualKeys.end()); Loading @@ -666,7 +633,7 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { if (device != nullptr) { return device->getKeyCharacterMap(); } return nullptr; Loading @@ -675,7 +642,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { if (device != nullptr) { if (map != device->overlayKeyMap) { device->overlayKeyMap = map; device->combinedKeyMap = KeyCharacterMap::combine(device->keyMap.keyCharacterMap, map); Loading Loading @@ -738,7 +705,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd()) { if (device != nullptr && device->hasValidFd()) { ff_effect effect; memset(&effect, 0, sizeof(effect)); effect.type = FF_RUMBLE; Loading Loading @@ -772,7 +739,7 @@ void EventHub::vibrate(int32_t deviceId, nsecs_t duration) { void EventHub::cancelVibrate(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->hasValidFd()) { if (device != nullptr && device->hasValidFd()) { if (device->ffEffectPlaying) { device->ffEffectPlaying = false; Loading Loading @@ -1089,7 +1056,7 @@ std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (!device || !device->videoDevice) { if (device == nullptr || !device->videoDevice) { return {}; } return device->videoDevice->consumeFrames(); Loading Loading @@ -1126,17 +1093,6 @@ void EventHub::scanDevicesLocked() { // ---------------------------------------------------------------------------- static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) { const uint8_t* end = array + endIndex; array += startIndex; while (array != end) { if (*(array++) != 0) { return true; } } return false; } static const int32_t GAMEPAD_KEYCODES[] = { AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C, // AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z, // Loading Loading @@ -1306,31 +1262,27 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { loadConfigurationLocked(device); // Figure out the kinds of events the device reports. ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask); ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask); ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask); ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask); ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask); ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask); ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask); device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask); device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask); // See if this is a keyboard. Ignore everything in the button range except for // joystick and gamepad buttons which are handled like keyboards for the most part. bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_WHEEL), sizeof_bit_array(KEY_MAX + 1)); bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC), sizeof_bit_array(BTN_MOUSE)) || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK), sizeof_bit_array(BTN_DIGI)); device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1); bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) || device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI); if (haveKeyboardKeys || haveGamepadButtons) { device->classes |= INPUT_DEVICE_CLASS_KEYBOARD; } // See if this is a cursor device such as a trackball or mouse. if (test_bit(BTN_MOUSE, device->keyBitmask) && test_bit(REL_X, device->relBitmask) && test_bit(REL_Y, device->relBitmask)) { if (device->keyBitmask.test(BTN_MOUSE) && device->relBitmask.test(REL_X) && device->relBitmask.test(REL_Y)) { device->classes |= INPUT_DEVICE_CLASS_CURSOR; } Loading @@ -1345,22 +1297,20 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { // See if this is a touch pad. // Is this a new modern multi-touch driver? if (test_bit(ABS_MT_POSITION_X, device->absBitmask) && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) { if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) { // Some joysticks such as the PS3 controller report axes that conflict // with the ABS_MT range. Try to confirm that the device really is // a touch screen. if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) { if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) { device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT; } // Is this an old style single-touch driver? } else if (test_bit(BTN_TOUCH, device->keyBitmask) && test_bit(ABS_X, device->absBitmask) && test_bit(ABS_Y, device->absBitmask)) { } else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) && device->absBitmask.test(ABS_Y)) { device->classes |= INPUT_DEVICE_CLASS_TOUCH; // Is this a BT stylus? } else if ((test_bit(ABS_PRESSURE, device->absBitmask) || test_bit(BTN_TOUCH, device->keyBitmask)) && !test_bit(ABS_X, device->absBitmask) && !test_bit(ABS_Y, device->absBitmask)) { } else if ((device->absBitmask.test(ABS_PRESSURE) || device->keyBitmask.test(BTN_TOUCH)) && !device->absBitmask.test(ABS_X) && !device->absBitmask.test(ABS_Y)) { device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS; // Keyboard will try to claim some of the buttons but we really want to reserve those so we // can fuse it with the touch screen data, so just take them back. Note this means an Loading @@ -1374,7 +1324,7 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { if (haveGamepadButtons) { uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK; for (int i = 0; i <= ABS_MAX; i++) { if (test_bit(i, device->absBitmask) && if (device->absBitmask.test(i) && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) { device->classes = assumedClasses; break; Loading @@ -1384,14 +1334,14 @@ status_t EventHub::openDeviceLocked(const std::string& devicePath) { // Check whether this device has switches. for (int i = 0; i <= SW_MAX; i++) { if (test_bit(i, device->swBitmask)) { if (device->swBitmask.test(i)) { device->classes |= INPUT_DEVICE_CLASS_SWITCH; break; } } // Check whether this device supports the vibrator. if (test_bit(FF_RUMBLE, device->ffBitmask)) { if (device->ffBitmask.test(FF_RUMBLE)) { device->classes |= INPUT_DEVICE_CLASS_VIBRATOR; } Loading Loading @@ -1703,7 +1653,7 @@ bool EventHub::hasKeycodeLocked(Device* device, int keycode) const { const size_t N = scanCodes.size(); for (size_t i = 0; i < N && i <= KEY_MAX; i++) { int32_t sc = scanCodes[i]; if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) { if (sc >= 0 && sc <= KEY_MAX && device->keyBitmask.test(sc)) { return true; } } Loading @@ -1718,7 +1668,7 @@ status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) con int32_t scanCode; if (device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) { if (scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) { if (scanCode >= 0 && scanCode <= LED_MAX && device->ledBitmask.test(scanCode)) { *outScanCode = scanCode; return NO_ERROR; } Loading
services/inputflinger/reader/include/EventHub.h +96 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef _RUNTIME_EVENT_HUB_H #define _RUNTIME_EVENT_HUB_H #include <bitset> #include <climits> #include <vector> #include <input/Input.h> Loading @@ -38,11 +40,6 @@ #include "TouchVideoDevice.h" /* Convenience constants. */ #define BTN_FIRST 0x100 // first button code #define BTN_LAST 0x15f // last button code namespace android { /* Loading Loading @@ -256,6 +253,76 @@ public: virtual status_t disableDevice(int32_t deviceId) = 0; }; template <std::size_t BITS> class BitArray { /* Array element type and vector of element type. */ using Element = std::uint32_t; /* Number of bits in each BitArray element. */ static constexpr size_t WIDTH = sizeof(Element) * CHAR_BIT; /* Number of elements to represent a bit array of the specified size of bits. */ static constexpr size_t COUNT = (BITS + WIDTH - 1) / WIDTH; public: /* BUFFER type declaration for BitArray */ using Buffer = std::array<Element, COUNT>; /* To tell if a bit is set in array, it selects an element from the array, and test * if the relevant bit set. * 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; } /* Returns total number of bytes needed for the array */ inline size_t bytes() { return (BITS + CHAR_BIT - 1) / CHAR_BIT; } /* Returns true if array contains any non-zero bit from the range defined by start and end * bit index [startIndex, endIndex). */ bool any(size_t startIndex, size_t endIndex) { if (startIndex >= endIndex || startIndex > BITS || endIndex > BITS + 1) { ALOGE("Invalid start/end index. start = %zu, end = %zu, total bits = %zu", startIndex, endIndex, BITS); return false; } size_t se = startIndex / WIDTH; // Start of element size_t ee = endIndex / WIDTH; // End of element size_t si = startIndex % WIDTH; // Start index in start element size_t ei = endIndex % WIDTH; // End index in end element // Need to check first unaligned bitset for any non zero bit if (si > 0) { size_t nBits = se == ee ? ei - si : WIDTH - si; // Generate the mask of interested bit range Element mask = ((1 << nBits) - 1) << si; if (mData[se++].to_ulong() & mask) { return true; } } // Check whole bitset for any bit set for (; se < ee; se++) { if (mData[se].any()) { return true; } } // Need to check last unaligned bitset for any non zero bit if (ei > 0 && se <= ee) { // Generate the mask of interested bit range Element mask = (1 << ei) - 1; if (mData[se].to_ulong() & mask) { return true; } } return false; } /* Load bit array values from buffer */ void loadFromBuffer(const Buffer& buffer) { for (size_t i = 0; i < COUNT; i++) { mData[i] = std::bitset<WIDTH>(buffer[i]); } } private: std::array<std::bitset<WIDTH>, COUNT> mData; }; class EventHub : public EventHubInterface { public: EventHub(); Loading Loading @@ -332,13 +399,15 @@ private: uint32_t classes; uint8_t keyBitmask[(KEY_MAX + 1) / 8]; uint8_t absBitmask[(ABS_MAX + 1) / 8]; uint8_t relBitmask[(REL_MAX + 1) / 8]; uint8_t swBitmask[(SW_MAX + 1) / 8]; uint8_t ledBitmask[(LED_MAX + 1) / 8]; uint8_t ffBitmask[(FF_MAX + 1) / 8]; uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8]; BitArray<KEY_MAX> keyBitmask; BitArray<KEY_MAX> keyState; BitArray<ABS_MAX> absBitmask; BitArray<REL_MAX> relBitmask; BitArray<SW_MAX> swBitmask; BitArray<SW_MAX> swState; BitArray<LED_MAX> ledBitmask; BitArray<FF_MAX> ffBitmask; BitArray<INPUT_PROP_MAX> propBitmask; std::string configurationFile; PropertyMap* configuration; Loading Loading @@ -371,6 +440,21 @@ private: } return keyMap.keyCharacterMap; } template <std::size_t N> status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray) { if (!hasValidFd()) { return BAD_VALUE; } if ((_IOC_SIZE(ioctlCode) == 0)) { ioctlCode |= _IOC(0, 0, 0, bitArray.bytes()); } typename BitArray<N>::Buffer buffer; status_t ret = ioctl(fd, ioctlCode, buffer.data()); bitArray.loadFromBuffer(buffer); return ret; } }; status_t openDeviceLocked(const std::string& devicePath); Loading
services/inputflinger/tests/EventHub_test.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -199,3 +199,76 @@ TEST_F(EventHubTest, InputEvent_TimestampIsMonotonic) { 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)); }