Loading services/inputflinger/EventHub.cpp +138 −68 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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 --- Loading Loading @@ -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", Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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) { Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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. Loading @@ -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 Loading @@ -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() { Loading Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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); Loading services/inputflinger/EventHub.h +25 −5 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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(); Loading @@ -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); Loading services/inputflinger/InputReader.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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]; Loading services/inputflinger/InputReader.h +18 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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, }; Loading Loading @@ -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), Loading Loading @@ -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. * Loading Loading @@ -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, Loading Loading @@ -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); Loading services/inputflinger/tests/InputReader_test.cpp +134 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/inputflinger/EventHub.cpp +138 −68 Original line number Diff line number Diff line Loading @@ -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)); Loading @@ -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 --- Loading Loading @@ -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", Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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) { Loading @@ -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", Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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. Loading @@ -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 Loading @@ -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() { Loading Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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); Loading
services/inputflinger/EventHub.h +25 −5 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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(); Loading @@ -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); Loading
services/inputflinger/InputReader.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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]; Loading
services/inputflinger/InputReader.h +18 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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, }; Loading Loading @@ -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), Loading Loading @@ -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. * Loading Loading @@ -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, Loading Loading @@ -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); Loading
services/inputflinger/tests/InputReader_test.cpp +134 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes