Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3045473
  • 博文数量: 396
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4209
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-04 13:04
文章分类

全部博文(396)

文章存档

2022年(1)

2021年(2)

2020年(8)

2019年(24)

2018年(135)

2017年(158)

2016年(68)

我的朋友

分类: Android平台

2020-07-01 14:53:32

接着上一篇的InputManagerService,这里主要介绍一下EventHub。EventHub主要是访问/dev/input下的所有设备节点,并将输入事件、设备节点的增删返给InputReader。

                                                                                                                                                                                         
1 EventHub初始化

由上一篇可知,EventHub对象是在NativeInputManager构造函数中创建的。先看一下EventHub构造函数中都做了些什么

    EventHub::EventHub(void) :
            mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1),
            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);
        //创建epoll对象,mEpollFd为epoll对象的描述符
        mEpollFd = epoll_create(EPOLL_SIZE_HINT);
        LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
        //创建inotify对象,mINotifyFd为inotify对象的描述符
        mINotifyFd = inotify_init();
        //DEVICE_PATH值为"/dev/input",监听该目录下的设备节点创建与删除操作。通过read函数读取事件。
        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);
     
        struct epoll_event eventItem;
        memset(&eventItem, 0, sizeof(eventItem));
        eventItem.events = EPOLLIN;    //监听可读事件
        eventItem.data.u32 = EPOLL_ID_INOTIFY;
        //EPOLL_CTL_ADD表示增加事件
        //epoll_ctl将事件监听添加到epoll对象中去。
        result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);
     
        int wakeFds[2];
        result = pipe(wakeFds);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);
     
        mWakeReadPipeFd = wakeFds[0];
        mWakeWritePipeFd = wakeFds[1];
     
        result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                errno);
     
        result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                errno);
     
        eventItem.data.u32 = EPOLL_ID_WAKE;
        result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
        LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                errno);
    }

这段代码主要工作:

    1.初始化一些成员变量
    2.创建epoll对象,EPOLL_SIZE_HINT = 8代表最大监听数为8.
    3.创建inotify对象,监听/dev/input下设备节点的增删。
    4.将mINotifyFd添加到epoll中,作为一个监控对象。
    5.创建管道,将管道读取端的可读事件添加到epoll中。使epoll_wait()返回,唤醒InputReader线程。

                                                                                                                                                                                         
2 EventHub::getEvents()

EventHub的主要工作都是在getEvents函数中,InputReaderThread通过循环调用EventHub的getEvents()函数获取输入事件。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指针向后移动一个元素。
        RawEvent* event = buffer;
        //capacity存buffer中剩余端元素数量,capacity为0,表示buffer已满。
        size_t capacity = bufferSize;
        bool awoken = false;
        for (;;) {
            ...............
        //循环体。
        }
     
        // All done, return the number of events we read.
        return event - buffer;
    }

以上是getEvents()的整体模型,接着看循环体中的方法。

                                                                                                                                                                                         

2.1 重新打开设备(mNeedToReopenDevices)

    //获取系统当前时间(native层的方法)。
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     
    // Reopen input devices if needed.
    if (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
    }

由EventHub构造函数可知mNeedToReopenDevices为初始值false,第一次调用getEvents()时不会运行上面的代码块。其中调用了closeAllDevicesLocked()函数

void EventHub::closeAllDevicesLocked() {
    while (mDevices.size() > 0) {
        closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1));
    }
}

closeAllDevicesLocked()函数中遍历mDevices,通过closeDeviceLocked()函数卸载所有这些设备。closeDeviceLocked()函数如下

    void EventHub::closeDeviceLocked(Device* device) {
        ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
             device->path.string(), device->identifier.name.string(), device->id,
             device->fd, device->classes);
     
        if (device->id == mBuiltInKeyboardId) {
            ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
                    device->path.string(), mBuiltInKeyboardId);
            mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
        }
        //判断是否是虚拟设备
        if (!device->isVirtual()) {
            //从epoll中删除对这些设备的监听
            if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
                ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);
            }
        }
        //移除设备
        mDevices.removeItem(device->id);
        device->close();
     
        // Unlink for opening devices list if it is present.
        Device* pred = NULL;
        bool found = false;
        for (Device* entry = mOpeningDevices; entry != NULL; ) {
            if (entry == device) {
                found = true;
                break;
            }
            pred = entry;
            entry = entry->next;
        }
        if (found) {
            // Unlink the device from the opening devices list then delete it.
            // We don't need to tell the client that the device was closed because
            // it does not even know it was opened in the first place.
            ALOGI("Device %s was immediately closed after opening.", device->path.string());
            if (pred) {
                pred->next = device->next;
            } else {
                mOpeningDevices = device->next;
            }
            delete device;
        } else {
            // Link into closing devices list.
            // The device will be deleted later after we have informed the client.
        //把这些设备添加到mClosingDevices,用来生成DEVICE_REMOVED事件
            device->next = mClosingDevices;    
            mClosingDevices = device;
        }
    }

