Linux 3.10
Android 4.4
http://blog.csdn.net/u013686019/article/details/53691888
Linux 3.10
Android 4.4
一、提纲挈领
EventHub是Android中Input事件的处理中心,完成kernel上报事件的读取、初步处理、传递。
- 读取:Input设备一旦产生动作,将通过事件(Event)的方式通知user空间;user空间通过读取/dev/input目录下各个文件,获取事件及事件所属的Input设备信息:
- 初步处理:kernel是以struct input_event的格式上报数据,这里只是根据读取的该结构体做一个简单的封装,成RawEvent形式的数据:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
struct RawEvent {
nsecs_t when;
int32_t deviceId;
int32_t type;
int32_t code;
int32_t value;
};
传递:RawEvent形式的数据传递给InputReader,由它进一步细分为Android可以识别的数据形式。
二、处理流程
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
AutoMutex _l(mLock);
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
ALOGI("getEvents, enter.");
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// 1、mNeedToReopenDevices = false
if (mNeedToReopenDevices) {
ALOGI("getEvents, mNeedToReopenDevices.");
mNeedToReopenDevices = false;
ALOGI("Reopening all input devices due to a configuration change.");
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
// 2、mClosingDevices == null
while (mClosingDevices) {
Device* device = mClosingDevices;
ALOGI("getEvents, Reporting device closed: id=%d, name=%s\n",
device->id, device->path.string());
mClosingDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
event->type = DEVICE_REMOVED;
event += 1;
delete device;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
// 3、EventHub对象构建时设置true
if (mNeedToScanDevices) {
ALOGI("getEvents, mNeedToScanDevices.");
mNeedToScanDevices = false;
// 4、扫描"/dev/input"目录,若属于我们需要监测的Input设备,就把它加入监测List
// 详见“Input设备open流程”
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
// 5、遍历mOpeningDevices列表,把设备的一些信息打包进RawEvent对象中
while (mOpeningDevices != NULL) {
Device* device = mOpeningDevices;
ALOGW("getEvents, Reporting device opened: id=%d, name=%s\n",
device->id, device->path.string());
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED;
event += 1; // 启动构建下一个RawEvent对象
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
// 6、添加一个FINISHED_DEVICE_SCAN类型的RawEvent对象
if (mNeedToSendFinishedDeviceScan) {
ALOGW("getEvents, mNeedToSendFinishedDeviceScan.");
mNeedToSendFinishedDeviceScan = false;
event->when = now;
event->type = FINISHED_DEVICE_SCAN;
event += 1;
if (--capacity == 0) {
break;
}
}
// Grab the next input event.
bool deviceChanged = false;
ALOGW("getEvents: before while, mPendingEventIndex=%d\n", mPendingEventIndex);
// 8、有事件,去处理
// mPendingEventCount:等待处理的事件的个数
// mPendingEventIndex:指示当前需要处理的事件
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
ALOGW("getEvents: #1 mPendingEventIndex=%d\n", mPendingEventIndex);
// EPOLL_ID_INOTIFY:用于监控某个目录(子目录)下是否有新增或者删除文件,在这里用于监视/dev/input
// 如果有新增设备,则会在该目录内创建新文件;
// 如果删除设备,则该目录的相应文件会被删除。
if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
} else {
ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
}
continue;
}
// EPOLL_ID_WAKE:EventHub维护一个pipe,当pipe的写入端按照适当格式写入事件后,
// getEvents可以通过pipe的读取端获取这个虚拟事件
if (eventItem.data.u32 == EPOLL_ID_WAKE) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
char buffer[16];
ssize_t nRead;
do {
nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
} else {
ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
eventItem.events);
}
continue;
}
// 9、当前事件属于的Input设备
ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
if (deviceIndex < 0) {
ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
eventItem.events, eventItem.data.u32);
continue;
}
// 10、获取当前事件属于的Input设备
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