Android 输入系统EventHub

Posted kiydkafa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 输入系统EventHub相关的知识,希望对你有一定的参考价值。

1 EventHub初始化

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

 

  1. EventHub::EventHub(void) :  
  2.         mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1),  
  3.         mOpeningDevices(0), mClosingDevices(0),  
  4.         mNeedToSendFinishedDeviceScan(false),  
  5.         mNeedToReopenDevices(false), mNeedToScanDevices(true),  
  6.         mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {  
  7.     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  8.     //创建epoll对象,mEpollFd为epoll对象的描述符  
  9.     mEpollFd = epoll_create(EPOLL_SIZE_HINT);  
  10.     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);  
  11.     //创建inotify对象,mINotifyFd为inotify对象的描述符  
  12.     mINotifyFd = inotify_init();  
  13.     //DEVICE_PATH值为"/dev/input",监听该目录下的设备节点创建与删除操作。通过read函数读取事件。  
  14.     int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);  
  15.     LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",  
  16.             DEVICE_PATH, errno);  
  17.   
  18.     struct epoll_event eventItem;  
  19.     memset(&eventItem, 0, sizeof(eventItem));  
  20.     eventItem.events = EPOLLIN;    //监听可读事件  
  21.     eventItem.data.u32 = EPOLL_ID_INOTIFY;  
  22.     //EPOLL_CTL_ADD表示增加事件  
  23.     //epoll_ctl将事件监听添加到epoll对象中去。  
  24.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);  
  25.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);  
  26.   
  27.     int wakeFds[2];  
  28.     result = pipe(wakeFds);  
  29.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);  
  30.   
  31.     mWakeReadPipeFd = wakeFds[0];  
  32.     mWakeWritePipeFd = wakeFds[1];  
  33.   
  34.     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);  
  35.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",  
  36.             errno);  
  37.   
  38.     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);  
  39.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",  
  40.             errno);  
  41.   
  42.     eventItem.data.u32 = EPOLL_ID_WAKE;  
  43.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);  
  44.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",  
  45.             errno);  
  46. }  

这段代码主要工作:

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中做了些什么,现在看一看。

 

  1. size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {  
  2.     ALOG_ASSERT(bufferSize >= 1);  
  3.   
  4.     AutoMutex _l(mLock);  
  5.   
  6.     struct input_event readBuffer[bufferSize];  
  7.     //每存一个事件,event指针向后移动一个元素。  
  8.     RawEvent* event = buffer;  
  9.     //capacity存buffer中剩余端元素数量,capacity为0,表示buffer已满。  
  10.     size_t capacity = bufferSize;  
  11.     bool awoken = false;  
  12.     for (;;) {  
  13.         ...............  
  14.     //循环体。  
  15.     }  
  16.   
  17.     // All done, return the number of events we read.  
  18.     return event - buffer;  
  19. }  

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

                                                                                                                                                                                         