closeDeviceLocked()函数主要工作:
1.从Epoll中删除监听(EPOLL_CTL_DEL)。
2.mDevices中删除Device对象

3.将删除端Device对象添加到mClosingDevices中。用于之后向InputReader发送DEVICE_REMOVED事件

                                                                                                                                                                                         

2.2 DEVICE_REMOVED事件(mClosingDevices)

    // Report any devices that had last been added/removed.
    //遍历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_ID : device->id;    //设置事件对应的设备id
        event->type = DEVICE_REMOVED;   //设在事件类型DEVICE_REMOVED
        event += 1;                  //event指向下一个RawEvent对象
        delete device;            //释放不需要的device
        mNeedToSendFinishedDeviceScan = true;
        //capacity为0时,表示buffer已满,则停止循环将事件返回给调用者(也就是InputReader),剩余的事件等下次getEvents调用
        if (--capacity == 0) {
             break;
        }
    }

mClosingDevices初始值为0,所以刚开始调用getEvents()函数不会运行上述代码块。该块中主要是遍历mClosingDevices,生成DEVICE_REMOVED事件。

                                                                                                                                                                                         
2.3 扫描加载设备(mNeedToScanDevices)

    if (mNeedToScanDevices) {
       mNeedToScanDevices = false;
       scanDevicesLocked();    //打开/dev/input下所有输入设备
       mNeedToSendFinishedDeviceScan = true;
    }

mNeedToScanDevices初始值为true,所以第一次getEvents会运行该代码块。该代码块主要工作:

    1 mNeedToScanDevices赋值为false,避免重复扫描打开设备。
    2 调用scanDevicesLocked(),//打开/dev/input下所有输入设备。
    3 mNeedToSendFinishedDeviceScan赋值为true,用于生成FINISHED_DEVICE_SCAN事件。

接着看一下scanDevicesLocked()函数

    void EventHub::scanDevicesLocked() {
        status_t res = scanDirLocked(DEVICE_PATH);
        if(res < 0) {
            ALOGE("scan dir failed for %s\n", DEVICE_PATH);
        }
        //创建一个虚拟的输入设备(这个不太清楚)。
        if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
            createVirtualKeyboardLocked();
        }
    }


scanDevicesLocked()函数中调用了scanDirLocked()函数,接着看scanDirLocked()函数:

    status_t EventHub::scanDirLocked(const char *dirname)
    {
        char devname[PATH_MAX];
        char *filename;
        DIR *dir;
        struct dirent *de;
        dir = opendir(dirname);
        if(dir == NULL)
            return -1;
        strcpy(devname, dirname);
        filename = devname + strlen(devname);
        *filename++ = '/';
        while((de = readdir(dir))) {
            if(de->d_name[0] == '.' &&
               (de->d_name[1] == '\0' ||
                (de->d_name[1] == '.' && de->d_name[2] == '\0')))
                continue;
            strcpy(filename, de->d_name);
            openDeviceLocked(devname); //
        }
        closedir(dir);
        return 0;
    }

scanDirLocked()函数遍历/dev/input文件夹下的所有设备节点,并分别执行openDeviceLocked(devname),加载设备。openDeviceLocked()函数比较长,就不全部贴出来了,只将一些重要的部分弄出来。

    status_t EventHub::openDeviceLocked(const char *devicePath) {
        //打开设备节点
        int fd = open(devicePath, O_RDWR | O_CLOEXEC);
        if(fd < 0) {
            ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
            return -1;
        }
        
        //获取device的name、driver version、id等。
        。。。。。。
        //创建Device
        int32_t deviceId = mNextDeviceId++;
        Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
        。。。。。。
        // Load the configuration file for the device. 加载配置信息
        loadConfigurationLocked(device);
        // Figure out the kinds of events the device reports.
        //设置device->classes,为设备分配类别(鼠标、键盘、触摸板等)
        
        // Register with epoll.将设备节点描述符的可读事件添加到Epoll中。
        struct epoll_event eventItem;
        memset(&eventItem, 0, sizeof(eventItem));
        eventItem.events = EPOLLIN;
        eventItem.data.u32 = deviceId;   //设备id
        if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
            ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
            delete device;
            return -1;
        }
        。。。。。
        //将device添加到mDevice中。
        addDeviceLocked(device);
        return 0;
    }

