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

Commit 9c8a754b authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Android (Google) Code Review
Browse files

Merge "Adding feature: input device disable/enable"

parents 72b06f10 e54cb857
Loading
Loading
Loading
Loading
+138 −68
Original line number Diff line number Diff line
@@ -150,7 +150,8 @@ EventHub::Device::Device(int fd, int32_t id, const String8& path,
        fd(fd), id(id), path(path), identifier(identifier),
        classes(0), configuration(NULL), virtualKeyMap(NULL),
        ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
        timestampOverrideSec(0), timestampOverrideUsec(0) {
        timestampOverrideSec(0), timestampOverrideUsec(0), enabled(true),
        isVirtual(fd < 0) {
    memset(keyBitmask, 0, sizeof(keyBitmask));
    memset(absBitmask, 0, sizeof(absBitmask));
    memset(relBitmask, 0, sizeof(relBitmask));
@@ -173,6 +174,25 @@ void EventHub::Device::close() {
    }
}

status_t EventHub::Device::enable() {
    fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
    if(fd < 0) {
        ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
        return -errno;
    }
    enabled = true;
    return OK;
}

status_t EventHub::Device::disable() {
    close();
    enabled = false;
    return OK;
}

bool EventHub::Device::hasValidFd() {
    return !isVirtual && enabled;
}

// --- EventHub ---

@@ -286,7 +306,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
        AutoMutex _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
            struct input_absinfo info;
            if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -337,7 +357,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
        AutoMutex _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
        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) {
@@ -352,7 +372,7 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
    AutoMutex _l(mLock);

    Device* device = getDeviceLocked(deviceId);
    if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
    if (device && device->hasValidFd() && device->keyMap.haveKeyLayout()) {
        Vector<int32_t> scanCodes;
        device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
        if (scanCodes.size() != 0) {
@@ -377,7 +397,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
        AutoMutex _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
        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) {
@@ -395,7 +415,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*
        AutoMutex _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
        if (device && device->hasValidFd() && test_bit(axis, device->absBitmask)) {
            struct input_absinfo info;
            if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
@@ -532,7 +552,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->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
    if (device && device->hasValidFd() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
        struct input_event ev;
        ev.time.tv_sec = 0;
        ev.time.tv_usec = 0;
@@ -636,7 +656,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->isVirtual()) {
    if (device && device->hasValidFd()) {
        ff_effect effect;
        memset(&effect, 0, sizeof(effect));
        effect.type = FF_RUMBLE;
@@ -670,7 +690,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->isVirtual()) {
    if (device && device->hasValidFd()) {
        if (device->ffEffectPlaying) {
            device->ffEffectPlaying = false;

@@ -1065,12 +1085,37 @@ static const int32_t GAMEPAD_KEYCODES[] = {
        AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
};

status_t EventHub::registerDeviceForEpollLocked(Device* device) {
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mUsingEpollWakeup) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = device->id;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
        return -errno;
    }
    return OK;
}

status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
    if (device->hasValidFd()) {
        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
            return -errno;
        }
    }
    return OK;
}

status_t EventHub::openDeviceLocked(const char *devicePath) {
    char buffer[80];

    ALOGV("Opening device: %s", devicePath);

    int fd = open(devicePath, O_RDWR | O_CLOEXEC);
    int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
    if(fd < 0) {
        ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
        return -1;
@@ -1135,13 +1180,6 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
    // Fill in the descriptor.
    assignDescriptorLocked(identifier);

    // Make file descriptor non-blocking for use with poll().
    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        ALOGE("Error %d making device file descriptor non-blocking.", errno);
        close(fd);
        return -1;
    }

    // Allocate device.  (The device object takes ownership of the fd at this point.)
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
@@ -1303,12 +1341,6 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
                break;
            }
        }

        // Disable kernel key repeat since we handle it ourselves
        unsigned int repeatRate[] = {0,0};
        if (ioctl(fd, EVIOCSREP, repeatRate)) {
            ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
        }
    }

    // If the device isn't recognized as something we handle, don't monitor it.
@@ -1332,23 +1364,41 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
    if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_DPAD)
            && device->classes & INPUT_DEVICE_CLASS_GAMEPAD) {
        device->controllerNumber = getNextControllerNumberLocked(device);
        setLedForController(device);
        setLedForControllerLocked(device);
    }

    // Register with epoll.
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mUsingEpollWakeup) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = deviceId;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);

    if (registerDeviceForEpollLocked(device) != OK) {
        delete device;
        return -1;
    }

    configureFd(device);

    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
         deviceId, fd, devicePath, device->identifier.name.string(),
         device->classes,
         device->configurationFile.string(),
         device->keyMap.keyLayoutFile.string(),
         device->keyMap.keyCharacterMapFile.string(),
         toString(mBuiltInKeyboardId == deviceId));

    addDeviceLocked(device);
    return OK;
}