2.1 重新打开设备(mNeedToReopenDevices)

 

  1. //获取系统当前时间(native层的方法)。  
  2. nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  3.   
  4. // Reopen input devices if needed.  
  5. if (mNeedToReopenDevices) {//判断是否需要重新打开设备  
  6.     mNeedToReopenDevices = false;  
  7.   
  8.     ALOGI("Reopening all input devices due to a configuration change.");  
  9.   
  10.     closeAllDevicesLocked();//关闭、卸载所有设备  
  11.     mNeedToScanDevices = true; //下次扫描设备  
  12.     break; // return to the caller before we actually rescan  
  13. }  

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

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

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

 

  1. void EventHub::closeDeviceLocked(Device* device) {  
  2.     ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",  
  3.          device->path.string(), device->identifier.name.string(), device->id,  
  4.          device->fd, device->classes);  
  5.   
  6.     if (device->id == mBuiltInKeyboardId) {  
  7.         ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",  
  8.                 device->path.string(), mBuiltInKeyboardId);  
  9.         mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;  
  10.     }  
  11.     //判断是否是虚拟设备  
  12.     if (!device->isVirtual()) {  
  13.         //从epoll中删除对这些设备的监听  
  14.         if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {  
  15.             ALOGW("Could not remove device fd from epoll instance.  errno=%d", errno);  
  16.         }  
  17.     }  
  18.     //移除设备  
  19.     mDevices.removeItem(device->id);  
  20.     device->close();  
  21.   
  22.     // Unlink for opening devices list if it is present.  
  23.     Device* pred = NULL;  
  24.     bool found = false;  
  25.     for (Device* entry = mOpeningDevices; entry != NULL; ) {  
  26.         if (entry == device) {  
  27.             found = true;  
  28.             break;  
  29.         }  
  30.         pred = entry;  
  31.         entry = entry->next;  
  32.     }  
  33.     if (found) {  
  34.         // Unlink the device from the opening devices list then delete it.  
  35.         // We don‘t need to tell the client that the device was closed because  
  36.         // it does not even know it was opened in the first place.  
  37.         ALOGI("Device %s was immediately closed after opening.", device->path.string());  
  38.         if (pred) {  
  39.             pred->next = device->next;  
  40.         } else {  
  41.             mOpeningDevices = device->next;  
  42.         }  
  43.         delete device;  
  44.     } else {  
  45.         // Link into closing devices list.  
  46.         // The device will be deleted later after we have informed the client.  
  47.     //把这些设备添加到mClosingDevices,用来生成DEVICE_REMOVED事件  
  48.         device->next = mClosingDevices;      
  49.         mClosingDevices = device;  
  50.     }  
  51. }  

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

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

                                                                                                                                                                                         

2.2 DEVICE_REMOVED事件(mClosingDevices)

 

  1. // Report any devices that had last been added/removed.  
  2. //遍历mClosingDevices,生成DEVICE_REMOVED事件  
  3. while (mClosingDevices) {  
  4.     Device* device = mClosingDevices;  
  5.     ALOGV("Reporting device closed: id=%d, name=%s\n",  
  6.                  device->id, device->path.string());  
  7.     mClosingDevices = device->next;  
  8.     event->when = now;//设置事件的时间戳  
  9.     event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;    //设置事件对应的设备id  
  10.     event->type = DEVICE_REMOVED;   //设在事件类型DEVICE_REMOVED  
  11.     event += 1;             //event指向下一个RawEvent对象  
  12.     delete device;          //释放不需要的device  
  13.     mNeedToSendFinishedDeviceScan = true;  
  14.     //capacity为0时,表示buffer已满,则停止循环将事件返回给调用者(也就是InputReader),剩余的事件等下次getEvents调用  
  15.     if (--capacity == 0) {  
  16.          break;  
  17.     }  
  18. }  

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

                                                                                                                                                                                         

2.3 扫描加载设备(mNeedToScanDevices)

 

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

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

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

接着看一下scanDevicesLocked()函数

 

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


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

  1. status_t EventHub::scanDirLocked(const char *dirname)  
  2. {  
  3.     char devname[PATH_MAX];  
  4.     char *filename;  
  5.     DIR *dir;  
  6.     struct dirent *de;  
  7.     dir = opendir(dirname);  
  8.     if(dir == NULL)  
  9.         return -1;  
  10.     strcpy(devname, dirname);  
  11.     filename = devname + strlen(devname);  
  12.     *filename++ = ‘/‘;  
  13.     while((de = readdir(dir))) {  
  14.         if(de->d_name[0] == ‘.‘ &&  
  15.            (de->d_name[1] == ‘\0‘ ||  
  16.             (de->d_name[1] == ‘.‘ && de->d_name[2] == ‘\0‘)))  
  17.             continue;  
  18.         strcpy(filename, de->d_name);  
  19.         openDeviceLocked(devname); //  
  20.     }  
  21.     closedir(dir);  
  22.     return 0;  
  23. }  

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

 

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

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

                                                                                                                                                                                         