addDeviceLocked将Device添加到mDevice中,同时也会添加到mOpeningDevices中,用来生成DEVICE_ADDED事件,发送给InputReader。这之后就可以通过getEvents读取到设备产生的输入事件了。

                                                                                                                                                                                         
2.4 DEVICE_ADDED事件(mOpeningDevices)

    while (mOpeningDevices != NULL) {
        Device* device = mOpeningDevices;
        ALOGD("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;        //设置事件类型DEVICE_ADDED
        event += 1;                //event指向下一个RawEvent对象,用于填写下一次事件
        mNeedToSendFinishedDeviceScan = true;
        if (--capacity == 0) {      //查看buffer是否已满
           break;
        }
    }

由于上面scanDevicesLocked时将/dev/input下的设备节点打开,并添加到mOpeningDevices中,所以会运行此代码块。这里主要是遍历mOpeningDevices,设置DEVICE_ADDED事件。

                                                                                                                                                                                         
2.5 FINISHED_DEVICE_SCAN事件(mNeedToSendFinishedDeviceScan)

    if (mNeedToSendFinishedDeviceScan) {
        mNeedToSendFinishedDeviceScan = false;
        event->when = now;          //设置事件端时间戳
        event->type = FINISHED_DEVICE_SCAN;    //设置事件类型FINISHED_DEVICE_SCAN
        event += 1;
        if (--capacity == 0) {
            break;
        }
    }

上述三个代码块都会将mNeedToSendFinishedDeviceScan设为true,所以接着生成FINISHED_DEVICE_SCAN类型的事件。也就是当设备增删事件后,需要向getEvents()函数调用者发送FINISHED_DEVICE_SCAN事件。
由代码顺序可以知道DEVICE_REMOVED事件优先级最高、然后DEVICE_ADDED事件、FINISHED_DEVICE_SCAN事件最低。只有高优先级的事件处理完之后才会处理低优先级的事件。

                                                                                                                                                                                         
2.6 iNotify事件、管道事件

接着是while循环,检查是否有未处理的设备事件。

    while (mPendingEventIndex < mPendingEventCount) {
          const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
          //EPOLL_ID_INOTIFY是EventHub初始化时,用来检测/dev/input下添加、删除设备事件。
          if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
               if (eventItem.events & EPOLLIN) {
            mPendingINotify = true;    //符合条件标记inotify事件待处理。
             } else {
               ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
             }
             continue;//继续处理mPendingEventItems中的事件
          }
           。。。。。。
    }
     
            // readNotify() will modify the list of devices so this must be done after
            // processing all other events to ensure that we read all remaining events
            // before closing the devices.
        //判断是否有待处理的inotify事件。
            if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
                mPendingINotify = false;
                readNotifyLocked();
                deviceChanged = true;
            }
        ALOGD("getEvents -----9 deviceChanged:%d",deviceChanged);
            // Report added or removed devices immediately.
            if (deviceChanged) {
                continue;//如果处理有inotify事件,处理后,进行下一次循环,生成设备增删事件。
            }
    。。。。。。

mPendingINotify赋值为false,表示之后没有待处理的inotify事件。

readNotifyLocked() 处理inotify事件。

deviceChanged设置为true,进行下一次循环,生成设备增删事件。
接着看一下readNotifyLocked()函数中做了些什么。

    status_t EventHub::readNotifyLocked() {
        int res;
        char devname[PATH_MAX];
        char *filename;
        char event_buf[512];
        int event_size;
        int event_pos = 0;
        struct inotify_event *event;
     
        ALOGD("EventHub::readNotify nfd: %d\n", mINotifyFd);
        //从mINotifyFd读取inotify事件,存到event_buf中,
        res = read(mINotifyFd, event_buf, sizeof(event_buf));
        if(res < (int)sizeof(*event)) {
            if(errno == EINTR)
                return 0;
            ALOGW("could not get event, %s\n", strerror(errno));
            return -1;
        }
        //printf("got %d bytes of event information\n", res);
     
        strcpy(devname, DEVICE_PATH);
        filename = devname + strlen(devname);
        *filename++ = '/';
     
        while(res >= (int)sizeof(*event)) {
            event = (struct inotify_event *)(event_buf + event_pos);
            //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
            if(event->len) {
                strcpy(filename, event->name);
                if(event->mask & IN_CREATE) {//判断事件类型是否是IN_CREATE
                    openDeviceLocked(devname);    //加载对应设备
                } else {                //事件类型不是IN_CREATE,则是IN_DELETE
                    ALOGI("Removing device '%s' due to inotify event\n", devname);
                    closeDeviceByPathLocked(devname);  //卸载对应设备
                }
            }
        //移动到下一个事件。
            event_size = sizeof(*event) + event->len;
            res -= event_size;
            event_pos += event_size;  
        }
        return 0;
    }

