am 266ea6b0
: Merge "Optimize EventHub to process events in big chunks. (DO NOT MERGE)" into honeycomb-mr2
* commit '266ea6b091d572eaa153e70574da97752b97180b': Optimize EventHub to process events in big chunks. (DO NOT MERGE)
This commit is contained in:
@ -127,9 +127,11 @@ EventHub::EventHub(void) :
|
|||||||
mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
|
mError(NO_INIT), mBuiltInKeyboardId(-1), mNextDeviceId(1),
|
||||||
mOpeningDevices(0), mClosingDevices(0),
|
mOpeningDevices(0), mClosingDevices(0),
|
||||||
mOpened(false), mNeedToSendFinishedDeviceScan(false),
|
mOpened(false), mNeedToSendFinishedDeviceScan(false),
|
||||||
mInputBufferIndex(0), mInputBufferCount(0), mInputFdIndex(0) {
|
mInputFdIndex(1) {
|
||||||
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
||||||
|
|
||||||
memset(mSwitches, 0, sizeof(mSwitches));
|
memset(mSwitches, 0, sizeof(mSwitches));
|
||||||
|
mNumCpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventHub::~EventHub(void) {
|
EventHub::~EventHub(void) {
|
||||||
@ -445,17 +447,10 @@ EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
|
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
|
||||||
outEvent->deviceId = 0;
|
// Note that we only allow one caller to getEvents(), so don't need
|
||||||
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
|
|
||||||
// to do locking here... only when adding/removing devices.
|
// to do locking here... only when adding/removing devices.
|
||||||
|
assert(bufferSize >= 1);
|
||||||
|
|
||||||
if (!mOpened) {
|
if (!mOpened) {
|
||||||
mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
|
mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
|
||||||
@ -463,99 +458,62 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
|
|||||||
mNeedToSendFinishedDeviceScan = true;
|
mNeedToSendFinishedDeviceScan = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct input_event readBuffer[bufferSize];
|
||||||
|
|
||||||
|
RawEvent* event = buffer;
|
||||||
|
size_t capacity = bufferSize;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
|
||||||
// Report any devices that had last been added/removed.
|
// Report any devices that had last been added/removed.
|
||||||
if (mClosingDevices != NULL) {
|
while (mClosingDevices) {
|
||||||
Device* device = mClosingDevices;
|
Device* device = mClosingDevices;
|
||||||
LOGV("Reporting device closed: id=%d, name=%s\n",
|
LOGV("Reporting device closed: id=%d, name=%s\n",
|
||||||
device->id, device->path.string());
|
device->id, device->path.string());
|
||||||
mClosingDevices = device->next;
|
mClosingDevices = device->next;
|
||||||
if (device->id == mBuiltInKeyboardId) {
|
event->when = now;
|
||||||
outEvent->deviceId = 0;
|
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
|
||||||
} else {
|
event->type = DEVICE_REMOVED;
|
||||||
outEvent->deviceId = device->id;
|
event += 1;
|
||||||
}
|
|
||||||
outEvent->type = DEVICE_REMOVED;
|
|
||||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
|
||||||
delete device;
|
delete device;
|
||||||
mNeedToSendFinishedDeviceScan = true;
|
mNeedToSendFinishedDeviceScan = true;
|
||||||
return true;
|
if (--capacity == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mOpeningDevices != NULL) {
|
while (mOpeningDevices != NULL) {
|
||||||
Device* device = mOpeningDevices;
|
Device* device = mOpeningDevices;
|
||||||
LOGV("Reporting device opened: id=%d, name=%s\n",
|
LOGV("Reporting device opened: id=%d, name=%s\n",
|
||||||
device->id, device->path.string());
|
device->id, device->path.string());
|
||||||
mOpeningDevices = device->next;
|
mOpeningDevices = device->next;
|
||||||
if (device->id == mBuiltInKeyboardId) {
|
event->when = now;
|
||||||
outEvent->deviceId = 0;
|
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
|
||||||
} else {
|
event->type = DEVICE_ADDED;
|
||||||
outEvent->deviceId = device->id;
|
event += 1;
|
||||||
}
|
|
||||||
outEvent->type = DEVICE_ADDED;
|
|
||||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
|
||||||
mNeedToSendFinishedDeviceScan = true;
|
mNeedToSendFinishedDeviceScan = true;
|
||||||
return true;
|
if (--capacity == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNeedToSendFinishedDeviceScan) {
|
if (mNeedToSendFinishedDeviceScan) {
|
||||||
mNeedToSendFinishedDeviceScan = false;
|
mNeedToSendFinishedDeviceScan = false;
|
||||||
outEvent->type = FINISHED_DEVICE_SCAN;
|
event->when = now;
|
||||||
outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
|
event->type = FINISHED_DEVICE_SCAN;
|
||||||
return true;
|
event += 1;
|
||||||
|
if (--capacity == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the next input event.
|
// Grab the next input event.
|
||||||
|
// mInputFdIndex is initially 1 because index 0 is used for inotify.
|
||||||
bool deviceWasRemoved = false;
|
bool deviceWasRemoved = false;
|
||||||
for (;;) {
|
while (mInputFdIndex < mFds.size()) {
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct pollfd& pfd = mFds[mInputFdIndex];
|
const struct pollfd& pfd = mFds[mInputFdIndex];
|
||||||
if (pfd.revents & POLLIN) {
|
if (pfd.revents & POLLIN) {
|
||||||
int32_t readSize = read(pfd.fd, mInputBufferData,
|
int32_t readSize = read(pfd.fd, readBuffer, sizeof(struct input_event) * capacity);
|
||||||
sizeof(struct input_event) * INPUT_BUFFER_SIZE);
|
|
||||||
if (readSize < 0) {
|
if (readSize < 0) {
|
||||||
if (errno == ENODEV) {
|
if (errno == ENODEV) {
|
||||||
deviceWasRemoved = true;
|
deviceWasRemoved = true;
|
||||||
@ -566,11 +524,43 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
|
|||||||
}
|
}
|
||||||
} else if ((readSize % sizeof(struct input_event)) != 0) {
|
} else if ((readSize % sizeof(struct input_event)) != 0) {
|
||||||
LOGE("could not get event (wrong size: %d)", readSize);
|
LOGE("could not get event (wrong size: %d)", readSize);
|
||||||
|
} else if (readSize == 0) { // eof
|
||||||
|
deviceWasRemoved = true;
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
mInputBufferCount = size_t(readSize) / sizeof(struct input_event);
|
const Device* device = mDevices[mInputFdIndex];
|
||||||
mInputBufferIndex = 0;
|
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.
|
// Handle the case where a device has been removed but INotify has not yet noticed.
|
||||||
@ -586,10 +576,16 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
|
|||||||
if(mFds[0].revents & POLLIN) {
|
if(mFds[0].revents & POLLIN) {
|
||||||
readNotify(mFds[0].fd);
|
readNotify(mFds[0].fd);
|
||||||
mFds.editItemAt(0).revents = 0;
|
mFds.editItemAt(0).revents = 0;
|
||||||
|
mInputFdIndex = mFds.size();
|
||||||
continue; // report added or removed devices immediately
|
continue; // report added or removed devices immediately
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Return now if we have collected any events, otherwise poll.
|
||||||
|
if (event != buffer) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Poll for events. Mind the wake lock dance!
|
// Poll for events. Mind the wake lock dance!
|
||||||
// We hold a wake lock at all times except during poll(). This works due to some
|
// 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
|
// subtle choreography. When a device driver has pending (unread) events, it acquires
|
||||||
@ -608,19 +604,36 @@ bool EventHub::getEvent(int timeoutMillis, RawEvent* outEvent) {
|
|||||||
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
||||||
|
|
||||||
if (pollResult == 0) {
|
if (pollResult == 0) {
|
||||||
// Timed out.
|
break; // timed out
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (pollResult < 0) {
|
if (pollResult < 0) {
|
||||||
|
// Sleep after errors to avoid locking up the system.
|
||||||
|
// Hopefully the error is transient.
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
LOGW("poll failed (errno=%d)\n", errno);
|
LOGW("poll failed (errno=%d)\n", errno);
|
||||||
usleep(100000);
|
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.
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -157,6 +157,8 @@ public:
|
|||||||
// Sent when all added/removed devices from the most recent scan have been reported.
|
// Sent when all added/removed devices from the most recent scan have been reported.
|
||||||
// This event is always sent at least once.
|
// This event is always sent at least once.
|
||||||
FINISHED_DEVICE_SCAN = 0x30000000,
|
FINISHED_DEVICE_SCAN = 0x30000000,
|
||||||
|
|
||||||
|
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
|
virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
|
||||||
@ -181,7 +183,7 @@ public:
|
|||||||
virtual void addExcludedDevice(const char* deviceName) = 0;
|
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.
|
* 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.
|
* 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
|
* If the device needs to remain awake longer than that, then the caller is responsible
|
||||||
@ -190,9 +192,9 @@ public:
|
|||||||
* The timeout is advisory only. If the device is asleep, it will not wake just to
|
* The timeout is advisory only. If the device is asleep, it will not wake just to
|
||||||
* service the timeout.
|
* 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.
|
* Query current input state.
|
||||||
@ -249,7 +251,7 @@ public:
|
|||||||
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
|
virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
|
||||||
const int32_t* keyCodes, uint8_t* outFlags) const;
|
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 bool hasLed(int32_t deviceId, int32_t led) const;
|
||||||
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
|
virtual void setLedState(int32_t deviceId, int32_t led, bool on);
|
||||||
@ -336,11 +338,11 @@ private:
|
|||||||
// device ids that report particular switches.
|
// device ids that report particular switches.
|
||||||
int32_t mSwitches[SW_MAX + 1];
|
int32_t mSwitches[SW_MAX + 1];
|
||||||
|
|
||||||
static const int INPUT_BUFFER_SIZE = 64;
|
// The index of the next file descriptor that needs to be read.
|
||||||
struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
|
|
||||||
size_t mInputBufferIndex;
|
|
||||||
size_t mInputBufferCount;
|
|
||||||
size_t mInputFdIndex;
|
size_t mInputFdIndex;
|
||||||
|
|
||||||
|
// Set to the number of CPUs.
|
||||||
|
int32_t mNumCpus;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -250,15 +250,11 @@ void InputReader::loopOnce() {
|
|||||||
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
|
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
RawEvent rawEvent;
|
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
|
||||||
if (mEventHub->getEvent(timeoutMillis, &rawEvent)) {
|
if (count) {
|
||||||
#if DEBUG_RAW_EVENTS
|
processEvents(mEventBuffer, count);
|
||||||
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,
|
if (!count || timeoutMillis == 0) {
|
||||||
rawEvent.value);
|
|
||||||
#endif
|
|
||||||
process(&rawEvent);
|
|
||||||
} else {
|
|
||||||
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
#if DEBUG_RAW_EVENTS
|
#if DEBUG_RAW_EVENTS
|
||||||
LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
|
LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
|
||||||
@ -268,23 +264,41 @@ void InputReader::loopOnce() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputReader::process(const RawEvent* rawEvent) {
|
void InputReader::processEvents(const RawEvent* rawEvents, size_t count) {
|
||||||
switch (rawEvent->type) {
|
for (const RawEvent* rawEvent = rawEvents; count;) {
|
||||||
case EventHubInterface::DEVICE_ADDED:
|
int32_t type = rawEvent->type;
|
||||||
addDevice(rawEvent->deviceId);
|
size_t batchSize = 1;
|
||||||
break;
|
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
|
||||||
|
int32_t deviceId = rawEvent->deviceId;
|
||||||
case EventHubInterface::DEVICE_REMOVED:
|
while (batchSize < count) {
|
||||||
removeDevice(rawEvent->deviceId);
|
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|
||||||
break;
|
|| rawEvent[batchSize].deviceId != deviceId) {
|
||||||
|
break;
|
||||||
case EventHubInterface::FINISHED_DEVICE_SCAN:
|
}
|
||||||
handleConfigurationChanged(rawEvent->when);
|
batchSize += 1;
|
||||||
break;
|
}
|
||||||
|
#if DEBUG_RAW_EVENTS
|
||||||
default:
|
LOGD("BatchSize: %d Count: %d", batchSize, count);
|
||||||
consumeEvent(rawEvent);
|
#endif
|
||||||
break;
|
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:
|
||||||
|
assert(false); // can't happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count -= batchSize;
|
||||||
|
rawEvent += batchSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,9 +419,8 @@ InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, ui
|
|||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputReader::consumeEvent(const RawEvent* rawEvent) {
|
void InputReader::processEventsForDevice(int32_t deviceId,
|
||||||
int32_t deviceId = rawEvent->deviceId;
|
const RawEvent* rawEvents, size_t count) {
|
||||||
|
|
||||||
{ // acquire device registry reader lock
|
{ // acquire device registry reader lock
|
||||||
RWLock::AutoRLock _rl(mDeviceRegistryLock);
|
RWLock::AutoRLock _rl(mDeviceRegistryLock);
|
||||||
|
|
||||||
@ -423,7 +436,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
device->process(rawEvent);
|
device->process(rawEvents, count);
|
||||||
} // release device registry reader lock
|
} // release device registry reader lock
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,11 +798,25 @@ 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();
|
size_t numMappers = mMappers.size();
|
||||||
for (size_t i = 0; i < numMappers; i++) {
|
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
|
||||||
InputMapper* mapper = mMappers[i];
|
#if DEBUG_RAW_EVENTS
|
||||||
mapper->process(rawEvent);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +216,10 @@ private:
|
|||||||
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
|
virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
|
||||||
virtual EventHubInterface* getEventHub() { return mEventHub.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.
|
// This reader/writer lock guards the list of input devices.
|
||||||
// The writer lock must be held whenever the list of input devices is modified
|
// The writer lock must be held whenever the list of input devices is modified
|
||||||
// and then promptly released.
|
// and then promptly released.
|
||||||
@ -228,16 +232,15 @@ private:
|
|||||||
KeyedVector<int32_t, InputDevice*> mDevices;
|
KeyedVector<int32_t, InputDevice*> mDevices;
|
||||||
|
|
||||||
// low-level input event decoding and device management
|
// 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 addDevice(int32_t deviceId);
|
||||||
void removeDevice(int32_t deviceId);
|
void removeDevice(int32_t deviceId);
|
||||||
void configureExcludedDevices();
|
void processEventsForDevice(int32_t deviceId, const RawEvent* rawEvents, size_t count);
|
||||||
|
|
||||||
void consumeEvent(const RawEvent* rawEvent);
|
|
||||||
void timeoutExpired(nsecs_t when);
|
void timeoutExpired(nsecs_t when);
|
||||||
|
|
||||||
void handleConfigurationChanged(nsecs_t when);
|
void handleConfigurationChanged(nsecs_t when);
|
||||||
|
void configureExcludedDevices();
|
||||||
|
|
||||||
// state management for all devices
|
// state management for all devices
|
||||||
Mutex mStateLock;
|
Mutex mStateLock;
|
||||||
@ -251,12 +254,12 @@ private:
|
|||||||
InputConfiguration mInputConfiguration;
|
InputConfiguration mInputConfiguration;
|
||||||
void updateInputConfiguration();
|
void updateInputConfiguration();
|
||||||
|
|
||||||
nsecs_t mDisableVirtualKeysTimeout;
|
nsecs_t mDisableVirtualKeysTimeout; // only accessed by reader thread
|
||||||
virtual void disableVirtualKeysUntil(nsecs_t time);
|
virtual void disableVirtualKeysUntil(nsecs_t time);
|
||||||
virtual bool shouldDropVirtualKey(nsecs_t now,
|
virtual bool shouldDropVirtualKey(nsecs_t now,
|
||||||
InputDevice* device, int32_t keyCode, int32_t scanCode);
|
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);
|
virtual void requestTimeoutAtTime(nsecs_t when);
|
||||||
|
|
||||||
// state queries
|
// state queries
|
||||||
@ -301,7 +304,7 @@ public:
|
|||||||
void addMapper(InputMapper* mapper);
|
void addMapper(InputMapper* mapper);
|
||||||
void configure();
|
void configure();
|
||||||
void reset();
|
void reset();
|
||||||
void process(const RawEvent* rawEvent);
|
void process(const RawEvent* rawEvents, size_t count);
|
||||||
void timeoutExpired(nsecs_t when);
|
void timeoutExpired(nsecs_t when);
|
||||||
|
|
||||||
void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
|
void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
|
||||||
|
@ -622,14 +622,14 @@ private:
|
|||||||
mExcludedDevices.add(String8(deviceName));
|
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()) {
|
if (mEvents.empty()) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*outEvent = *mEvents.begin();
|
*buffer = *mEvents.begin();
|
||||||
mEvents.erase(mEvents.begin());
|
mEvents.erase(mEvents.begin());
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
|
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
|
||||||
@ -1445,7 +1445,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe
|
|||||||
|
|
||||||
// Event handling.
|
// Event handling.
|
||||||
RawEvent event;
|
RawEvent event;
|
||||||
mDevice->process(&event);
|
mDevice->process(&event, 1);
|
||||||
|
|
||||||
ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
|
ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
|
||||||
ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
|
ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
|
||||||
|
Reference in New Issue
Block a user