2.4 DEVICE_ADDED事件(mOpeningDevices)

 

  1. while (mOpeningDevices != NULL) {  
  2.     Device* device = mOpeningDevices;  
  3.     ALOGD("Reporting device opened: id=%d, name=%s\n",  
  4.                  device->id, device->path.string());  
  5.     mOpeningDevices = device->next;  
  6.     event->when = now;       //设置事件端时间戳  
  7.     event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;  
  8.     event->type = DEVICE_ADDED;      //设置事件类型DEVICE_ADDED  
  9.     event += 1;             //event指向下一个RawEvent对象,用于填写下一次事件  
  10.     mNeedToSendFinishedDeviceScan = true;  
  11.     if (--capacity == 0) {    //查看buffer是否已满  
  12.        break;  
  13.     }  
  14. }  

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

                                                                                                                                                                                         

2.5 FINISHED_DEVICE_SCAN事件(mNeedToSendFinishedDeviceScan)

  1. if (mNeedToSendFinishedDeviceScan) {  
  2.     mNeedToSendFinishedDeviceScan = false;  
  3.     event->when = now;         //设置事件端时间戳  
  4.     event->type = FINISHED_DEVICE_SCAN;  //设置事件类型FINISHED_DEVICE_SCAN  
  5.     event += 1;  
  6.     if (--capacity == 0) {  
  7.         break;  
  8.     }  
  9. }  

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

                                                                                                                                                                                         

2.6 iNotify事件、管道事件

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

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

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

readNotifyLocked() 处理inotify事件。

deviceChanged设置为true,进行下一次循环,生成设备增删事件。

接着看一下readNotifyLocked()函数中做了些什么。

  1. status_t EventHub::readNotifyLocked() {  
  2.     int res;  
  3.     char devname[PATH_MAX];  
  4.     char *filename;  
  5.     char event_buf[512];  
  6.     int event_size;  
  7.     int event_pos = 0;  
  8.     struct inotify_event *event;  
  9.   
  10.     ALOGD("EventHub::readNotify nfd: %d\n", mINotifyFd);  
  11.     //从mINotifyFd读取inotify事件,存到event_buf中,  
  12.     res = read(mINotifyFd, event_buf, sizeof(event_buf));  
  13.     if(res < (int)sizeof(*event)) {  
  14.         if(errno == EINTR)  
  15.             return 0;  
  16.         ALOGW("could not get event, %s\n", strerror(errno));  
  17.         return -1;  
  18.     }  
  19.     //printf("got %d bytes of event information\n", res);  
  20.   
  21.     strcpy(devname, DEVICE_PATH);  
  22.     filename = devname + strlen(devname);  
  23.     *filename++ = ‘/‘;  
  24.   
  25.     while(res >= (int)sizeof(*event)) {  
  26.         event = (struct inotify_event *)(event_buf + event_pos);  
  27.         //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");  
  28.         if(event->len) {  
  29.             strcpy(filename, event->name);  
  30.             if(event->mask & IN_CREATE) {//判断事件类型是否是IN_CREATE  
  31.                 openDeviceLocked(devname);  //加载对应设备  
  32.             } else {                //事件类型不是IN_CREATE,则是IN_DELETE  
  33.                 ALOGI("Removing device ‘%s‘ due to inotify event\n", devname);  
  34.                 closeDeviceByPathLocked(devname);  //卸载对应设备  
  35.             }  
  36.         }  
  37.     //移动到下一个事件。  
  38.         event_size = sizeof(*event) + event->len;  
  39.         res -= event_size;  
  40.         event_pos += event_size;    
  41.     }  
  42.     return 0;  
  43. }  

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

  1. while (mPendingEventIndex < mPendingEventCount) {  
  2. 。。。。。  
  3. if (eventItem.data.u32 == EPOLL_ID_WAKE) {  
  4.                 if (eventItem.events & EPOLLIN) {  
  5.                     ALOGD("awoken after wake()");  
  6.                     awoken = true; //用来唤醒InputRead线程  
  7.                     char buffer[16];  
  8.                     ssize_t nRead;  
  9.                     do {//从mWakeReadPipeFd读取管道事件  
  10.                         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));  
  11.                     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));  
  12.                 } else {  
  13.                     ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",  
  14.                             eventItem.events);  
  15.                 }  
  16.                 continue;  
  17.             }  
  18. 。。。。  
  19. }  
  20. 。。。。  
  21. // Return now if we have collected any events or if we were explicitly awoken.  
  22.         if (event != buffer || awoken) {  
  23.             break; //退出循环返回到InputReader。  
  24.         }  


                                                                                                                                                                                         