主要工作
1 通过read()函数读取iNotify事件
2 遍历所有的iNotify事件
3 判断iNotify事件类型,IN_CREATE类型则加载设备,IN_DELETE类型则卸载设备。
接着是判断是否是管道事件

    while (mPendingEventIndex < mPendingEventCount) {
    。。。。。
    if (eventItem.data.u32 == EPOLL_ID_WAKE) {
                    if (eventItem.events & EPOLLIN) {
                        ALOGD("awoken after wake()");
                        awoken = true; //用来唤醒InputRead线程
                        char buffer[16];
                        ssize_t nRead;
                        do {//从mWakeReadPipeFd读取管道事件
                            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;
                }
    。。。。
    }
    。。。。
    // Return now if we have collected any events or if we were explicitly awoken.
            if (event != buffer || awoken) {
                break; //退出循环返回到InputReader。
            }


                                                                                                                                                                                         

2.7 输入事件

接着到输入事件了。根据输入事件,进行设置时间戳、id、类型、值等。拥有返回给调用者InputReader。

    while (mPendingEventIndex < mPendingEventCount) {
          。。。。。
          //通过eventItem.data.u32 获取设备id
          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;
          }
          //从mDevices获取设备
          Device* device = mDevices.valueAt(deviceIndex);
                if (eventItem.events & EPOLLIN) {//epoll事件是EPOLLIN,可读,读取结果保存在readBuffer中,capacity是限制一次读取事件的个数
                   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.
                        ALOGW("could 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) {
                            ALOGW("could not get event (errno=%d)", errno);
                        }
                    } else if ((readSize % sizeof(struct input_event)) != 0) {
                        ALOGE("could not get event (wrong size: %d)", readSize);
                    } 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];
     
                            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));
                            }
     
    #ifdef HAVE_POSIX_CLOCKS
                //设置更准确的时间           
                            event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
                                    + nsecs_t(iev.time.tv_usec) * 1000LL;
                            ALOGV("event time %lld, now %lld", event->when, now);
     
                            if (event->when >= now + 10 * 1000000000LL) {
                                // Double-check.  Time may have moved on.
                                nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
                                if (event->when > time) {
                                    ALOGW("An input event from %s has a timestamp that appears to "
                                            "have been generated using the wrong clock source "
                                            "(expected CLOCK_MONOTONIC): "
                                            "event time %lld, current time %lld, call time %lld.  "
                                            "Using current time instead.",
                                            device->path.string(), event->when, time, now);
                                    event->when = time;
                                } else {
                                    ALOGV("Event time is ok but failed the fast path and required "
                                            "an extra call to systemTime: "
                                            "event time %lld, current time %lld, call time %lld.",
                                            event->when, time, now);
                                }
                            }
    #else
                            event->when = now;
    #endif
                //设置一些信息
                            event->deviceId = deviceId;
                            event->type = iev.type;
                            event->code = iev.code;
                            event->value = iev.value;
                            event += 1;  //移动到下一该可用元素
                            capacity -= 1;    //可用数量减少1
                        }
                        if (capacity == 0) {//buffer存满了,mPendingEventIndex至为-1,下一次循环处理未完的事件。
                            // 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());
                }
            }      
    。。。。。。
        rerutn event-buffer;//返回事件数量
    }

while循环后面是判断是否有inotify事件,wake事件。接着是获取epoll事件 。先获取到epoll事件,下次循环才会处理while循环。
通过mEpollFd描述符,获取epoll事件。保存在mPendingEventItems中,EPOLL_MAX_EVENTS(16)为限制一次最大读取事件次数,timeoutMillis为超时时间。

    mPendingEventIndex = 0;
     
            mLock.unlock(); // release lock before poll, must be before release_wake_lock
            release_wake_lock(WAKE_LOCK_ID);
        //等待事件
            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
     
            if (pollResult == 0) {
                // Timed out.
                mPendingEventCount = 0;
                break;
            }
     
            if (pollResult < 0) {
                // An error occurred.
                mPendingEventCount = 0;
     
                // Sleep after errors to avoid locking up the system.
                // Hopefully the error is transient.
                if (errno != EINTR) {
                    ALOGW("poll failed (errno=%d)\n", errno);
                    usleep(100000);
                }
            } else {
                // Some events occurred.
            //保存epoll事件数量,用于下次for循环处理
                mPendingEventCount = size_t(pollResult);
            }
        }

到现在getEvents函数基本上就完了。还有许多内容待揣摩。

                                                                                                                                                                                         

3 总结

EventHub主要工作:设备管理(加载、卸载)、输入事件读取。核心代码就是getEvent(),该代码中完成了这些事情。

其中使用到的epoll、inotify、管道这些技术可以好好研究下。。。。

阅读(1457) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~