上篇文章《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_ID : device->id;
             //设置事件的类型为DEVICE_REMOVED
             event->type = DEVICE_REMOVED;
             //将event指针移动到下一个可用于填充事件的RawEvent
             event += 1;
             //生成DEVICE_REMOVED事件之后,被卸载的Device对象就不再需要了
             delete device;
             mNeedToSendFinishedDeviceScan = true;
             if (--capacity == 0) {
  
                 break;
             }
         }
        if (mNeedToScanDevices) {
  
             mNeedToScanDevices = false;
            //scanDevicesLocked()将会把dev/input下所有可用的输入设备打开并储存到Device结构体中
             scanDevicesLocked();
             mNeedToSendFinishedDeviceScan = true;
         }
        while (mOpeningDevices != NULL) {
  
             Device* device = mOpeningDevices;
             ALOGV("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;
             mNeedToSendFinishedDeviceScan = true;
             if (--capacity == 0) {
  
                 break;
             }
         }
        if (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;
        //处理未被inputReader取走的输入事件与设备事件
         while (mPendingEventIndex < mPendingEventCount) {
  
             const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
             /* 通过Epoll事件的data字段确定此事件表示mINotifyFd可读注意EPOLL_ID_INOTIFY在EventHub的构造函数中作为data字段向Epoll注册mINotifyFd的可读事件*/
             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;   //继续处理下一条Epoll事件
             }
             //其他Epoll事件的处理
             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;
             }
             //通过Epoll的data.u32字段获取设备Id,进而获取对应的Device对象
             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;
             }
            Device* device = mDevices.valueAt(deviceIndex);
             if (eventItem.events & EPOLLIN) {
  
                 //如果Epoll事件为EPOLLIN,表示设备节点有原始输入事件可读
                 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: %" PRId32
                             " bufferSize: %zu capacity: %zu 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);
                     //将读取到的每一个input_event结构体中的数据转换为RawEvent对象,并存储在buffer参数中以返回给调用者
                     for (size_t i = 0; i < count; i++) {
  
                         struct input_event& iev = readBuffer[i];
                         ...
                         event->deviceId = deviceId;
                         event->type = iev.type;
                         event->code = iev.code;
                         event->value = iev.value;
                         event += 1;
                         capacity -= 1;
                     }
           ...
         //若mINotifyFd有数据可读,说明该设备节点发生了增删操作
         //若INotify事件待处理
         if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
  
             mPendingINotify = false;
             /* 调用readNotifyLocked()函数读取并处理存储在mINotifyFd中的INotify事件这个函数将完成设备的加载与卸载 */
             readNotifyLocked();
             deviceChanged = true;
         }
        //设备节点增删操作发生时,则重新执行循环体,以便将设备变化的事件放入buffer中
         //若处理了INotify事件,则返回到循环开始处,生成设备增删事件
         if (deviceChanged) {
  
             continue;
         }
        // Return now if we have collected any events or if we were explicitly awoken.
         if (event != buffer || awoken) {
  
             break;
         }
        //若此次getEvents()调用没能获取事件,说明mPendingEventIndex中没有事件可用。
         mPendingEventIndex = 0;
...
    //返回本次getEvents()调用所读的事件数据
     return event - buffer;
 }
 加载所有输入设备由scanDevicesLocked()函数完成,代码如下:
void EventHub::scanDevicesLocked() {
  
     //调用scanDirLocked()函数遍历dev/input文件夹下的所有设备节点并打开
     status_t res = scanDirLocked(DEVICE_PATH);
     if(res < 0) {
  
         ALOGE("scan dir failed for %s\n", DEVICE_PATH);
     }
     //时刻打开这一个名为VIRTUAL_KEYBOARD虚拟的输入设备
     if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
  
         createVirtualKeyboardLocked();
     }
 }
 scanDevicesLocked()遍历指定文件夹下的所有设备节点,分别对其执行openDeviceLocked()完成设备的打开操作,为设备节点创建并加载Device结构体。代码如下:
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;
     }
     //通过ioctl()函数从设备节点中获取输入设备的厂商信息
     InputDeviceIdentifier identifier;
     ...
    //分配一个设备id并创建Device结构体
     int32_t deviceId = mNextDeviceId++;
     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
     ...
     //为设备加载配置信息
     loadConfigurationLocked(device);
    // 通过ioctl函数获取设备的事件位掩码
     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
     ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
     ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
     ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
     ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
     ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
     ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
    ...
     //将设备节点的描述符的可读事件注册到Epoll中。
     struct epoll_event eventItem;
     memset(&eventItem, 0, sizeof(eventItem));
     eventItem.events = EPOLLIN;
     if (mUsingEpollWakeup) {
  
         eventItem.events |= EPOLLWAKEUP;
     }
     eventItem.data.u32 = deviceId;
     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;
     }
    ...
     //调用addDeviceLocked()将Device添加到mDevices字典中
     addDeviceLocked(device);
     return 0;
 }
 调用readNotifyLocked()函数读取并处理存储在mINotifyFd中的INotify事件这个函数将完成设备的加载与卸载。代码如下:
status_t EventHub::readNotifyLocked() {
  
     ...
     //从mINotifyFd中读取INotify事件列表
     res = read(mINotifyFd, event_buf, sizeof(event_buf));
     ...
     //逐个处理列表中的事件
     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) {
  
                 openDeviceLocked(devname); //若事件类型为IN_CREATE,则加载对应的设备
             } else {
  
                 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;
 }
 EventHub作为直接操作设备节点的输入系统组件,通过接口getEvent()向使用者提供抽取设备事件与原始输入事件的功能,其核心都是在getEvent()函数中完成的。下面接着讨论EventHub所提供的原始输入事件如何被加工为Android输入事件——InputReader。