Android6.0输入系统之EventHub源码分析

本文深入探讨Android6.0输入系统中的EventHub,详细阐述了EventHub如何利用INotify和Epoll机制建立设备监听,以及getEvents()函数的工作原理,涉及输入设备管理和原始输入事件的读取。通过对EventHub的构造函数、scanDevicesLocked()和readNotifyLocked()等关键函数的分析,揭示了Android输入事件的处理流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇文章《Android6.0输入系统之InputManagerService构成分析》 完成了IMS的创建,接着就沿着输入系统这条路继续往下走。
在EventHub的构造函数中,它通过INotify与Epoll机制建立起对设备点增删事件及可读状态的监听。INotify是Linux内核所提供的一种文件系统变化通知机制。它可以为应用程序监控文件系统的变化,如文件的新建、删除、读写等等。它有两个基本对象,inotify对象对应一个队列,应用程序可以向inotify对象添加多个监听,当被监听的事件发生时,可以通过read()函数从inotify对象中将事件信息读取出来;而watch对象则用来描述文件系统的变化事件的监听,它是一个二元组,包括监听目标和事件掩码两个元素,监听目标是文件系统的一个路径,可以是文件也可以是文件夹。Epoll可以使用一次等待监听多个描述符的可读/可写状态。
frameworks/native/services/inputflinger/EventHub.cpp

设备节点监听的建立
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);

    //1.首先使用epoll_create()函数创建一个epoll对象
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    ...
    //2.创建一个inotify对象,用来监听设备节点的增删事件
    mINotifyFd = inotify_init();
    //将存储设备点的路径dev/input作为监听对象添加到inotify对象中
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
            DEVICE_PATH, errno);

    //3.将mINotifyFd作为epoll的一个监控对象
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;  //监听mINotifyFd可读
    eventItem.data.u32 = EPOLL_ID_INOTIFY;
    //将对mINotifyFd的监听注册到epoll对象中
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    ...
}
getEvents()函数的工作方式、输入设备管理、原始输入事件的监听与读取
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);

    AutoMutex _l(mLock);

    struct input_event readBuffer[bufferSize];

    /* event指针指向在buffer中下一个可用于存储事件的RawEvent结构体。每存储一个事件,event指针都会向后偏移一个元素 */
    RawEvent* event = buffer;
    //capacity记录了buffer中的剩余的元素数量
    size_t capacity = bufferSize;
    bool awoken = false;
    //循环getEvent()函数的主体
    for (;;) {
        ...
        //遍历mClosingDevices链表,为每一个已卸载的设备生成DEVICE_REMOVED事件
        while (mClosingDevices) {
            Device* device = mClosingDevices;
            ALOGV("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_I
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值