Android 输入系统(二)EventHub

本文详细介绍了Android系统中的EventHub组件,它负责管理/dev/input下的设备节点,处理输入事件及设备的增删。在EventHub的getEvents()函数中,包括了重新打开设备、处理DEVICE_REMOVED、DEVICE_ADDED事件、扫描加载设备、处理iNotify和管道事件,以及读取和处理输入事件。核心功能集中在getEvents(),涉及epoll、inotify和管道等技术的应用。
摘要由CSDN通过智能技术生成

接着上一篇的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) {
       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值