当前位置: 首页 > wzjs >正文

服装设计找图网站海盐建设局网站

服装设计找图网站,海盐建设局网站,做班级相册网站的目的意义,广东的网站建设案例概述 本文主要描述了Android Input框架中的InputReader的功能,InputReader模块的功能,总结成一句话就是InputReader获取输入设备的事件并将事件进行加工处理,然后传递给QueuedInputListener,最终QueuedInputListener将事件传递给…

概述

本文主要描述了Android Input框架中的InputReader的功能,InputReader模块的功能,总结成一句话就是InputReader获取输入设备的事件并将事件进行加工处理,然后传递给QueuedInputListener,最终QueuedInputListener将事件传递给InputDispatcher模块处理,事件处理的方向就是:

InputReader -> QueuedInputListener -> InputDispatcher

本文涉及的源码路径

frameworks/native/services/inputflinger/EventHub.cpp

frameworks/native/services/inputflinger/EventHub.h

frameworks/native/services/inputflinger/InputReader.cpp

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

InputReader的初始化

InputReader对象由InputManager创建如下所示:

InputManager::InputManager(const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {/* 创建事件分发对象 */mDispatcher = new InputDispatcher(dispatcherPolicy);/* 创建事件获取对象 */mReader = new InputReader(eventHub, readerPolicy, mDispatcher);initialize();
}

继续深入InputReader类的构造函数,如下所示:

InputReader::InputReader(const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) :......mConfigurationChangesToRefresh(0) {// 初始化事件监听器mQueuedListener = new QueuedInputListener(listener);......
}

Inputreader的构造函数比较简单,在这里我们关注构造函数的第一个参数和第三个参数。

eventHub: 获取事件来源的对象,InputReader通过EventHub获取输入设备上报的事件;

listener: InputReader处理完事件后的传递目的地,后面的章节有描述处理流程;

InputReader的运行

在InputManager的初始化过程中,会创建一个InputReadThread线程,如下所示:

void InputManager::initialize() {/* 创建事件获取线程 */mReaderThread = new InputReaderThread(mReader);......
}

InputManager初始化完成开始运行的时候会调用线程的运行方法,对InputReader来说最终调用InputReader::loopOnce, 如下所示:

void InputReader::loopOnce() {......size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lock......// 处理获取到的intput事件if (count) {processEventsLocked(mEventBuffer, count);}......} // release lock......// 刷新监听队列,将InputReader的事件处理结果,传递给InputDispatcher处理mQueuedListener->flush();
}

InputReader的事件获取

InputReader在Thread线程中调用EventHub的getEvents方法获取输入事件,如下所示:

 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

该方法将获取到input事件保存在mEventBuffer中,并返回获取到的事件个数

InputReader的事件处理

InputReader从EventHub获取到输入事件后,调用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;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: %d Count: %d", batchSize, count);
#endif/*** 处理deviceID设备的上报的事件* @batchSize: 事件个数*/processEventsForDeviceLocked(deviceId, rawEvent, batchSize);} else {// 处理EventHub上报的输入设备增加和删除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 happenbreak;}}count -= batchSize;rawEvent += batchSize;}
}

processEventsLocked:方法主要完成如下的功能:

1、处理系统已经存在的输入设备上报的事件;

2、处理系统输入设备的增加和删除事件;

设备添加和删除

本章节主要描述当系统增加一个输入设备时的InputReader处理流程,对于系统设备的删除和扫描的处理流程与增加处理流程类似,这里不再描述。下面我们从系统增加输入设备的处理流程进行描述。系统增加输入设备调用addDeviceLocked方法,addDeviceLocked的核心代码如下所示:

void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {ssize_t deviceIndex = mDevices.indexOfKey(deviceId);// 设备已经增加进来了,直接返回if (deviceIndex >= 0) {ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);return;}......// 创建InputDevice设备管理对象// @deviceId: 设备ID// @classes: 输入设备类型InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);device->configure(when, &mConfig, 0);device->reset(when);......mDevices.add(deviceId, device);......
}

addDeviceLocked主要完成如下功能:

a、检测该设备是否已经增加过了,如果是,直接返回;

b、根据输入设备的类型,创建InputDevice设备;

c、将创建的InputDevice设备加入到InputReader设备管理容器中;

接着我们分析createDeviceLocked方法,后续我们主要分析多点触控设备的事件处理,因此我们只保留与多点触控相关的核心实现如下所示:

InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,const InputDeviceIdentifier& identifier, uint32_t classes) {InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),controllerNumber, identifier, classes);......// 多点触控if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {device->addMapper(new MultiTouchInputMapper(device));} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {device->addMapper(new SingleTouchInputMapper(device));}return device;
}

createDeviceLocked方法的核心功能比较简单:

a、创建InputDevice设备;

b、根据输入设备的类型安装对应的事件处理器,Android系统可以处理的输入设备种类很多,对于每一类输入设备Android系统都抽象出了一个事件处理器处理该类设备上报的输入事件,对于多点触控设备来说,就是安装MultiTouchInputMapper事件处理器;

c、返回InputDevice设备;

d、这里没有描述InputMapper的实现机制,它的主要作用就是定义事件处理的接口,比如鼠标设备的处理使用CursorButtonAccumulator类,单点触控类设备使用SingleTouchInputMapper,多点触控设备使用MultiTouchInputMapper等,感兴趣的同学可以阅读Android源码去分析它们之间的关系;

设备上报事件

设备上报的输入事件处理函数是processEventsForDeviceLocked,该方法的核心实现,如下所示:

void InputReader::processEventsForDeviceLocked(int32_t deviceId,const RawEvent* rawEvents, size_t count) {......device->process(rawEvents, count);
}

进一步调用InputDevice中的process方法,实现如下:

void InputDevice::process(const RawEvent* rawEvents, size_t count) {......size_t numMappers = mMappers.size();for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {......} else {for (size_t i = 0; i < numMappers; i++) {InputMapper* mapper = mMappers[i];mapper->process(rawEvent);}}}
}

该方法的核心功能就是遍历每一个事件,调用设备自己注册的事件处理器进行处理,对于多点触控设备来说,调用如下的方法:

void MultiTouchInputMapper::process(const RawEvent* rawEvent) {TouchInputMapper::process(rawEvent);/* 处理多点触控坐标信息 */mMultiTouchMotionAccumulator.process(rawEvent);
}

继续调用TouchInputMapper类中的process进行处理,该方法的核心实现,如下所示:

void TouchInputMapper::process(const RawEvent* rawEvent) {/* 鼠标按键事件处理 */mCursorButtonAccumulator.process(rawEvent);/* 鼠标滚轮事件处理 */mCursorScrollAccumulator.process(rawEvent);/* 触摸按键 */mTouchButtonAccumulator.process(rawEvent);// 当前事件全部上报处理完成,进行事件同步操作if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {sync(rawEvent->when);}
}

事件处理的具体细节,我们不再深入谈论,该方法当事件处理完成后,调用sync进行事件同步,核心如下所示:

void TouchInputMapper::sync(nsecs_t when) {......// Sync touch// 同步触摸坐标syncTouch(when, next);......processRawTouches(false /*timeout*/);
}

该方法会调用syncTouch这个虚拟方法,对于多点触控设备来说,最终调用MultiTouchInputMapper子类实现syncTouch, 这里不再详细展开描述。然后调用processRawTouches开始事件的处理,实现方法如下所示:

void TouchInputMapper::processRawTouches(bool timeout) {......const size_t N = mRawStatesPending.size();size_t count;// 遍历每一个上报的事件for(count = 0; count < N; count++) {const RawState& next = mRawStatesPending[count];......mCurrentRawState.copyFrom(next);if (mCurrentRawState.when < mLastRawState.when) {mCurrentRawState.when = mLastRawState.when;}cookAndDispatch(mCurrentRawState.when);}// 事件处理完成,清空mRawStatesPendingif (count != 0) {mRawStatesPending.removeItemsAt(0, count);}.......
}

接着调用cookAndDispatch方法,核心实现如下所示:

void TouchInputMapper::cookAndDispatch(nsecs_t when) {// Always start with a clean state.mCurrentCookedState.clear();......cookPointerData();......} else {// 触摸屏......if (!mCurrentMotionAborted) {dispatchButtonRelease(when, policyFlags);dispatchHoverExit(when, policyFlags);dispatchTouches(when, policyFlags);dispatchHoverEnterAndMove(when, policyFlags);dispatchButtonPress(when, policyFlags);}......}......
}

该方法中,我们为了叙述的简单,只保留了触摸屏幕相关的处理,cookPointerData方法的实现,这里不详细描述,主要就是处理坐标信息,对于触摸屏幕设备来说,就是调用dispatchTouches方法接着处理,核心实现如下所示:

void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {......if (currentIdBits == lastIdBits) {if (!currentIdBits.isEmpty()) {......// 滑动dispatchMotion(when, policyFlags, mSource,AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,AMOTION_EVENT_EDGE_FLAG_NONE,mCurrentCookedState.cookedPointerData.pointerProperties,mCurrentCookedState.cookedPointerData.pointerCoords,mCurrentCookedState.cookedPointerData.idToIndex,currentIdBits, -1,mOrientedXPrecision, mOrientedYPrecision, mDownTime);}} else {......// Dispatch pointer up events.// 触点抬起while (!upIdBits.isEmpty()) {uint32_t upId = upIdBits.clearFirstMarkedBit();dispatchMotion(when, policyFlags, mSource,AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,mLastCookedState.cookedPointerData.pointerProperties,mLastCookedState.cookedPointerData.pointerCoords,mLastCookedState.cookedPointerData.idToIndex,dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);dispatchedIdBits.clearBit(upId);}......if (moveNeeded && !moveIdBits.isEmpty()) {ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);dispatchMotion(when, policyFlags, mSource,AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,mCurrentCookedState.cookedPointerData.pointerProperties,mCurrentCookedState.cookedPointerData.pointerCoords,mCurrentCookedState.cookedPointerData.idToIndex,dispatchedIdBits, -1, mOrientedXPrecision, mOrientedYPrecision, mDownTime);}// Dispatch pointer down events using the new pointer locations.// 触点按下while (!downIdBits.isEmpty()) {......dispatchMotion(when, policyFlags, mSource,AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,mCurrentCookedState.cookedPointerData.pointerProperties,mCurrentCookedState.cookedPointerData.pointerCoords,mCurrentCookedState.cookedPointerData.idToIndex,dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);}}
}

该方法中会处理三种触摸动作,滑动,抬起和按下,最终调用dispatchMotion方法进行处理,核心实现如下所示:

void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,......float xPrecision, float yPrecision, nsecs_t downTime) {......// 根据触摸屏幕的坐标事件,初始化NotifyMotionArgs对象NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,action, actionButton, flags, metaState, buttonState, edgeFlags,mViewport.displayId, pointerCount, pointerProperties, pointerCoords,xPrecision, yPrecision, downTime);// 找到InputReader的Listen,在初始时指定,最终指向是QueuedInputListenergetListener()->notifyMotion(&args);
}

该方法的核心,就是构造一个NotifyMotionArgs,然后调用InputReader自己的listen中的方法,最终调用QueuedInputListener中的notifyMotion,核心实现如下:

// 加入到内部mArgsQueue队列中
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {mArgsQueue.push(new NotifyMotionArgs(*args));
}

该方法的实现非常简单,构造一个NotifyMotionArgs,然后加入mArgsQueue队列中。

TouchInputMapper方法的process处理流程方法,讲述完成,然后我们回到MultiTouchInputMapper,接着调用了mMultiTouchMotionAccumulator中的process方法,这里不再展开叙述。

void MultiTouchInputMapper::process(const RawEvent* rawEvent) {TouchInputMapper::process(rawEvent);/* 处理多点触控坐标信息 */mMultiTouchMotionAccumulator.process(rawEvent);
}

至此,一个输入设备的事件处理流程讲述完成,最后,我们回到InputReader线程执行函数的,如下所示:

void InputReader::loopOnce() {......size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockAutoMutex _l(mLock);mReaderIsAliveCondition.broadcast();// 处理获取到的intput事件if (count) {processEventsLocked(mEventBuffer, count);}......} // release lock......// 刷新监听队列,将InputReader的事件处理结果,传递给InputDispatcher处理mQueuedListener->flush();
}

我们可以看到,设备上报的所有输入事件处理完成后,最后调用mQueuedListener的flush方法。这个方法的实现,下一个章节进行描述。

InputReader事件传递

上一个章节,我们描述了InputReader处理输入设备上报事件的处理流程,当InputReader处理完上报的事件后调用mQueuedListener的flush,该方法的实现如下所示:

void QueuedInputListener::flush() {size_t count = mArgsQueue.size();for (size_t i = 0; i < count; i++) {NotifyArgs* args = mArgsQueue[i];args->notify(mInnerListener);delete args;}mArgsQueue.clear();
}

该方法的实现比较简单,调用notify虚拟方法,对于触摸设备来说就是调用子类实现如下所示:

// 直接传递给InputDispatcher
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {listener->notifyMotion(this);
}

直接调用listener的notifyMotion进行处理,这里的listener其实就是InputDispatcher,这在InputReader初始化的时候进行传递的,如下所示:

InputManager::InputManager(const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {/* 创建事件分发对象 */mDispatcher = new InputDispatcher(dispatcherPolicy);/* 创建事件获取对象 */mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
}InputReader::InputReader(const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) :mContext(this), mEventHub(eventHub), mPolicy(policy),mGlobalMetaState(0), mGeneration(1),mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),mConfigurationChangesToRefresh(0) {// 初始化事件监听器mQueuedListener = new QueuedInputListener(listener);{ // acquire lockAutoMutex _l(mLock);refreshConfigurationLocked(0);updateGlobalMetaStateLocked();} // release lock
}

将InputDispatcher当做QueuedInputListener的listener。最终listener->notifyMotion(this)调用到,如下所示:

void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
......
}

这里不再详解展开描述,在InputDispatcher模块进行详细描述。

总结

本文描述了InputReader对EventHub事件的处理,InputReader对于每一个不同类型的输入设备调用对应的事件处理器进行处理,当事件处理完成后最终将处理结果传递给InputDispatcher。下一章我们描述InputDispatcher的功能。


文章转载自:

http://2VpU745O.qnpyz.cn
http://ss4u7k5W.qnpyz.cn
http://tY3L7XMj.qnpyz.cn
http://nf9yOJZS.qnpyz.cn
http://CgBCakJV.qnpyz.cn
http://u9Bbu4ik.qnpyz.cn
http://eTuLkRsC.qnpyz.cn
http://oWJxP0FH.qnpyz.cn
http://horGYeFc.qnpyz.cn
http://seA8JAKo.qnpyz.cn
http://nGVagv2K.qnpyz.cn
http://5RHUeCCh.qnpyz.cn
http://vPdeTEP7.qnpyz.cn
http://G6N7v2Vl.qnpyz.cn
http://dIedfC81.qnpyz.cn
http://JmpTtQn3.qnpyz.cn
http://6X9VZauD.qnpyz.cn
http://uYTQakkM.qnpyz.cn
http://FMs7ksIs.qnpyz.cn
http://l4usdxFV.qnpyz.cn
http://lqf68S4B.qnpyz.cn
http://2WCstCvS.qnpyz.cn
http://L2wogwOS.qnpyz.cn
http://4W5eEsui.qnpyz.cn
http://sonUbN6G.qnpyz.cn
http://On3gZWpc.qnpyz.cn
http://khKunxHq.qnpyz.cn
http://S9XdNmfW.qnpyz.cn
http://hyYDrJMb.qnpyz.cn
http://PpA6Osq8.qnpyz.cn
http://www.dtcms.com/wzjs/686952.html

相关文章:

  • python做网站有什么优势网站建设 郑州
  • 深圳建设网站哪家强WordPress手动切换主题
  • 微信小程序联盟网站中小企业网站开发
  • 网站轮播图怎么保存项目投资网
  • php网站开发报告用别人的照片做网站
  • 商城网站素材青岛永诚网络管理有限公司
  • 宜春制作网站公司哪家好范县网站建设费用
  • 番禺区pc端网站建设济宁网页
  • 微信网站开发报价表wap浏览器网页版
  • 做网站还赚钱么企业网站建站系统哪个好用
  • 黑白高端网站建设网站做的图上传后字变得很模糊
  • 营销型手机网站专业做制作网站
  • 学校网站logo怎么做wordpress 页面显示分类文章列表
  • 照片做3d网站vue如何网站开发
  • 网站开发用什么工具好网站用什么cms
  • 做网站微信公众号金银饰品那家网站做的好
  • 网站线上投票怎样做可信网站认证有用
  • 河南一般建一个网站需要多少钱wordpress slider pro
  • 家装设计效果图网站企业展厅图片
  • 帝国cms灵动标签做网站地图做网站要写代码吗
  • 网站开发及维护是什么如何经营电商平台
  • 成品网站速成网站智能锁网站建设关键词
  • 在国内可以做国外的网站吗太原有网站工程公司吗
  • 电子商务网站开发实训wordpress 主题页脚修改
  • 旅游网站开发的意义相关资料直播电商平台开发
  • 重庆网站建设电话网站首页为什么不收录
  • 推广展示类网站有哪些马边彝族移动网站建设
  • 福建省建设局网站实名制wordpress字体投影
  • 如何做网站卖东西phpcms 专题网站模板
  • wordpress 评论弹窗登陆网站怎么优化关键词