void EventHub::configureFd(Device* device) {
    // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        // Disable kernel key repeat since we handle it ourselves
        unsigned int repeatRate[] = {0, 0};
        if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
            ALOGW("Unable to disable kernel key repeat for %s: %s",
                  device->path.string(), strerror(errno));
        }
    }

    String8 wakeMechanism("EPOLLWAKEUP");
    if (!mUsingEpollWakeup) {
#ifndef EVIOCSSUSPENDBLOCK
@@ -1357,44 +1407,67 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
        // this feature, we need to be prepared to define the ioctl ourselves.
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
#endif
        if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
            wakeMechanism = "<none>";
        } else {
            wakeMechanism = "EVIOCSSUSPENDBLOCK";
        }
    }

    // Tell the kernel that we want to use the monotonic clock for reporting timestamps
    // associated with input events.  This is important because the input system
    // uses the timestamps extensively and assumes they were recorded using the monotonic
    // clock.
    //
    // In older kernel, before Linux 3.4, there was no way to tell the kernel which
    // clock to use to input event timestamps.  The standard kernel behavior was to
    // record a real time timestamp, which isn't what we want.  Android kernels therefore
    // contained a patch to the evdev_event() function in drivers/input/evdev.c to
    // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
    // clock to be used instead of the real time clock.
    //
    // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
    // Therefore, we no longer require the Android-specific kernel patch described above
    // as long as we make sure to set select the monotonic clock.  We do that here.
    int clockId = CLOCK_MONOTONIC;
    bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
    bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
          toString(usingClockIoctl));
}

    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
            "wakeMechanism=%s, usingClockIoctl=%s",
         deviceId, fd, devicePath, device->identifier.name.string(),
         device->classes,
         device->configurationFile.string(),
         device->keyMap.keyLayoutFile.string(),
         device->keyMap.keyCharacterMapFile.string(),
         toString(mBuiltInKeyboardId == deviceId),
         wakeMechanism.string(), toString(usingClockIoctl));
bool EventHub::isDeviceEnabled(int32_t deviceId) {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == NULL) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
        return false;
    }
    return device->enabled;
}

    addDeviceLocked(device);
    return 0;
status_t EventHub::enableDevice(int32_t deviceId) {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == NULL) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
        return BAD_VALUE;
    }
    if (device->enabled) {
        ALOGW("Duplicate call to %s, input device %" PRId32 " already enabled", __func__, deviceId);
        return OK;
    }
    status_t result = device->enable();
    if (result != OK) {
        ALOGE("Failed to enable device %" PRId32, deviceId);
        return result;
    }

    configureFd(device);

    return registerDeviceForEpollLocked(device);
}

status_t EventHub::disableDevice(int32_t deviceId) {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == NULL) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
        return BAD_VALUE;
    }
    if (!device->enabled) {
        ALOGW("Duplicate call to %s, input device already disabled", __func__);
        return OK;
    }
    unregisterDeviceFromEpollLocked(device);
    return device->disable();
}

void EventHub::createVirtualKeyboardLocked() {
@@ -1490,7 +1563,7 @@ void EventHub::releaseControllerNumberLocked(Device* device) {
    mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
}

void EventHub::setLedForController(Device* device) {
void EventHub::setLedForControllerLocked(Device* device) {
    for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
        setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
    }
@@ -1556,11 +1629,7 @@ void EventHub::closeDeviceLocked(Device* device) {
        mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
    }

    if (!device->isVirtual()) {
        if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
            ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
        }
    }
    unregisterDeviceFromEpollLocked(device);

    releaseControllerNumberLocked(device);

@@ -1691,6 +1760,7 @@ void EventHub::dump(String8& dump) {
            }
            dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
            dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
            dump.appendFormat(INDENT3 "Enabled: %s\n", toString(device->enabled));
            dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
            dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
            dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
+25 −5
Original line number Diff line number Diff line
@@ -25,9 +25,8 @@
#include <input/KeyCharacterMap.h>
#include <input/VirtualKeyMap.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Mutex.h>
#include <utils/Log.h>
#include <utils/threads.h>
#include <utils/List.h>
#include <utils/Errors.h>
#include <utils/PropertyMap.h>
@@ -267,6 +266,15 @@ public:

    /* Called by the heatbeat to ensures that the reader has not deadlocked. */
    virtual void monitor() = 0;

    /* Return true if the device is enabled. */
    virtual bool isDeviceEnabled(int32_t deviceId) = 0;

    /* Enable an input device */
    virtual status_t enableDevice(int32_t deviceId) = 0;

    /* Disable an input device. Closes file descriptor to that device. */
    virtual status_t disableDevice(int32_t deviceId) = 0;
};

