EventHub分析(二)

来源:互联网 发布:2016淘宝搜索排名规则 编辑:程序博客网 时间:2024/05/04 17:35

2, EventHub

一台移动设备中能产生输入消息的部件很多,比如键盘,触摸屏以及按键等等,EventHub主要是将这些设备产生的消息打包成一种格式,再发往上层进行处理.

首先看看EventHub的构造函数,

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);    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);    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);    int major, minor;    getLinuxRelease(&major, &minor);    // EPOLLWAKEUP was introduced in kernel 3.5    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);}

这里面涉及的是linux驱动的知识,反正知道会监视目录文件  /dev/input就可以了。

在getEvents方法中,

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {•••if (mNeedToScanDevices) {            mNeedToScanDevices = false;            scanDevicesLocked();            mNeedToSendFinishedDeviceScan = true;        }•••}

如果是第一次调用getEvents方法,则会调用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();    }}
static const char *WAKE_LOCK_ID = "KeyEvents";static const char *DEVICE_PATH = "/dev/input";

直接看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方法,在该目录下存放的并不是设备,而是event文件,这些event文件对应的设备信息可以在文件 /proc/bus/input/devices中可以查看。不同的设备对应不同的文件。

  openDeviceLocked方法太长,首先打开设备并获取设备的信息,然后判断设备的类型,根据类型来初始化,最后为设备创建一个InputDevice对象,然后调用addDeviceLocked方法将InputDevice对象添加到EventHub的mDevices列表中。

  总体的流程图如下:


0 0
原创粉丝点击