当前位置:首页 > android 4.0 input分析
判断是不是EPOLL_ID_WAKE事件,即mWakeReadPipeFd有没有变化,如果有设置awoken为true,继续循环取下一个事件。如果不是EPOLL_ID_WAKE事件,继续往下走,肯定是有设备输入事件发生。 ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32); if (deviceIndex < 0) {
LOGW(\ eventItem.events, eventItem.data.u32); continue;
}
得到有事件发生的设备索引,如果deviceIndex < 0,有错误发声,继续循环取下一个事件。 Device* device = mDevices.valueAt(deviceIndex); if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
LOGW(\not get event, removed? (fd: %d size: %d bufferSize: %d capacity: %d errno: %d)\\n\
device->fd, readSize, bufferSize, capacity, errno); deviceChanged = true; closeDeviceLocked(device); } else if (readSize < 0) {
if (errno != EAGAIN && errno != EINTR) {
LOGW(\ }
} else if ((readSize % sizeof(struct input_event)) != 0) { LOGE(\ } else {
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(\ device->path.string(),
(int) iev.time.tv_sec, (int) iev.time.tv_usec, iev.type, iev.code, iev.value); #ifdef HAVE_POSIX_CLOCKS
// Use the time specified in the event instead of the current time // so that downstream code can get more accurate estimates of // event dispatch latency from the time the event is enqueued onto // the evdev client buffer. //
// The event's timestamp fortuitously uses the same monotonic clock // time base as the rest of Android. The kernel event device driver // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
// The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a // system call that also queries ktime_get_ts().
event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL + nsecs_t(iev.time.tv_usec) * 1000LL; LOGV(\#else
event->when = now; #endif
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, event->keyCode, event->flags, err); }
event += 1; }
capacity -= count; if (capacity == 0) {
// The result buffer is full. Reset the pending event index // so we will try to read the device again on the next iteration. mPendingEventIndex -= 1; break; } } } else {
LOGW(\ eventItem.events, device->identifier.name.string());
} }
根据设备索引的设备文件句柄,通过read函数读取input_event事件,读取个数为capacity,根据read返回值readSize除以sizeof(struct input_event)得到实际读取的事件个数,然后循环把input_event赋给event,同时capacity减去读取事件个数,如果capacity等于0,就退出循环,表明这次getEvents已经取得256个event事件了,返回给inputreader处理。如果不等于0,判断mPendingEventIndex 和 mPendingEventCount关系,如果小于继续循环从mPendingEventItems取下一个事件,如果相等,就表示事件已经取完了,执行下面的代码 if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) { mPendingINotify = false; readNotifyLocked();
deviceChanged = true;
}
如果mPendingINotify为true,且mPendingEventIndex >= mPendingEventCount,就表明有设备热拔插事件发生,调用readNotifyLocked() readNotifyLocked()调用
read(mINotifyFd, event_buf, sizeof(event_buf))
从event_buf循环取出inotify_event事件,包括设备节点创建或者删除,以及设备名字
如果是IN_CREATE,就调用openDeviceLocked打开设备,添加打开设备链表。如果是IN_DELETE,就调用closeDeviceByPathLocked关闭设备,添加关闭设备链表。并设置deviceChanged为true。 // Report added or removed devices immediately. if (deviceChanged) { continue;
}
如果deviceChanged为true,结束本次循环,从头执行循环,即立即执行设备添加或删除。 // Return now if we have collected any events or if we were explicitly awoken. if (event != buffer || awoken) {
break; }
如果event != buffer,就表示有event事件发生,或者awoken存在,结束循环,立即返回给inputreader处理event事件。
mPendingEventIndex = 0;
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
调用epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis)之后,读到的epoll_event事件保存在mPendingEventItems,总共的事件数保存在mPendingEventCount,即
mPendingEventCount = size_t(pollResult);
当然,在调用epoll_wait之前,mPendingEventIndex被清0,直正的事件处理在上面的代码中。epoll_event只表明某个设备上有事件,并不包含事件内容,具体事件内容需要通过read来读取。
// All done, return the number of events we read. return event - buffer;
返回得到的event个数,支持整个getEvents已经执行完成,所有的event事件都保存在inputreader传递的RawEvent里面,看看下面的图,理解数据结构的变化
2.7处理事件
在上面2.4节最后我们看到InputReaderThread线程里面会循环调用 InputReader::loopOnce 调用
count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); 读取事件,上一节已经介绍了,得到事件后,接着调用 processEventsLocked(mEventBuffer, count) 处理事件
在processEventsLocked里面主要分两步处理:
1)处理来自于事件驱动设备的事件(processEventsForDeviceLocked) 2)处理设备增加、删除和修改事件—为处理事件做准备 for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
进入for循环,取得本次循环头一个rawEvent,然后判断事件type,如果小于FIRST_SYNTHETIC_EVENT,就表示是真正的input事件,如果大于等于,就表示是input设备变化事件。 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(\#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
判断下一事件type,从rawEvent数组里面取得属于同一个设备的连续input事件,然后交给设备处理程序去处理,如果后面的事件不属于同一个设备,或者事件type是FIRST_SYNTHETIC_EVENT以后的事件,就终止查询,运行processEventsForDeviceLocked。 } else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId); break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId); break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when); break; default:
LOG_ASSERT(false); // can't happen break;
} }
如果事件type是FIRST_SYNTHETIC_EVENT以后的事件,是与Device相关的事件,这些事件是在EventHub::getEvents中产生的,并不是Kernel态的事件输入设备产生的。就调用设备添加,删除,配置变化等函数。
count -= batchSize;
rawEvent += batchSize;
去掉已经处理的事件,为下一次循环做准备。
}
至此,我们看到inputreader对getEvents得到的事件都有一一对应的处理。
共分享92篇相关文档