class EventHub : public EventHubInterface
@@ -335,7 +343,7 @@ private:
    struct Device {
        Device* next;

        int fd; // may be -1 if device is virtual
        int fd; // may be -1 if device is closed
        const int32_t id;
        const String8 path;
        const InputDeviceIdentifier identifier;
@@ -371,7 +379,11 @@ private:

        void close();

        inline bool isVirtual() const { return fd < 0; }
        bool enabled; // initially true
        status_t enable();
        status_t disable();
        bool hasValidFd();
        const bool isVirtual; // set if fd < 0 is passed to constructor

        const sp<KeyCharacterMap>& getKeyCharacterMap() const {
            if (combinedKeyMap != NULL) {
@@ -390,6 +402,14 @@ private:
    void closeDeviceLocked(Device* device);
    void closeAllDevicesLocked();

    void configureFd(Device* device);

    bool isDeviceEnabled(int32_t deviceId);
    status_t enableDevice(int32_t deviceId);
    status_t disableDevice(int32_t deviceId);
    status_t registerDeviceForEpollLocked(Device* device);
    status_t unregisterDeviceFromEpollLocked(Device* device);

    status_t scanDirLocked(const char *dirname);
    void scanDevicesLocked();
    status_t readNotifyLocked();
@@ -409,7 +429,7 @@ private:

    int32_t getNextControllerNumberLocked(Device* device);
    void releaseControllerNumberLocked(Device* device);
    void setLedForController(Device* device);
    void setLedForControllerLocked(Device* device);

    status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
    void setLedStateLocked(Device* device, int32_t led, bool on);
+38 −0
Original line number Diff line number Diff line
@@ -788,6 +788,18 @@ void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
    }
}

bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
    AutoMutex _l(mLock);

    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex >= 0) {
        InputDevice* device = mDevices.valueAt(deviceIndex);
        return device->isEnabled();
    }
    ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
    return false;
}

void InputReader::dump(String8& dump) {
    AutoMutex _l(mLock);

@@ -961,6 +973,26 @@ InputDevice::~InputDevice() {
    mMappers.clear();
}

bool InputDevice::isEnabled() {
    return getEventHub()->isDeviceEnabled(mId);
}

void InputDevice::setEnabled(bool enabled, nsecs_t when) {
    if (isEnabled() == enabled) {
        return;
    }

    if (enabled) {
        getEventHub()->enableDevice(mId);
        reset(when);
    } else {
        reset(when);
        getEventHub()->disableDevice(mId);
    }
    // Must change generation to flag this device as changed
    bumpGeneration();
}

void InputDevice::dump(String8& dump) {
    InputDeviceInfo deviceInfo;
    getDeviceInfo(& deviceInfo);
@@ -1032,6 +1064,12 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config
            }
        }

        if (!changes || (changes & InputReaderConfiguration::CHANGE_ENABLED_STATE)) {
            ssize_t index = config->disabledDevices.indexOf(mId);
            bool enabled = index < 0;
            setEnabled(enabled, when);
        }

        size_t numMappers = mMappers.size();
        for (size_t i = 0; i < numMappers; i++) {
            InputMapper* mapper = mMappers[i];
+18 −1
Original line number Diff line number Diff line
@@ -26,11 +26,14 @@
#include <input/VelocityTracker.h>
#include <ui/DisplayInfo.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Condition.h>
#include <utils/Thread.h>
#include <utils/Mutex.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/BitSet.h>
#include <utils/SortedVector.h>

#include <stddef.h>
#include <unistd.h>
@@ -147,6 +150,9 @@ struct InputReaderConfiguration {
        // The pointer capture mode has changed.
        CHANGE_POINTER_CAPTURE = 1 << 8,

        // The set of disabled input devices (disabledDevices) has changed.
        CHANGE_ENABLED_STATE = 1 << 9,

        // All devices must be reopened.
        CHANGE_MUST_REOPEN = 1 << 31,
    };
@@ -237,6 +243,9 @@ struct InputReaderConfiguration {
    // True if pointer capture is enabled.
    bool pointerCapture;

    // The set of currently disabled input devices.
    SortedVector<int32_t> disabledDevices;

    InputReaderConfiguration() :
            virtualKeyQuietTime(0),
            pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
@@ -344,6 +353,9 @@ public:
    /* Called by the heatbeat to ensures that the reader has not deadlocked. */
    virtual void monitor() = 0;

    /* Returns true if the input device is enabled. */
    virtual bool isInputDeviceEnabled(int32_t deviceId) = 0;

    /* Runs a single iteration of the processing loop.
     * Nominally reads and processes one incoming message from the EventHub.
     *
@@ -463,6 +475,8 @@ public:

    virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);

    virtual bool isInputDeviceEnabled(int32_t deviceId);

    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
            int32_t scanCode);
    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
@@ -608,6 +622,9 @@ public:

    inline bool isIgnored() { return mMappers.isEmpty(); }

    bool isEnabled();
    void setEnabled(bool enabled, nsecs_t when);

    void dump(String8& dump);
    void addMapper(InputMapper* mapper);
    void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+134 −1

File changed.

Preview size limit exceeded, changes collapsed.