您的位置:首页 > 移动开发 > Android开发

Android 输入事件系统之 EventHub 和 Input Lib(事件解析库)

2016-09-22 16:33 369 查看
EventHub和 Input Lib 关系如下类图所示


 Device 类是 EventHub的内部类,这里用EventHub&Device 表示,EventHub和Device是属于inputflinger 模块(frameworks\native\services\inputflinger)
 其余类都在Input Lib库里(frameworks\native\libs\input)

    KeyLayoutMap\KeyCharacterMap\VirtualKeyMap 都包含各自的Parser内部类。



下面看下具体细节实现,EventHub 中实现了两个关键的函数,一是EventHub() 构造函数,另一个是getEvents() 函数。

一、 EventHub() 构造函数主要是联合inotify 和 epoll
机制,监听设备的插拔事件,设备节点的数据。

inotify :监听输入设备的add和delete事件。

epoll : 监听各输入设备节点是否有新数据,这个机制主要优点是监听大批量fd时效率依旧很高,而这个也是select方式最大缺点。

              如果某个节点有新数据,epoll_wait 函数会返回新数据,阻塞等待事件。

EventHub::EventHub(void) :
mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
mOpeningDevices(0), mClosingDevices(0),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false), mNeedToScanDevices(true),
mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);

mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);

mINotifyFd = inotify_init();
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);// 监听设备插拔 ,DEVICE_PATH = "/dev/input"
LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
DEVICE_PATH, errno);

struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
eventItem.data.u32 = EPOLL_ID_INOTIFY;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);// 监听设备目录个节点数据 ,DEVICE_PATH = "/dev/input"
.....

}
二 、getEvents() 函数功能

 1. 初次启动或者配置改变时,重新扫描设备,加载设备配置信息。

 2. 执行epoll_wait 监听设备节点,如果监听到设备节点有变化,则登记设备节点到pending 列表;否则阻塞等待。

 3. 把pending 列表里的event 里记录的设备节点,读取节点数据,并保存到buffer里返回给调用者。

 4. 如果读取到event,则退出for循环,把event数据返回给调用则。

<pre name="code" class="cpp">size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
.....

for (;;) {
....
// 是否需要扫描设备,第一次肯定需要
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
.....
// Grab the next input event.
bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
......
ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);// 得到新数据的设备id
if (deviceIndex < 0) {
ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
eventItem.events, eventItem.data.u32);
continue;
}
Device* device = mDevices.valueAt(deviceIndex);// 获取到有新数据的设备
ALOGV("eventItem.data.u32:%d deviceIndex:%d path:%s",eventItem.data.u32,deviceIndex,device->path.string());
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);// 从设备读取数据

......
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++) {
struct input_event& iev = readBuffer[i];
ALOGV("%s got: time=%d.%06d, 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);

if (iev.type == EV_MSC) {
if (iev.code == MSC_ANDROID_TIME_SEC) {
device->timestampOverrideSec = iev.value;
continue;
} else if (iev.code == MSC_ANDROID_TIME_USEC) {
device->timestampOverrideUsec = iev.value;
continue;
}
}
if (device->timestampOverrideSec || device->timestampOverrideUsec) {
iev.time.tv_sec = device->timestampOverrideSec;
iev.time.tv_usec = device->timestampOverrideUsec;
if (iev.type == EV_SYN && iev.code == SYN_REPORT) {
device->timestampOverrideSec = 0;
device->timestampOverrideUsec = 0;
}
ALOGV("applied override time %d.%06d",
int(iev.time.tv_sec), int(iev.time.tv_usec));
}

// 把数据格式化
event->when = now;

event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
}
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 if (eventItem.events & EPOLLHUP) {
ALOGI("Removing device %s due to epoll hang-up event.",
device->identifier.name.string());
deviceChanged = true;
closeDeviceLocked(device);
} else {
ALOGW("Received unexpected epoll event 0x%08x for device %s.",
eventItem.events, device->identifier.name.string());
}
}
// 如果读取到数据,则退出循环
if (event != buffer || awoken) {
break;
}
.....
// 否则继续监听
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock
....
}

// All done, return the number of events we read.
return event - buffer;
}




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: