电商网站seo方案,网页版微信怎么截图,新闻类网站源码,建被采集的网站这一节主要了解输入事件的获取#xff0c;InputReaderThread继承自C的Thread类#xff0c;Thread类封装了pthread线程工具#xff0c;提供了与Java层Thread类相似的API。C的Thread类提供了一个名为threadLoop()的纯虚函数#xff0c;当线程开始运行后#xff0c;将会在内建… 这一节主要了解输入事件的获取InputReaderThread继承自C的Thread类Thread类封装了pthread线程工具提供了与Java层Thread类相似的API。C的Thread类提供了一个名为threadLoop()的纯虚函数当线程开始运行后将会在内建的线程循环中不断地调用threadLoop()直到此函数返回false则退出线程循环从而结束线程。
/frameworks/native/services/inputflinger/InputThread.cppclass InputThreadImpl : public Thread {
public:explicit InputThreadImpl(std::functionvoid() loop): Thread(/* canCallJava */ true), mThreadLoop(loop) {}~InputThreadImpl() {}private:std::functionvoid() mThreadLoop;bool threadLoop() override {mThreadLoop();return true;}
};
/frameworks/native/services/inputflinger/reader/InputReader.cppstatus_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread std::make_uniqueInputThread(InputReader, [this]() { loopOnce(); }, [this]() { mEventHub-wake(); });return OK;
}void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged false;std::vectorInputDeviceInfo inputDevices;{ // acquire lockAutoMutex _l(mLock);oldGeneration mGeneration;timeoutMillis -1;uint32_t changes mConfigurationChangesToRefresh;if (changes) {mConfigurationChangesToRefresh 0;timeoutMillis 0;refreshConfigurationLocked(changes);} else if (mNextTimeout ! LLONG_MAX) {nsecs_t now systemTime(SYSTEM_TIME_MONOTONIC);timeoutMillis toMillisecondTimeoutDelay(now, mNextTimeout);}} // release lock// 通过EventHub获取事件列表 读取的结果存储在参数mEventBuffer中 表示事件的个数size_t count mEventHub-getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockAutoMutex _l(mLock);mReaderIsAliveCondition.broadcast();//如果获取到事件 对事件进行加工处理if (count) {processEventsLocked(mEventBuffer, count);}if (mNextTimeout ! LLONG_MAX) {nsecs_t now systemTime(SYSTEM_TIME_MONOTONIC);if (now mNextTimeout) {
#if DEBUG_RAW_EVENTSALOGD(Timeout expired, latency%0.3fms, (now - mNextTimeout) * 0.000001f);
#endifmNextTimeout LLONG_MAX;timeoutExpiredLocked(now);}}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);}// 发布事件 将所有事件交给InputDispatchermQueuedListener-flush();
}
分析:首先从EventHub中抽取未处理的事件列表。这些事件分为两类一类是从设备节点中读取的原始输入事件另一类则是输入设备可用性变化事件简称为设备事件。通过 processEventsLocke()对事件进行处理。对于设备事件此函数对根据设备的可用性加载或移除设备对应的配置信息。对于原始输入事件则在进行转译、封装与加工后将结果暂存到mQueuedListener 中。所有事件处理完毕后调用mQueuedListener.flush()将所有暂存的输入事件一次性地交付给InputDispatcher。 /frameworks/native/services/inputflinger/reader/EventHub.cppsize_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;size_t capacity bufferSize;bool awoken false;for (;;) {nsecs_t now systemTime(SYSTEM_TIME_MONOTONIC);// 重新打开设备节点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}...if (mNeedToScanDevices) {mNeedToScanDevices false;scanDevicesLocked();mNeedToSendFinishedDeviceScan true;}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;// 处理未被InputReader取走的输入事件与设备事件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;}if (eventItem.data.fd mWakeReadPipeFd) {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;}Device* device getDeviceByFdLocked(eventItem.data.fd);if (!device) {ALOGE(Received unexpected epoll event 0x%08x for unknown fd %d., eventItem.events,eventItem.data.fd);ALOG_ASSERT(!DEBUG);continue;}if (device-videoDevice eventItem.data.fd device-videoDevice-getFd()) {if (eventItem.events EPOLLIN) {size_t numFrames device-videoDevice-readAndQueueFrames();if (numFrames 0) {ALOGE(Received epoll event for video device %s, but could not read frame,device-videoDevice-getName().c_str());}} else if (eventItem.events EPOLLHUP) {// TODO(b/121395353) - consider adding EPOLLRDHUPALOGI(Removing video device %s due to epoll hang-up event.,device-videoDevice-getName().c_str());unregisterVideoDeviceFromEpollLocked(*device-videoDevice);device-videoDevice nullptr;} else {ALOGW(Received unexpected epoll event 0x%08x for device %s., eventItem.events,device-videoDevice-getName().c_str());ALOG_ASSERT(!DEBUG);}continue;}// This must be an input eventif (eventItem.events EPOLLIN) {int32_t readSize read(device-fd, readBuffer, sizeof(struct input_event) * capacity);...}// 设备节点发生增删操作if (mPendingINotify mPendingEventIndex mPendingEventCount) {mPendingINotify false;readNotifyLocked();deviceChanged true;}// 等待新的事件int pollResult epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);mLock.lock(); // reacquire lock after pollif (pollResult 0) {// Timed out.mPendingEventCount 0;break;}if (pollResult 0) {// An error occurred.mPendingEventCount 0;// Sleep after errors to avoid locking up the system.// Hopefully the error is transient.if (errno ! EINTR) {ALOGW(poll failed (errno%d)\n, errno);usleep(100000);}} else {// Some events occurred.mPendingEventCount size_t(pollResult);}}// 获取所读取的事件数量return event - buffer;
}
分析: getEvent()函数使用Epoll的核心是mPendingEventItems数组它是一个事件池。getEvents()函数会优先从这个事件池获取epoll 事件进行处理并将读取相应的原始输入事件返回给调用者。当无法获得任何事件时会调用epoll_wait()函数等待新事件到来将事件池重新注满然后再重新处理事件池中的Epoll事件。
EventHub的直译是事件集线器它将所有的输入事件通过一个接口 getEvents()把从多个输人设备节点中读取的事件交给InputReader它是输人系统最底层的一个组件。
/frameworks/native/services/inputflinger/reader/InputReader.cpp void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent rawEvents; count;) {int32_t type rawEvent-type;size_t batchSize 1;// 根据事件的类型区分原始输入事件或设备增删事件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;}batchSize 1;}
#if DEBUG_RAW_EVENTSALOGD(BatchSize: %zu Count: %zu, batchSize, count);
#endif// 处理属于某一设备的一批事件 batchSize表示属于此设备的输入事件的个数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); // cant happenbreak;}}count - batchSize;rawEvent batchSize;}
}void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,size_t count) {auto deviceIt mDevices.find(eventHubId);if (deviceIt mDevices.end()) {ALOGW(Discarding event for unknown eventHubId %d., eventHubId);return;}std::shared_ptrInputDevice device deviceIt-second;if (device-isIgnored()) {// ALOGD(Discarding event for ignored deviceId %d., deviceId);return;}// 调用InputDevice的process函数进行处理device-process(rawEvents, count);
}
/frameworks/native/services/inputflinger/reader/InputDevice.cppvoid InputDevice::process(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent rawEvents; count ! 0; rawEvent) {
#if DEBUG_RAW_EVENTSALOGD(Input event: device%d type0x%04x code0x%04x value0x%08x when% PRId64,rawEvent-deviceId, rawEvent-type, rawEvent-code, rawEvent-value, rawEvent-when);
#endifif (mDropUntilNextSync) {if (rawEvent-type EV_SYN rawEvent-code SYN_REPORT) {mDropUntilNextSync false;
#if DEBUG_RAW_EVENTSALOGD(Recovered from input event buffer overrun.);
#endif} else {
#if DEBUG_RAW_EVENTSALOGD(Dropped input event while waiting for next input sync.);
#endif}} else if (rawEvent-type EV_SYN rawEvent-code SYN_DROPPED) {ALOGI(Detected input event buffer overrun for device %s., getName().c_str());mDropUntilNextSync true;reset(rawEvent-when);} else {for_each_mapper_in_subdevice(rawEvent-deviceId, [rawEvent](InputMapper mapper) {mapper.process(rawEvent);});}--count;}
} 分析:InputDevice用来存储输入设备的信息事件交给InputMapper的process()事件处理它有很多子类 用于加工不同类型的原始输入事件这里有点像责任连模式。