diff options
Diffstat (limited to 'services/input/EventHub.cpp')
| -rw-r--r-- | services/input/EventHub.cpp | 186 |
1 files changed, 101 insertions, 85 deletions
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp index 665d711..2ba821e 100644 --- a/services/input/EventHub.cpp +++ b/services/input/EventHub.cpp @@ -93,6 +93,34 @@ static String8 sha1(const String8& in) { return out; } +static void setDescriptor(InputDeviceIdentifier& identifier) { + // Compute a device descriptor that uniquely identifies the device. + // The descriptor is assumed to be a stable identifier. Its value should not + // change between reboots, reconnections, firmware updates or new releases of Android. + // Ideally, we also want the descriptor to be short and relatively opaque. + String8 rawDescriptor; + rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product); + if (!identifier.uniqueId.isEmpty()) { + rawDescriptor.append("uniqueId:"); + rawDescriptor.append(identifier.uniqueId); + } if (identifier.vendor == 0 && identifier.product == 0) { + // If we don't know the vendor and product id, then the device is probably + // built-in so we need to rely on other information to uniquely identify + // the input device. Usually we try to avoid relying on the device name or + // location but for built-in input device, they are unlikely to ever change. + if (!identifier.name.isEmpty()) { + rawDescriptor.append("name:"); + rawDescriptor.append(identifier.name); + } else if (!identifier.location.isEmpty()) { + rawDescriptor.append("location:"); + rawDescriptor.append(identifier.location); + } + } + identifier.descriptor = sha1(rawDescriptor); + ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(), + identifier.descriptor.string()); +} + // --- Global Functions --- uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) { @@ -164,7 +192,7 @@ const int EventHub::EPOLL_SIZE_HINT; const int EventHub::EPOLL_MAX_EVENTS; EventHub::EventHub(void) : - mBuiltInKeyboardId(-1), mNextDeviceId(1), + mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), @@ -256,7 +284,7 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(axis, device->absBitmask)) { + if (device && !device->isVirtual() && 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", @@ -307,7 +335,7 @@ int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(scanCode, device->keyBitmask)) { + if (device && !device->isVirtual() && 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) { @@ -322,7 +350,7 @@ int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && device->keyMap.haveKeyLayout()) { + if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) { Vector<int32_t> scanCodes; device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes); if (scanCodes.size() != 0) { @@ -347,7 +375,7 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(sw, device->swBitmask)) { + if (device && !device->isVirtual() && 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) { @@ -365,7 +393,7 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && test_bit(axis, device->absBitmask)) { + if (device && !device->isVirtual() && 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", @@ -408,58 +436,35 @@ bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, return false; } -status_t EventHub::mapKey(int32_t deviceId, int scancode, - int32_t* outKeycode, uint32_t* outFlags) const -{ +status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, + int32_t* outKeycode, uint32_t* outFlags) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - + if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags); + status_t err = device->keyMap.keyLayoutMap->mapKey( + scanCode, usageCode, outKeycode, outFlags); if (err == NO_ERROR) { return NO_ERROR; } } - - if (mBuiltInKeyboardId != -1) { - device = getDeviceLocked(mBuiltInKeyboardId); - - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(scancode, outKeycode, outFlags); - if (err == NO_ERROR) { - return NO_ERROR; - } - } - } - + *outKeycode = 0; *outFlags = 0; return NAME_NOT_FOUND; } -status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo) const -{ +status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); + status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo); if (err == NO_ERROR) { return NO_ERROR; } } - if (mBuiltInKeyboardId != -1) { - device = getDeviceLocked(mBuiltInKeyboardId); - - if (device && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo); - if (err == NO_ERROR) { - return NO_ERROR; - } - } - } - return NAME_NOT_FOUND; } @@ -494,7 +499,7 @@ bool EventHub::hasLed(int32_t deviceId, int32_t led) const { void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); - if (device && led >= 0 && led <= LED_MAX) { + if (device && !device->isVirtual() && led >= 0 && led <= LED_MAX) { struct input_event ev; ev.time.tv_sec = 0; ev.time.tv_usec = 0; @@ -520,17 +525,17 @@ void EventHub::getVirtualKeyDefinitions(int32_t deviceId, } } -String8 EventHub::getKeyCharacterMapFile(int32_t deviceId) const { +sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const { AutoMutex _l(mLock); Device* device = getDeviceLocked(deviceId); if (device) { - return device->keyMap.keyCharacterMapFile; + return device->keyMap.keyCharacterMap; } - return String8(); + return NULL; } EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { - if (deviceId == 0) { + if (deviceId == BUILT_IN_KEYBOARD_ID) { deviceId = mBuiltInKeyboardId; } ssize_t index = mDevices.indexOfKey(deviceId); @@ -578,7 +583,7 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz device->id, device->path.string()); mClosingDevices = device->next; event->when = now; - event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; + event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id; event->type = DEVICE_REMOVED; event += 1; delete device; @@ -703,16 +708,8 @@ size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSiz #endif event->deviceId = deviceId; event->type = iev.type; - event->scanCode = iev.code; + event->code = iev.code; event->value = iev.value; - event->keyCode = AKEYCODE_UNKNOWN; - event->flags = 0; - if (iev.type == EV_KEY && device->keyMap.haveKeyLayout()) { - status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code, - &event->keyCode, &event->flags); - ALOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", - iev.code, event->keyCode, event->flags, err); - } event += 1; } capacity -= count; @@ -813,6 +810,9 @@ void EventHub::scanDevicesLocked() { if(res < 0) { ALOGE("scan dir failed for %s\n", DEVICE_PATH); } + if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) { + createVirtualKeyboardLocked(); + } } // ---------------------------------------------------------------------------- @@ -908,29 +908,8 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { identifier.uniqueId.setTo(buffer); } - // Compute a device descriptor that uniquely identifies the device. - // The descriptor is assumed to be a stable identifier. Its value should not - // change between reboots, reconnections, firmware updates or new releases of Android. - // Ideally, we also want the descriptor to be short and relatively opaque. - String8 rawDescriptor; - rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product); - if (!identifier.uniqueId.isEmpty()) { - rawDescriptor.append("uniqueId:"); - rawDescriptor.append(identifier.uniqueId); - } if (identifier.vendor == 0 && identifier.product == 0) { - // If we don't know the vendor and product id, then the device is probably - // built-in so we need to rely on other information to uniquely identify - // the input device. Usually we try to avoid relying on the device name or - // location but for built-in input device, they are unlikely to ever change. - if (!identifier.name.isEmpty()) { - rawDescriptor.append("name:"); - rawDescriptor.append(identifier.name); - } else if (!identifier.location.isEmpty()) { - rawDescriptor.append("location:"); - rawDescriptor.append(identifier.location); - } - } - identifier.descriptor = sha1(rawDescriptor); + // Fill in the descriptor. + setDescriptor(identifier); // Make file descriptor non-blocking for use with poll(). if (fcntl(fd, F_SETFL, O_NONBLOCK)) { @@ -952,7 +931,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { ALOGV(" name: \"%s\"\n", identifier.name.string()); ALOGV(" location: \"%s\"\n", identifier.location.string()); ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string()); - ALOGV(" descriptor: \"%s\" (%s)\n", identifier.descriptor.string(), rawDescriptor.string()); + ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string()); ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff); @@ -1048,7 +1027,7 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) { // Register the keyboard as a built-in keyboard if it is eligible. if (!keyMapStatus - && mBuiltInKeyboardId == -1 + && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD && isEligibleBuiltInKeyboard(device->identifier, device->configuration, &device->keyMap)) { mBuiltInKeyboardId = device->id; @@ -1103,24 +1082,59 @@ status_t EventHub::openDeviceLocked(const char *devicePath) { // Enable wake-lock behavior on kernels that support it. // TODO: Only need this for devices that can really wake the system. - bool usingSuspendBlock = ioctl(fd, EVIOCSSUSPENDBLOCK, 1) == 0; + bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1); + + // 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. + bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, CLOCK_MONOTONIC); ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, " "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, " - "usingSuspendBlock=%s", + "usingSuspendBlockIoctl=%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), - toString(usingSuspendBlock)); + toString(usingSuspendBlockIoctl), toString(usingClockIoctl)); - mDevices.add(deviceId, device); + addDeviceLocked(device); + return 0; +} +void EventHub::createVirtualKeyboardLocked() { + InputDeviceIdentifier identifier; + identifier.name = "Virtual"; + identifier.uniqueId = "<virtual>"; + setDescriptor(identifier); + + Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier); + device->classes = INPUT_DEVICE_CLASS_KEYBOARD + | INPUT_DEVICE_CLASS_ALPHAKEY + | INPUT_DEVICE_CLASS_DPAD + | INPUT_DEVICE_CLASS_VIRTUAL; + loadKeyMapLocked(device); + addDeviceLocked(device); +} + +void EventHub::addDeviceLocked(Device* device) { + mDevices.add(device->id, device); device->next = mOpeningDevices; mOpeningDevices = device; - return 0; } void EventHub::loadConfigurationLocked(Device* device) { @@ -1207,11 +1221,13 @@ void EventHub::closeDeviceLocked(Device* device) { if (device->id == mBuiltInKeyboardId) { ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this", device->path.string(), mBuiltInKeyboardId); - mBuiltInKeyboardId = -1; + mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD; } - if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) { - ALOGW("Could not remove device fd from epoll instance. errno=%d", errno); + 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); + } } mDevices.removeItem(device->id); |
