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

来源:互联网 发布:上海交大 知乎 编辑:程序博客网 时间:2024/06/06 05:31
   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;}



0 0
原创粉丝点击