2.7 输入事件

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

  1. while (mPendingEventIndex < mPendingEventCount) {  
  2.       。。。。。  
  3.       //通过eventItem.data.u32 获取设备id  
  4.       ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);  
  5.       if (deviceIndex < 0) {  
  6.          ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",  
  7.                         eventItem.events, eventItem.data.u32);  
  8.      continue;  
  9.       }  
  10.       //从mDevices获取设备  
  11.       Device* device = mDevices.valueAt(deviceIndex);  
  12.             if (eventItem.events & EPOLLIN) {//epoll事件是EPOLLIN,可读,读取结果保存在readBuffer中,capacity是限制一次读取事件的个数  
  13.                int32_t readSize = read(device->fd, readBuffer,  
  14.                         sizeof(struct input_event) * capacity);  
  15.                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {  
  16.             //读取有问题  
  17.                     // Device was removed before INotify noticed.  
  18.                     ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "  
  19.                             "capacity: %d errno: %d)\n",  
  20.                             device->fd, readSize, bufferSize, capacity, errno);  
  21.                     deviceChanged = true;  
  22.                     closeDeviceLocked(device);//关闭该设备  
  23.                 } else if (readSize < 0) {  
  24.                     if (errno != EAGAIN && errno != EINTR) {  
  25.                         ALOGW("could not get event (errno=%d)", errno);  
  26.                     }  
  27.                 } else if ((readSize % sizeof(struct input_event)) != 0) {  
  28.                     ALOGE("could not get event (wrong size: %d)", readSize);  
  29.                 } else {  
  30.                     int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;  
  31.   
  32.                     size_t count = size_t(readSize) / sizeof(struct input_event);  
  33.             //遍历所有读取的输入事件  
  34.                     for (size_t i = 0; i < count; i++) {  
  35.                         struct input_event& iev = readBuffer[i];  
  36.   
  37.                         if (iev.type == EV_MSC) {  
  38.                             if (iev.code == MSC_android_TIME_SEC) {  
  39.                                 device->timestampOverrideSec = iev.value;  
  40.                                 continue;  
  41.                             } else if (iev.code == MSC_ANDROID_TIME_USEC) {  
  42.                                 device->timestampOverrideUsec = iev.value;  
  43.                                 continue;  
  44.                             }  
  45.                         }  
  46.                         if (device->timestampOverrideSec || device->timestampOverrideUsec) {  
  47.                             iev.time.tv_sec = device->timestampOverrideSec;  
  48.                             iev.time.tv_usec = device->timestampOverrideUsec;  
  49.                             if (iev.type == EV_SYN && iev.code == SYN_REPORT) {  
  50.                                 device->timestampOverrideSec = 0;  
  51.                                 device->timestampOverrideUsec = 0;  
  52.                             }  
  53.                             ALOGV("applied override time %d.%06d",  
  54.                                     int(iev.time.tv_sec), int(iev.time.tv_usec));  
  55.                         }  
  56.   
  57. #ifdef HAVE_POSIX_CLOCKS  
  58.             //设置更准确的时间             
  59.                         event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL  
  60.                                 + nsecs_t(iev.time.tv_usec) * 1000LL;  
  61.                         ALOGV("event time %lld, now %lld", event->when, now);  
  62.   
  63.                         if (event->when >= now + 10 * 1000000000LL) {  
  64.                             // Double-check.  Time may have moved on.  
  65.                             nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);  
  66.                             if (event->when > time) {  
  67.                                 ALOGW("An input event from %s has a timestamp that appears to "  
  68.                                         "have been generated using the wrong clock source "  
  69.                                         "(expected CLOCK_MONOTONIC): "  
  70.                                         "event time %lld, current time %lld, call time %lld.  "  
  71.                                         "Using current time instead.",  
  72.                                         device->path.string(), event->when, time, now);  
  73.                                 event->when = time;  
  74.                             } else {  
  75.                                 ALOGV("Event time is ok but failed the fast path and required "  
  76.                                         "an extra call to systemTime: "  
  77.                                         "event time %lld, current time %lld, call time %lld.",  
  78.                                         event->when, time, now);  
  79.                             }  
  80.                         }  
  81. #else  
  82.                         event->when = now;  
  83. #endif  
  84.             //设置一些信息  
  85.                         event->deviceId = deviceId;  
  86.                         event->type = iev.type;  
  87.                         event->code = iev.code;  
  88.                         event->value = iev.value;  
  89.                         event += 1;  //移动到下一该可用元素  
  90.                         capacity -= 1;  //可用数量减少1  
  91.                     }  
  92.                     if (capacity == 0) {//buffer存满了,mPendingEventIndex至为-1,下一次循环处理未完的事件。  
  93.                         // The result buffer is full.  Reset the pending event index  
  94.                         // so we will try to read the device again on the next iteration.  
  95.                         mPendingEventIndex -= 1;  
  96.                         break;  
  97.                     }  
  98.                 }  
  99.             } else if (eventItem.events & EPOLLHUP) {//事件类型为挂起  
  100.                 ALOGI("Removing device %s due to epoll hang-up event.",  
  101.                         device->identifier.name.string());  
  102.                 deviceChanged = true;  
  103.                 closeDeviceLocked(device);  //卸载设备  
  104.             } else {  
  105.                 ALOGW("Received unexpected epoll event 0x%08x for device %s.",  
  106.                         eventItem.events, device->identifier.name.string());  
  107.             }  
  108.         }        
  109. 。。。。。。  
  110.     rerutn event-buffer;//返回事件数量  
  111. }  

