am 3922484d: Merge "Optimize EventHub reads." into gingerbread
Merge commit '3922484d7458a4ab72fc1ca8952a0776dd1c7d20' into gingerbread-plus-aosp * commit '3922484d7458a4ab72fc1ca8952a0776dd1c7d20': Optimize EventHub reads.
This commit is contained in:
@@ -267,6 +267,12 @@ private:
|
|||||||
#ifdef EV_SW
|
#ifdef EV_SW
|
||||||
int32_t mSwitches[SW_MAX + 1];
|
int32_t mSwitches[SW_MAX + 1];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const int INPUT_BUFFER_SIZE = 64;
|
||||||
|
struct input_event mInputBufferData[INPUT_BUFFER_SIZE];
|
||||||
|
int32_t mInputBufferIndex;
|
||||||
|
int32_t mInputBufferCount;
|
||||||
|
int32_t mInputDeviceIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ EventHub::EventHub(void)
|
|||||||
, mDevicesById(0), mNumDevicesById(0)
|
, mDevicesById(0), mNumDevicesById(0)
|
||||||
, mOpeningDevices(0), mClosingDevices(0)
|
, mOpeningDevices(0), mClosingDevices(0)
|
||||||
, mDevices(0), mFDs(0), mFDCount(0), mOpened(false)
|
, mDevices(0), mFDs(0), mFDCount(0), mOpened(false)
|
||||||
|
, mInputBufferIndex(0), mInputBufferCount(0), mInputDeviceIndex(0)
|
||||||
{
|
{
|
||||||
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
||||||
#ifdef EV_SW
|
#ifdef EV_SW
|
||||||
@@ -341,13 +342,6 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
|||||||
outEvent->value = 0;
|
outEvent->value = 0;
|
||||||
outEvent->when = 0;
|
outEvent->when = 0;
|
||||||
|
|
||||||
status_t err;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
int res;
|
|
||||||
int pollres;
|
|
||||||
struct input_event iev;
|
|
||||||
|
|
||||||
// Note that we only allow one caller to getEvent(), so don't need
|
// 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.
|
||||||
|
|
||||||
@@ -356,9 +350,8 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
|||||||
mOpened = true;
|
mOpened = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
for (;;) {
|
||||||
|
// Report any devices that had last been added/removed.
|
||||||
// First, report any devices that had last been added/removed.
|
|
||||||
if (mClosingDevices != NULL) {
|
if (mClosingDevices != NULL) {
|
||||||
device_t* device = mClosingDevices;
|
device_t* device = mClosingDevices;
|
||||||
LOGV("Reporting device closed: id=0x%x, name=%s\n",
|
LOGV("Reporting device closed: id=0x%x, name=%s\n",
|
||||||
@@ -388,77 +381,96 @@ bool EventHub::getEvent(RawEvent* outEvent)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
release_wake_lock(WAKE_LOCK_ID);
|
// Grab the next input event.
|
||||||
|
for (;;) {
|
||||||
|
// Consume buffered input events, if any.
|
||||||
|
if (mInputBufferIndex < mInputBufferCount) {
|
||||||
|
const struct input_event& iev = mInputBufferData[mInputBufferIndex++];
|
||||||
|
const device_t* device = mDevices[mInputDeviceIndex];
|
||||||
|
|
||||||
pollres = poll(mFDs, mFDCount, -1);
|
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);
|
||||||
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
if (device->id == mFirstKeyboardId) {
|
||||||
|
outEvent->deviceId = 0;
|
||||||
if (pollres <= 0) {
|
} else {
|
||||||
if (errno != EINTR) {
|
outEvent->deviceId = device->id;
|
||||||
LOGW("select failed (errno=%d)\n", errno);
|
}
|
||||||
usleep(100000);
|
outEvent->type = iev.type;
|
||||||
}
|
outEvent->scanCode = iev.code;
|
||||||
continue;
|
if (iev.type == EV_KEY) {
|
||||||
}
|
status_t err = device->layoutMap->map(iev.code,
|
||||||
|
& outEvent->keyCode, & outEvent->flags);
|
||||||
//printf("poll %d, returned %d\n", mFDCount, pollres);
|
LOGV("iev.code=%d keyCode=%d flags=0x%08x err=%d\n",
|
||||||
|
iev.code, outEvent->keyCode, outEvent->flags, err);
|
||||||
// mFDs[0] is used for inotify, so process regular events starting at mFDs[1]
|
if (err != 0) {
|
||||||
for(i = 1; i < mFDCount; i++) {
|
outEvent->keyCode = AKEYCODE_UNKNOWN;
|
||||||
if(mFDs[i].revents) {
|
outEvent->flags = 0;
|
||||||
LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
|
|
||||||
if(mFDs[i].revents & POLLIN) {
|
|
||||||
res = read(mFDs[i].fd, &iev, sizeof(iev));
|
|
||||||
if (res == sizeof(iev)) {
|
|
||||||
device_t* device = mDevices[i];
|
|
||||||
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 == mFirstKeyboardId) {
|
|
||||||
outEvent->deviceId = 0;
|
|
||||||
} else {
|
|
||||||
outEvent->deviceId = device->id;
|
|
||||||
}
|
|
||||||
outEvent->type = iev.type;
|
|
||||||
outEvent->scanCode = iev.code;
|
|
||||||
if (iev.type == EV_KEY) {
|
|
||||||
err = device->layoutMap->map(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);
|
|
||||||
if (err != 0) {
|
|
||||||
outEvent->keyCode = AKEYCODE_UNKNOWN;
|
|
||||||
outEvent->flags = 0;
|
|
||||||
}
|
|
||||||
} 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;
|
|
||||||
} else {
|
|
||||||
if (res<0) {
|
|
||||||
LOGW("could not get event (errno=%d)", errno);
|
|
||||||
} else {
|
|
||||||
LOGE("could not get event (wrong size: %d)", res);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
} 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.
|
||||||
|
mInputDeviceIndex += 1;
|
||||||
|
if (mInputDeviceIndex >= mFDCount) {
|
||||||
|
mInputDeviceIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct pollfd &pfd = mFDs[mInputDeviceIndex];
|
||||||
|
if (pfd.revents & POLLIN) {
|
||||||
|
int32_t readSize = read(pfd.fd, mInputBufferData,
|
||||||
|
sizeof(struct input_event) * INPUT_BUFFER_SIZE);
|
||||||
|
if (readSize < 0) {
|
||||||
|
if (errno != EAGAIN && errno != EINTR) {
|
||||||
|
LOGW("could not get event (errno=%d)", errno);
|
||||||
|
}
|
||||||
|
} else if ((readSize % sizeof(struct input_event)) != 0) {
|
||||||
|
LOGE("could not get event (wrong size: %d)", readSize);
|
||||||
|
} else {
|
||||||
|
mInputBufferCount = readSize / sizeof(struct input_event);
|
||||||
|
mInputBufferIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read_notify() will modify mFDs and mFDCount, so this must be done after
|
// read_notify() will modify mFDs and mFDCount, so this must be done after
|
||||||
// processing all other events.
|
// processing all other events.
|
||||||
if(mFDs[0].revents & POLLIN) {
|
if(mFDs[0].revents & POLLIN) {
|
||||||
read_notify(mFDs[0].fd);
|
read_notify(mFDs[0].fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// a kernel wake lock. However, once the last pending event has been read, the device
|
||||||
|
// driver will release the kernel wake lock. To prevent the system from going to sleep
|
||||||
|
// when this happens, the EventHub holds onto its own user wake lock while the client
|
||||||
|
// is processing events. Thus the system can only sleep if there are no events
|
||||||
|
// pending or currently being processed.
|
||||||
|
release_wake_lock(WAKE_LOCK_ID);
|
||||||
|
|
||||||
|
int pollResult = poll(mFDs, mFDCount, -1);
|
||||||
|
|
||||||
|
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
|
||||||
|
|
||||||
|
if (pollResult <= 0) {
|
||||||
|
if (errno != EINTR) {
|
||||||
|
LOGW("select failed (errno=%d)\n", errno);
|
||||||
|
usleep(100000);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +488,7 @@ bool EventHub::openPlatformInput(void)
|
|||||||
mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
|
mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
|
||||||
mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
|
mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
|
||||||
mFDs[0].events = POLLIN;
|
mFDs[0].events = POLLIN;
|
||||||
|
mFDs[0].revents = 0;
|
||||||
mDevices[0] = NULL;
|
mDevices[0] = NULL;
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
mFDs[0].fd = inotify_init();
|
mFDs[0].fd = inotify_init();
|
||||||
@@ -582,6 +595,12 @@ int EventHub::open_device(const char *deviceName)
|
|||||||
idstr[0] = '\0';
|
idstr[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
|
||||||
|
LOGE("Error %d making device file descriptor non-blocking.", errno);
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int devid = 0;
|
int devid = 0;
|
||||||
while (devid < mNumDevicesById) {
|
while (devid < mNumDevicesById) {
|
||||||
if (mDevicesById[devid].device == NULL) {
|
if (mDevicesById[devid].device == NULL) {
|
||||||
@@ -639,6 +658,7 @@ int EventHub::open_device(const char *deviceName)
|
|||||||
device->fd = fd;
|
device->fd = fd;
|
||||||
mFDs[mFDCount].fd = fd;
|
mFDs[mFDCount].fd = fd;
|
||||||
mFDs[mFDCount].events = POLLIN;
|
mFDs[mFDCount].events = POLLIN;
|
||||||
|
mFDs[mFDCount].revents = 0;
|
||||||
|
|
||||||
// Figure out the kinds of events the device reports.
|
// Figure out the kinds of events the device reports.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user