Loading services/input/EventHub.cpp +97 −84 Original line number Diff line number Diff line Loading @@ -127,9 +127,11 @@ EventHub::EventHub(void) : mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1), mOpeningDevices(0), mClosingDevices(0), mOpened(false), mNeedToSendFinishedDeviceScan(false), mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) { mInputFdIndex(1) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); memset(mSwitches, 0, sizeof(mSwitches)); mNumCpus = sysconf(_SC_NPROCESSORS_ONLN); } EventHub::~EventHub(void) { Loading Loading @@ -445,17 +447,10 @@ EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { return NULL; } bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { outEvent->deviceId = 0; outEvent->type = 0; outEvent->scanCode = 0; outEvent->keyCode = 0; outEvent->flags = 0; outEvent->value = 0; outEvent->when = 0; // Note that we only allow one caller to getEvent(), so don't need size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { // Note that we only allow one caller to getEvents(), so don't need // to do locking here... only when adding/removing devices. assert(bufferSize >= 1); if (!mOpened) { mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR; Loading @@ -463,99 +458,62 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { mNeedToSendFinishedDeviceScan = true; } struct input_event readBuffer[bufferSize]; RawEvent* event = buffer; size_t capacity = bufferSize; for (;;) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); // Report any devices that had last been added/removed. if (mClosingDevices != NULL) { while (mClosingDevices) { Device* device = mClosingDevices; LOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.string()); mClosingDevices = device->next; if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = DEVICE_REMOVED; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; event->type = DEVICE_REMOVED; event += 1; delete device; mNeedToSendFinishedDeviceScan = true; return true; if (--capacity == 0) { break; } } if (mOpeningDevices != NULL) { while (mOpeningDevices != NULL) { Device* device = mOpeningDevices; LOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.string()); mOpeningDevices = device->next; if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = DEVICE_ADDED; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; event->type = DEVICE_ADDED; event += 1; mNeedToSendFinishedDeviceScan = true; return true; if (--capacity == 0) { break; } } if (mNeedToSendFinishedDeviceScan) { mNeedToSendFinishedDeviceScan = false; outEvent->type = FINISHED_DEVICE_SCAN; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); return true; event->when = now; event->type = FINISHED_DEVICE_SCAN; event += 1; if (--capacity == 0) { break; } } // Grab the next input event. // mInputFdIndex is initially 1 because index 0 is used for inotify. bool deviceWasRemoved = false; for (;;) { // Consume buffered input events, if any. if (mInputBufferIndex < mInputBufferCount) { const struct input_event& iev = mInputBufferData[mInputBufferIndex++]; const Device* device = mDevices[mInputFdIndex]; LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(), (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = iev.type; outEvent->scanCode = iev.code; outEvent->flags = 0; if (iev.type == EV_KEY) { outEvent->keyCode = AKEYCODE_UNKNOWN; if (device->keyMap.haveKeyLayout()) { status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code, &outEvent->keyCode, &outEvent->flags); LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", iev.code, outEvent->keyCode, outEvent->flags, err); } } else { outEvent->keyCode = iev.code; } outEvent->value = iev.value; // Use an event timestamp in the same timebase as // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis() // as expected by the rest of the system. outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); return true; } // Finish reading all events from devices identified in previous poll(). // This code assumes that mInputDeviceIndex is initially 0 and that the // revents member of pollfd is initialized to 0 when the device is first added. // Since mFds[0] is used for inotify, we process regular events starting at index 1. mInputFdIndex += 1; if (mInputFdIndex >= mFds.size()) { break; } while (mInputFdIndex < mFds.size()) { const struct pollfd& pfd = mFds[mInputFdIndex]; if (pfd.revents & POLLIN) { int32_t readSize = read(pfd.fd, mInputBufferData, sizeof(struct input_event) * INPUT_BUFFER_SIZE); int32_t readSize = read(pfd.fd, readBuffer, sizeof(struct input_event) * capacity); if (readSize < 0) { if (errno == ENODEV) { deviceWasRemoved = true; Loading @@ -566,12 +524,44 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { } } else if ((readSize % sizeof(struct input_event)) != 0) { LOGE("could not get event (wrong size: %d)", readSize); } else if (readSize == 0) { // eof deviceWasRemoved = true; break; } else { mInputBufferCount = size_t(readSize) / sizeof(struct input_event); mInputBufferIndex = 0; const Device* device = mDevices[mInputFdIndex]; int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; size_t count = size_t(readSize) / sizeof(struct input_event); for (size_t i = 0; i < count; i++) { const struct input_event& iev = readBuffer[i]; LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, value=%d", device->path.string(), (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); event->when = now; event->deviceId = deviceId; event->type = iev.type; event->scanCode = 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); LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", iev.code, event->keyCode, event->flags, err); } event += 1; } capacity -= count; if (capacity == 0) { break; } } } mInputFdIndex += 1; } // Handle the case where a device has been removed but INotify has not yet noticed. if (deviceWasRemoved) { Loading @@ -586,10 +576,16 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { if(mFds[0].revents & POLLIN) { readNotify(mFds[0].fd); mFds.editItemAt(0).revents = 0; mInputFdIndex = mFds.size(); continue; // report added or removed devices immediately } #endif // Return now if we have collected any events, otherwise poll. if (event != buffer) { break; } // Poll for events. Mind the wake lock dance! // We hold a wake lock at all times except during poll(). This works due to some // subtle choreography. When a device driver has pending (unread) events, it acquires Loading @@ -608,19 +604,36 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); if (pollResult == 0) { // Timed out. return false; break; // timed out } if (pollResult < 0) { // Sleep after errors to avoid locking up the system. // Hopefully the error is transient. if (errno != EINTR) { LOGW("poll failed (errno=%d)\n", errno); usleep(100000); } } else { // On an SMP system, it is possible for the framework to read input events // faster than the kernel input device driver can produce a complete packet. // Because poll() wakes up as soon as the first input event becomes available, // the framework will often end up reading one event at a time until the // packet is complete. Instead of one call to read() returning 71 events, // it could take 71 calls to read() each returning 1 event. // // Sleep for a short period of time after waking up from the poll() to give // the kernel time to finish writing the entire packet of input events. if (mNumCpus > 1) { usleep(250); } } // Prepare to process all of the FDs we just polled. mInputFdIndex = 0; mInputFdIndex = 1; } // All done, return the number of events we read. return event - buffer; } /* Loading services/input/EventHub.h +10 −8 Original line number Diff line number Diff line Loading @@ -157,6 +157,8 @@ public: // Sent when all added/removed devices from the most recent scan have been reported. // This event is always sent at least once. FINISHED_DEVICE_SCAN = 0x30000000, FIRST_SYNTHETIC_EVENT = DEVICE_ADDED, }; virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0; Loading @@ -181,7 +183,7 @@ public: virtual void addExcludedDevice(const char* deviceName) = 0; /* * Wait for the next event to become available and return it. * Wait for events to become available and returns them. * After returning, the EventHub holds onto a wake lock until the next call to getEvent. * This ensures that the device will not go to sleep while the event is being processed. * If the device needs to remain awake longer than that, then the caller is responsible Loading @@ -190,9 +192,9 @@ public: * The timeout is advisory only. If the device is asleep, it will not wake just to * service the timeout. * * Returns true if an event was obtained, false if the timeout expired. * Returns the number of events obtained, or 0 if the timeout expired. */ virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) = 0; virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; /* * Query current input state. Loading Loading @@ -249,7 +251,7 @@ public: virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const; virtual bool getEvent(int timeoutMillis, RawEvent* outEvent); virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize); virtual bool hasLed(int32_t deviceId, int32_t led) const; virtual void setLedState(int32_t deviceId, int32_t led, bool on); Loading Loading @@ -336,11 +338,11 @@ private: // device ids that report particular switches. int32_t mSwitches[SW_MAX + 1]; static const int INPUT_BUFFER_SIZE = 64; struct input_event mInputBufferData[INPUT_BUFFER_SIZE]; size_t mInputBufferIndex; size_t mInputBufferCount; // The index of the next file descriptor that needs to be read. size_t mInputFdIndex; // Set to the number of CPUs. int32_t mNumCpus; }; }; // namespace android Loading services/input/InputReader.cpp +61 −34 Original line number Diff line number Diff line Loading @@ -250,15 +250,11 @@ void InputReader::loopOnce() { timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); } RawEvent rawEvent; if (mEventHub->getEvent(timeoutMillis, &rawEvent)) { #if DEBUG_RAW_EVENTS LOGD("Input event: device=%d type=0x%04x scancode=0x%04x keycode=0x%04x value=0x%04x", rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode, rawEvent.value); #endif process(&rawEvent); } else { size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); if (count) { processEvents(mEventBuffer, count); } if (!count || timeoutMillis == 0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); #if DEBUG_RAW_EVENTS LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); Loading @@ -268,25 +264,43 @@ void InputReader::loopOnce() { } } void InputReader::process(const RawEvent* rawEvent) { void InputReader::processEvents(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId != deviceId) { break; } batchSize += 1; } #if DEBUG_RAW_EVENTS LOGD("BatchSize: %d Count: %d", batchSize, count); #endif processEventsForDevice(deviceId, rawEvent, batchSize); } else { switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: addDevice(rawEvent->deviceId); break; case EventHubInterface::DEVICE_REMOVED: removeDevice(rawEvent->deviceId); break; case EventHubInterface::FINISHED_DEVICE_SCAN: handleConfigurationChanged(rawEvent->when); break; default: consumeEvent(rawEvent); assert(false); // can't happen break; } } count -= batchSize; rawEvent += batchSize; } } void InputReader::addDevice(int32_t deviceId) { String8 name = mEventHub->getDeviceName(deviceId); Loading Loading @@ -405,9 +419,8 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui return device; } void InputReader::consumeEvent(const RawEvent* rawEvent) { int32_t deviceId = rawEvent->deviceId; void InputReader::processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count) { { // acquire device registry reader lock RWLock::AutoRLock _rl(mDeviceRegistryLock); Loading @@ -423,7 +436,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) { return; } device->process(rawEvent); device->process(rawEvents, count); } // release device registry reader lock } Loading Loading @@ -785,13 +798,27 @@ void InputDevice::reset() { } } void InputDevice::process(const RawEvent* rawEvent) { void InputDevice::process(const RawEvent* rawEvents, size_t count) { // Process all of the events in order for each mapper. // We cannot simply ask each mapper to process them in bulk because mappers may // have side-effects that must be interleaved. For example, joystick movement events and // gamepad button presses are handled by different mappers but they should be dispatched // in the order received. size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { #if DEBUG_RAW_EVENTS LOGD("Input event: device=%d type=0x%04x scancode=0x%04x " "keycode=0x%04x value=0x%04x flags=0x%08x", rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode, rawEvent->value, rawEvent->flags); #endif for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); } } } void InputDevice::timeoutExpired(nsecs_t when) { size_t numMappers = mMappers.size(); Loading services/input/InputReader.h +10 −7 Original line number Diff line number Diff line Loading @@ -216,6 +216,10 @@ private: virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } virtual EventHubInterface* getEventHub() { return mEventHub.get(); } // The event queue. static const int EVENT_BUFFER_SIZE = 256; RawEvent mEventBuffer[EVENT_BUFFER_SIZE]; // This reader/writer lock guards the list of input devices. // The writer lock must be held whenever the list of input devices is modified // and then promptly released. Loading @@ -228,16 +232,15 @@ private: KeyedVector<int32_t, InputDevice*> mDevices; // low-level input event decoding and device management void process(const RawEvent* rawEvent); void processEvents(const RawEvent* rawEvents, size_t count); void addDevice(int32_t deviceId); void removeDevice(int32_t deviceId); void configureExcludedDevices(); void consumeEvent(const RawEvent* rawEvent); void processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count); void timeoutExpired(nsecs_t when); void handleConfigurationChanged(nsecs_t when); void configureExcludedDevices(); // state management for all devices Mutex mStateLock; Loading @@ -251,12 +254,12 @@ private: InputConfiguration mInputConfiguration; void updateInputConfiguration(); nsecs_t mDisableVirtualKeysTimeout; nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread virtual void disableVirtualKeysUntil(nsecs_t time); virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode); nsecs_t mNextTimeout; nsecs_t mNextTimeout; // only accessed by reader thread virtual void requestTimeoutAtTime(nsecs_t when); // state queries Loading Loading @@ -301,7 +304,7 @@ public: void addMapper(InputMapper* mapper); void configure(); void reset(); void process(const RawEvent* rawEvent); void process(const RawEvent* rawEvents, size_t count); void timeoutExpired(nsecs_t when); void getDeviceInfo(InputDeviceInfo* outDeviceInfo); Loading services/input/tests/InputReader_test.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -622,14 +622,14 @@ private: mExcludedDevices.add(String8(deviceName)); } virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) { virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { if (mEvents.empty()) { return false; return 0; } *outEvent = *mEvents.begin(); *buffer = *mEvents.begin(); mEvents.erase(mEvents.begin()); return true; return 1; } virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const { Loading Loading @@ -1445,7 +1445,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe // Event handling. RawEvent event; mDevice->process(&event); mDevice->process(&event, 1); ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled()); ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled()); Loading Loading
services/input/EventHub.cpp +97 −84 Original line number Diff line number Diff line Loading @@ -127,9 +127,11 @@ EventHub::EventHub(void) : mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1), mOpeningDevices(0), mClosingDevices(0), mOpened(false), mNeedToSendFinishedDeviceScan(false), mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) { mInputFdIndex(1) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); memset(mSwitches, 0, sizeof(mSwitches)); mNumCpus = sysconf(_SC_NPROCESSORS_ONLN); } EventHub::~EventHub(void) { Loading Loading @@ -445,17 +447,10 @@ EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const { return NULL; } bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { outEvent->deviceId = 0; outEvent->type = 0; outEvent->scanCode = 0; outEvent->keyCode = 0; outEvent->flags = 0; outEvent->value = 0; outEvent->when = 0; // Note that we only allow one caller to getEvent(), so don't need size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { // Note that we only allow one caller to getEvents(), so don't need // to do locking here... only when adding/removing devices. assert(bufferSize >= 1); if (!mOpened) { mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR; Loading @@ -463,99 +458,62 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { mNeedToSendFinishedDeviceScan = true; } struct input_event readBuffer[bufferSize]; RawEvent* event = buffer; size_t capacity = bufferSize; for (;;) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); // Report any devices that had last been added/removed. if (mClosingDevices != NULL) { while (mClosingDevices) { Device* device = mClosingDevices; LOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.string()); mClosingDevices = device->next; if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = DEVICE_REMOVED; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; event->type = DEVICE_REMOVED; event += 1; delete device; mNeedToSendFinishedDeviceScan = true; return true; if (--capacity == 0) { break; } } if (mOpeningDevices != NULL) { while (mOpeningDevices != NULL) { Device* device = mOpeningDevices; LOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.string()); mOpeningDevices = device->next; if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = DEVICE_ADDED; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); event->when = now; event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; event->type = DEVICE_ADDED; event += 1; mNeedToSendFinishedDeviceScan = true; return true; if (--capacity == 0) { break; } } if (mNeedToSendFinishedDeviceScan) { mNeedToSendFinishedDeviceScan = false; outEvent->type = FINISHED_DEVICE_SCAN; outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); return true; event->when = now; event->type = FINISHED_DEVICE_SCAN; event += 1; if (--capacity == 0) { break; } } // Grab the next input event. // mInputFdIndex is initially 1 because index 0 is used for inotify. bool deviceWasRemoved = false; for (;;) { // Consume buffered input events, if any. if (mInputBufferIndex < mInputBufferCount) { const struct input_event& iev = mInputBufferData[mInputBufferIndex++]; const Device* device = mDevices[mInputFdIndex]; LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d", device->path.string(), (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); if (device->id == mBuiltInKeyboardId) { outEvent->deviceId = 0; } else { outEvent->deviceId = device->id; } outEvent->type = iev.type; outEvent->scanCode = iev.code; outEvent->flags = 0; if (iev.type == EV_KEY) { outEvent->keyCode = AKEYCODE_UNKNOWN; if (device->keyMap.haveKeyLayout()) { status_t err = device->keyMap.keyLayoutMap->mapKey(iev.code, &outEvent->keyCode, &outEvent->flags); LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", iev.code, outEvent->keyCode, outEvent->flags, err); } } else { outEvent->keyCode = iev.code; } outEvent->value = iev.value; // Use an event timestamp in the same timebase as // java.lang.System.nanoTime() and android.os.SystemClock.uptimeMillis() // as expected by the rest of the system. outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC); return true; } // Finish reading all events from devices identified in previous poll(). // This code assumes that mInputDeviceIndex is initially 0 and that the // revents member of pollfd is initialized to 0 when the device is first added. // Since mFds[0] is used for inotify, we process regular events starting at index 1. mInputFdIndex += 1; if (mInputFdIndex >= mFds.size()) { break; } while (mInputFdIndex < mFds.size()) { const struct pollfd& pfd = mFds[mInputFdIndex]; if (pfd.revents & POLLIN) { int32_t readSize = read(pfd.fd, mInputBufferData, sizeof(struct input_event) * INPUT_BUFFER_SIZE); int32_t readSize = read(pfd.fd, readBuffer, sizeof(struct input_event) * capacity); if (readSize < 0) { if (errno == ENODEV) { deviceWasRemoved = true; Loading @@ -566,12 +524,44 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { } } else if ((readSize % sizeof(struct input_event)) != 0) { LOGE("could not get event (wrong size: %d)", readSize); } else if (readSize == 0) { // eof deviceWasRemoved = true; break; } else { mInputBufferCount = size_t(readSize) / sizeof(struct input_event); mInputBufferIndex = 0; const Device* device = mDevices[mInputFdIndex]; int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id; size_t count = size_t(readSize) / sizeof(struct input_event); for (size_t i = 0; i < count; i++) { const struct input_event& iev = readBuffer[i]; LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, value=%d", device->path.string(), (int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); event->when = now; event->deviceId = deviceId; event->type = iev.type; event->scanCode = 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); LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n", iev.code, event->keyCode, event->flags, err); } event += 1; } capacity -= count; if (capacity == 0) { break; } } } mInputFdIndex += 1; } // Handle the case where a device has been removed but INotify has not yet noticed. if (deviceWasRemoved) { Loading @@ -586,10 +576,16 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { if(mFds[0].revents & POLLIN) { readNotify(mFds[0].fd); mFds.editItemAt(0).revents = 0; mInputFdIndex = mFds.size(); continue; // report added or removed devices immediately } #endif // Return now if we have collected any events, otherwise poll. if (event != buffer) { break; } // Poll for events. Mind the wake lock dance! // We hold a wake lock at all times except during poll(). This works due to some // subtle choreography. When a device driver has pending (unread) events, it acquires Loading @@ -608,19 +604,36 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); if (pollResult == 0) { // Timed out. return false; break; // timed out } if (pollResult < 0) { // Sleep after errors to avoid locking up the system. // Hopefully the error is transient. if (errno != EINTR) { LOGW("poll failed (errno=%d)\n", errno); usleep(100000); } } else { // On an SMP system, it is possible for the framework to read input events // faster than the kernel input device driver can produce a complete packet. // Because poll() wakes up as soon as the first input event becomes available, // the framework will often end up reading one event at a time until the // packet is complete. Instead of one call to read() returning 71 events, // it could take 71 calls to read() each returning 1 event. // // Sleep for a short period of time after waking up from the poll() to give // the kernel time to finish writing the entire packet of input events. if (mNumCpus > 1) { usleep(250); } } // Prepare to process all of the FDs we just polled. mInputFdIndex = 0; mInputFdIndex = 1; } // All done, return the number of events we read. return event - buffer; } /* Loading
services/input/EventHub.h +10 −8 Original line number Diff line number Diff line Loading @@ -157,6 +157,8 @@ public: // Sent when all added/removed devices from the most recent scan have been reported. // This event is always sent at least once. FINISHED_DEVICE_SCAN = 0x30000000, FIRST_SYNTHETIC_EVENT = DEVICE_ADDED, }; virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0; Loading @@ -181,7 +183,7 @@ public: virtual void addExcludedDevice(const char* deviceName) = 0; /* * Wait for the next event to become available and return it. * Wait for events to become available and returns them. * After returning, the EventHub holds onto a wake lock until the next call to getEvent. * This ensures that the device will not go to sleep while the event is being processed. * If the device needs to remain awake longer than that, then the caller is responsible Loading @@ -190,9 +192,9 @@ public: * The timeout is advisory only. If the device is asleep, it will not wake just to * service the timeout. * * Returns true if an event was obtained, false if the timeout expired. * Returns the number of events obtained, or 0 if the timeout expired. */ virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) = 0; virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0; /* * Query current input state. Loading Loading @@ -249,7 +251,7 @@ public: virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const; virtual bool getEvent(int timeoutMillis, RawEvent* outEvent); virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize); virtual bool hasLed(int32_t deviceId, int32_t led) const; virtual void setLedState(int32_t deviceId, int32_t led, bool on); Loading Loading @@ -336,11 +338,11 @@ private: // device ids that report particular switches. int32_t mSwitches[SW_MAX + 1]; static const int INPUT_BUFFER_SIZE = 64; struct input_event mInputBufferData[INPUT_BUFFER_SIZE]; size_t mInputBufferIndex; size_t mInputBufferCount; // The index of the next file descriptor that needs to be read. size_t mInputFdIndex; // Set to the number of CPUs. int32_t mNumCpus; }; }; // namespace android Loading
services/input/InputReader.cpp +61 −34 Original line number Diff line number Diff line Loading @@ -250,15 +250,11 @@ void InputReader::loopOnce() { timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); } RawEvent rawEvent; if (mEventHub->getEvent(timeoutMillis, &rawEvent)) { #if DEBUG_RAW_EVENTS LOGD("Input event: device=%d type=0x%04x scancode=0x%04x keycode=0x%04x value=0x%04x", rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode, rawEvent.value); #endif process(&rawEvent); } else { size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); if (count) { processEvents(mEventBuffer, count); } if (!count || timeoutMillis == 0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); #if DEBUG_RAW_EVENTS LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); Loading @@ -268,25 +264,43 @@ void InputReader::loopOnce() { } } void InputReader::process(const RawEvent* rawEvent) { void InputReader::processEvents(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId != deviceId) { break; } batchSize += 1; } #if DEBUG_RAW_EVENTS LOGD("BatchSize: %d Count: %d", batchSize, count); #endif processEventsForDevice(deviceId, rawEvent, batchSize); } else { switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: addDevice(rawEvent->deviceId); break; case EventHubInterface::DEVICE_REMOVED: removeDevice(rawEvent->deviceId); break; case EventHubInterface::FINISHED_DEVICE_SCAN: handleConfigurationChanged(rawEvent->when); break; default: consumeEvent(rawEvent); assert(false); // can't happen break; } } count -= batchSize; rawEvent += batchSize; } } void InputReader::addDevice(int32_t deviceId) { String8 name = mEventHub->getDeviceName(deviceId); Loading Loading @@ -405,9 +419,8 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui return device; } void InputReader::consumeEvent(const RawEvent* rawEvent) { int32_t deviceId = rawEvent->deviceId; void InputReader::processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count) { { // acquire device registry reader lock RWLock::AutoRLock _rl(mDeviceRegistryLock); Loading @@ -423,7 +436,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) { return; } device->process(rawEvent); device->process(rawEvents, count); } // release device registry reader lock } Loading Loading @@ -785,13 +798,27 @@ void InputDevice::reset() { } } void InputDevice::process(const RawEvent* rawEvent) { void InputDevice::process(const RawEvent* rawEvents, size_t count) { // Process all of the events in order for each mapper. // We cannot simply ask each mapper to process them in bulk because mappers may // have side-effects that must be interleaved. For example, joystick movement events and // gamepad button presses are handled by different mappers but they should be dispatched // in the order received. size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { #if DEBUG_RAW_EVENTS LOGD("Input event: device=%d type=0x%04x scancode=0x%04x " "keycode=0x%04x value=0x%04x flags=0x%08x", rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode, rawEvent->value, rawEvent->flags); #endif for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); } } } void InputDevice::timeoutExpired(nsecs_t when) { size_t numMappers = mMappers.size(); Loading
services/input/InputReader.h +10 −7 Original line number Diff line number Diff line Loading @@ -216,6 +216,10 @@ private: virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); } virtual EventHubInterface* getEventHub() { return mEventHub.get(); } // The event queue. static const int EVENT_BUFFER_SIZE = 256; RawEvent mEventBuffer[EVENT_BUFFER_SIZE]; // This reader/writer lock guards the list of input devices. // The writer lock must be held whenever the list of input devices is modified // and then promptly released. Loading @@ -228,16 +232,15 @@ private: KeyedVector<int32_t, InputDevice*> mDevices; // low-level input event decoding and device management void process(const RawEvent* rawEvent); void processEvents(const RawEvent* rawEvents, size_t count); void addDevice(int32_t deviceId); void removeDevice(int32_t deviceId); void configureExcludedDevices(); void consumeEvent(const RawEvent* rawEvent); void processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count); void timeoutExpired(nsecs_t when); void handleConfigurationChanged(nsecs_t when); void configureExcludedDevices(); // state management for all devices Mutex mStateLock; Loading @@ -251,12 +254,12 @@ private: InputConfiguration mInputConfiguration; void updateInputConfiguration(); nsecs_t mDisableVirtualKeysTimeout; nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread virtual void disableVirtualKeysUntil(nsecs_t time); virtual bool shouldDropVirtualKey(nsecs_t now, InputDevice* device, int32_t keyCode, int32_t scanCode); nsecs_t mNextTimeout; nsecs_t mNextTimeout; // only accessed by reader thread virtual void requestTimeoutAtTime(nsecs_t when); // state queries Loading Loading @@ -301,7 +304,7 @@ public: void addMapper(InputMapper* mapper); void configure(); void reset(); void process(const RawEvent* rawEvent); void process(const RawEvent* rawEvents, size_t count); void timeoutExpired(nsecs_t when); void getDeviceInfo(InputDeviceInfo* outDeviceInfo); Loading
services/input/tests/InputReader_test.cpp +5 −5 Original line number Diff line number Diff line Loading @@ -622,14 +622,14 @@ private: mExcludedDevices.add(String8(deviceName)); } virtual bool getEvent(int timeoutMillis, RawEvent* outEvent) { virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { if (mEvents.empty()) { return false; return 0; } *outEvent = *mEvents.begin(); *buffer = *mEvents.begin(); mEvents.erase(mEvents.begin()); return true; return 1; } virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const { Loading Loading @@ -1445,7 +1445,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe // Event handling. RawEvent event; mDevice->process(&event); mDevice->process(&event, 1); ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled()); ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled()); Loading