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

Commit 9a8c972a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Inputflinger : Use BitArray class to replace raw bytes array."

parents 31c88ded 66fbac39
Loading
Loading
Loading
Loading
+52 −102
Original line number Diff line number Diff line
@@ -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 "      "
@@ -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();
@@ -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,
@@ -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;
}
@@ -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;
}
@@ -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;
            }
        }
    }
@@ -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;
                    }
                }
@@ -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;
            }
        }
    }
@@ -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,
@@ -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();
@@ -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;
                    }
@@ -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) {
@@ -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;
@@ -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;
}
@@ -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;
}
@@ -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;
@@ -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());
@@ -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;
@@ -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);
@@ -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;
@@ -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;

@@ -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();
@@ -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,    //
@@ -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;
    }

@@ -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
@@ -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;
@@ -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;
    }

@@ -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;
        }
    }
@@ -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;
        }
+96 −12
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef _RUNTIME_EVENT_HUB_H
#define _RUNTIME_EVENT_HUB_H

#include <bitset>
#include <climits>
#include <vector>

#include <input/Input.h>
@@ -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 {

/*
@@ -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();
@@ -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;
@@ -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);
+73 −0
Original line number Diff line number Diff line
@@ -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));
}