android Input专题- Q/R/S 10/11/12 InputReader源码分析1
新课程优惠获取请加入千里马老师qq群:422901085
上节课已经讲到了InputReaderThread和InputDispatchThread已经启动了,调用了对应的run方法,这里会导致对应的threadLoop方法执行:
native/services/inputflinger/InputReaderBase.cpp
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true;}
这里会调用到mReader的loopOnce方法,这个方法将是非常关键的方法:
void InputReader::loopOnce() { int32_t oldGeneration; int32_t timeoutMillis; bool inputDevicesChanged = false; std::vector<InputDeviceInfo> inputDevices; //省略部分 //mEventHub获取数据 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); { // acquire lock AutoMutex _l(mLock); mReaderIsAliveCondition.broadcast(); if (count) { processEventsLocked(mEventBuffer, count); }//省略部分 if (oldGeneration != mGeneration) { inputDevicesChanged = true; getInputDevicesLocked(inputDevices); } } // release lock // Send out a message that the describes the changed input devices. if (inputDevicesChanged) { mPolicy->notifyInputDevicesChanged(inputDevices); }//省略部分注释 mQueuedListener->flush();}
1. mEventHub中获取getEvents数据:
这里第一步就是调用了EventHub的getEvents方法:
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { ALOG_ASSERT(bufferSize >= 1); AutoMutex _l(mLock); struct input_event readBuffer[bufferSize]; RawEvent* event = buffer; size_t capacity = bufferSize; bool awoken = false; for (;;) {//省略部分 if (mNeedToScanDevices) { mNeedToScanDevices = false; scanDevicesLocked(); mNeedToSendFinishedDeviceScan = true; }//第一次一般遍历mOpeningDevices这个列表进行各个device获取变成DEVICE_ADDED while (mOpeningDevices != nullptr) { Device* device = mOpeningDevices; ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str()); 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; //第一次扫描时候没有消息,指导后面有触摸消息才会进入这里,这里是会由下面epoll监听消息触发 while (mPendingEventIndex < mPendingEventCount) { const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++]; if (eventItem.data.fd == mINotifyFd) { if (eventItem.events & EPOLLIN) { mPendingINotify = true; } else { ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events); } continue; }//省略部分 Device* device = getDeviceByFdLocked(eventItem.data.fd); //省略部分 // This must be an input event if (eventItem.events & EPOLLIN) { //读取对应数据 int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity); //省略部分 } else { int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;//获取真实读取到的inputevent数据真实个数 size_t count = size_t(readSize) / sizeof(struct input_event); //构造出对应的event for (size_t i = 0; i < count; i++) { struct input_event& iev = readBuffer[i]; event->when = processEventTimestamp(iev); event->deviceId = deviceId; event->type = iev.type; event->code = iev.code; event->value = iev.value; event += 1; capacity -= 1; } //省略部分 } } //省略部分 }//省略部分 if (event != buffer || awoken) {//第一次扫描就会进入这里进行返回 break; }//省略部分//这里epoll在等待消息产生,产生消息EventItem都会放到mPendingEventItems中 int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); if (pollResult < 0) { //省略部分 } else { //这里对mPendingEventCount进行赋值真正有多少个事件产生 // Some events occurred. mPendingEventCount = size_t(pollResult); } } // All done, return the number of events we read. return event - buffer;}
这个方法相对还是比较复杂的,主要关心做了两部分的业务:
1、获取设备device各个信息,及监听设备变化
2、监听各个设备产生数据,并转换变成元数据RawEvent
最后会把一个个的RawEvent放入到传递进来的event这个链表里面即InputReader的
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
中的mEventBuffer,所以后面就是用这个mEventBuffer进行对应数据读取等,当mEventBuffer数据有了之后那应该到了InputReader loopOnce的下一步了。
2. 处理数据processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; //首先判断type类型,如果已经开始触摸,那么这里type值肯定会小于FIRST_SYNTHETIC_EVENT if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { //判断是否有其他消息,或者设备都换了,存在则退出这次数据的系列 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId != deviceId) { break; } //一个触摸事件是由若干个RawEvent组成,比如触摸滑动,他有abs,syn等类型 batchSize += 1; } //把一个系列事件完成后进行processEvents进行处理 processEventsForDeviceLocked(deviceId, rawEvent, batchSize); } else { //以下几种都是对设备相关移除添加进行操作的 switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: addDeviceLocked(rawEvent->when, rawEvent->deviceId); break; case EventHubInterface::DEVICE_REMOVED: removeDeviceLocked(rawEvent->when, rawEvent->deviceId); break; case EventHubInterface::FINISHED_DEVICE_SCAN: handleConfigurationChangedLocked(rawEvent->when); break; default: ALOG_ASSERT(false); // can't happen break; } } count -= batchSize; rawEvent += batchSize; }}
这里注释中对大部分已经进行讲解,最重要其实是processEventsForDeviceLocked