while循环后面是判断是否有inotify事件,wake事件。接着是获取epoll事件 。先获取到epoll事件,下次循环才会处理while循环。

通过mEpollFd描述符,获取epoll事件。保存在mPendingEventItems中,EPOLL_MAX_EVENTS(16)为限制一次最大读取事件次数,timeoutMillis为超时时间。

  1. mPendingEventIndex = 0;  
  2.   
  3.         mLock.unlock(); // release lock before poll, must be before release_wake_lock  
  4.         release_wake_lock(WAKE_LOCK_ID);  
  5.     //等待事件  
  6.         int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);  
  7.   
  8.         acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  9.         mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock  
  10.   
  11.         if (pollResult == 0) {  
  12.             // Timed out.  
  13.             mPendingEventCount = 0;  
  14.             break;  
  15.         }  
  16.   
  17.         if (pollResult < 0) {  
  18.             // An error occurred.  
  19.             mPendingEventCount = 0;  
  20.   
  21.             // Sleep after errors to avoid locking up the system.  
  22.             // Hopefully the error is transient.  
  23.             if (errno != EINTR) {  
  24.                 ALOGW("poll failed (errno=%d)\n", errno);  
  25.                 usleep(100000);  
  26.             }  
  27.         } else {  
  28.             // Some events occurred.  
  29.         //保存epoll事件数量,用于下次for循环处理  
  30.             mPendingEventCount = size_t(pollResult);  
  31.         }  
  32.     }  

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

                                                                                                                                                                                         

3 总结

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

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


。。。。。。














































以上是关于Android 输入系统EventHub的主要内容,如果未能解决你的问题,请参考以下文章

Android输入系统——InputManagerService

android系统用啥输入法好

android如何调用显示和隐藏系统默认的输入法

Android输入系统——InputStage

android系统下怎么广播键盘的输入消息

10.13 android输入系统_多点触摸驱动理论与框架