本文转载自:http://blog.csdn.net/jscese/article/details/43561773

前文Linux/Android——Input系统之InputReader (七)介绍到了inputreader的运作流程,如何获取events到初步的分发,依次分析到InputMapper做第一步的处理.

前文有解析Mapper类型的依赖规则,不做重述.,这里单以触摸屏input_device 对应的SingleTouchInputMapper 为例。

撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/43561773本博文来自【 jscese 】的博客!

SingleTouchInputMapper:

原型定义在InputReader.h 中:

  1. class SingleTouchInputMapper : public TouchInputMapper {
  2. public:
  3. SingleTouchInputMapper(InputDevice* device);
  4. virtual ~SingleTouchInputMapper();
  5. virtual void reset(nsecs_t when);
  6. virtual void process(const RawEvent* rawEvent);
  7. protected:
  8. virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
  9. virtual void configureRawPointerAxes();
  10. virtual bool hasStylus() const;
  11. private:
  12. SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
  13. };

继承自TouchInputMapper,函数实现全部放在InputReader.cpp中,先看首先调用进的process:

  1. void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
  2. TouchInputMapper::process(rawEvent);  //调用父类的process
  3. mSingleTouchMotionAccumulator.process(rawEvent);  //数据的同步
  4. }

继续跟:

  1. void TouchInputMapper::process(const RawEvent* rawEvent) {
  2. mCursorButtonAccumulator.process(rawEvent);
  3. mCursorScrollAccumulator.process(rawEvent);
  4. mTouchButtonAccumulator.process(rawEvent);   //这三个Accumulator 进一步处理rawEvent ,原型都在InputReader.cpp中,根据rawEvent->code 取出对应信息
  5. ALOGW("jscese dsp TouchInputMapper::process event type==0x%x, code==0x%x, valude ==0x%x \n",rawEvent->type,rawEvent->code,rawEvent->value);
  6. if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
  7. sync(rawEvent->when); //同步
  8. }
  9. }

上面的几个process 有兴趣可以看下,会依次根据code type抽取对应的信息保存,比如CursorMotionAccumulator 中的  mRelX ,mRelY 代表相对坐标值

作为我调试的触摸框来说这里只在TouchButtonAccumulator中抽取了 BTN_TOUCH 一个按下或者抬起的事件值.  ABS_X. ABS_Y 并没有在这里读取。而是在后面的SingleTouchMotionAccumulator::process中.

其它的input 设备就需要看驱动具体上报的code type了.

TouchInputMapper::sync:

从上面分析可以看到。一个rawEvent过来的时候 都会先经过三个process去抽取信息,然后才会检测是否是一个同步sync的rawEent事件,

这也就是为什么 在驱动中 一次完整的事件上报,总是先report一些button res abs之类的,最后来一个sync!

这个同步函数比较长只留意几个地方就可以了:

  1. void TouchInputMapper::sync(nsecs_t when) {
  2. ALOGW("TouchInputMapper::sync");
  3. // Sync button state.
  4. mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
  5. | mCursorButtonAccumulator.getButtonState();
  6. // Sync scroll state.
  7. ...
  8. // Sync touch state.
  9. bool havePointerIds = true;
  10. mCurrentRawPointerData.clear();
  11. syncTouch(when, &havePointerIds);//调用子类的syncTouch,这里自然调用的是我 触摸框的 SingleTouchMotionAccumulator的syncTouch,更新ABS 坐标值,我这里是把数据存入到mCurrentRawPointerData中供下面cook
  12. ...
  13. // Reset state that we will compute below.
  14. mCurrentFingerIdBits.clear();
  15. mCurrentStylusIdBits.clear();
  16. mCurrentMouseIdBits.clear();
  17. mCurrentCookedPointerData.clear();   // 先清掉
  18. ...
  19. // Cook pointer data.  This call populates the mCurrentCookedPointerData structure
  20. // with cooked pointer data that has the same ids and indices as the raw data.
  21. // The following code can use either the raw or cooked data, as needed.
  22. cookPointerData();  //这个函数不跟进去了,太庞大,cook数据,主要是生成 mCurrentCookedPointerData.pointerCoords,mCurrentCookedPointerData.pointerProperties和mCurrentCookedPointerData.idToIndex
  23. ...
  24. dispatchTouches(when, policyFlags);  //又进行分发
  25. ...
  26. //一些数据保存之类的操作
  27. }

这里正常的处理是调用dispatchTouches 函数 ,往里走是dispatchMotion

  1. void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
  2. int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
  3. const PointerProperties* properties, const PointerCoords* coords,
  4. const uint32_t* idToIndex, BitSet32 idBits,
  5. int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
  6. PointerCoords pointerCoords[MAX_POINTERS];
  7. PointerProperties pointerProperties[MAX_POINTERS];
  8. uint32_t pointerCount = 0;
  9. ...
  10. getListener()->notifyMotion(&args);  //回调
  11. }

这里是走的signeltouch的所以最终会调用getListener()->notifyMotion(&args),如果是Keydown事件。根据上面的逻辑会在cookPointerData 之前调用synthesizeButtonKeys 依次会调用到context->getListener()->notifyKey(&args);

QueuedInputListener:

上面分析到的notifyMotion最后会调用到这个类中,这个作为inputreader环节的最后交接维护类,回顾一下InputRead的构建,可以看下:

  1. // --- InputReader ---
  2. InputReader::InputReader(const sp<EventHubInterface>& eventHub,
  3. const sp<InputReaderPolicyInterface>& policy,
  4. const sp<InputListenerInterface>& listener)   //这里注意最后一个参数~
  5. ...
  6. {
  7. mQueuedListener = new QueuedInputListener(listener); //构造了一个QueuedinputListener
  8. ...
  9. }

这里又要看下最开始的构造调用了/frameworks/base/services/input/InputManager.cpp中:

  1. InputManager::InputManager(
  2. ...
  3. mDispatcher = new InputDispatcher(dispatcherPolicy);
  4. mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  //可以看到这里传入的是InputDispatcher ,但是上面直接用的InputListenerInterface ,,直接强制转换成了 父类指针!  这里注意一下
  5. ...
  6. }

所以在InputReader中构造QueuedInputListener的时候保存的是InputDispatcher的父类指针,保存在私有成员 mInnerListener

  1. // --- QueuedInputListener ---
  2. QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
  3. mInnerListener(innerListener) {
  4. }

为什么这么做是应为 后续调用的纯虚函数。将会交由InputDispatcher 的函数来实现。实现了一个传递,C++ 就是这样,要整个看明白。才知道设计者写的代码到底跑到哪里去了~

往下分析流程就知道我为什么这么说了.

回到前面,调用 QueuedInputListener::notifyMotion,将这个notifyMotion push进mArgsQueue 链表队列,然后在 loopOnce() 中做完上述一次事件的获取以及分发处理之后将会调用  mQueuedListener->flush();

  1. void QueuedInputListener::flush() {
  2. size_t count = mArgsQueue.size();
  3. for (size_t i = 0; i < count; i++) {
  4. NotifyArgs* args = mArgsQueue[i];
  5. args->notify(mInnerListener);  //这里依次调用上面push进来的不同种类notify的notify函数,NotifyConfigurationChangedArgs /  NotifyKeyArgs / NotifyMotionArgs / NotifySwitchArgs / NotifyDeviceResetArgs 这几种
  6. delete args;
  7. }
  8. mArgsQueue.clear();
  9. }

这里还是单以我做的notifyMotion为例:

  1. void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
  2. listener->notifyMotion(this);
  3. }

就是这里。又来了一个 notifyMotion调用,这个纯虚函数 ,两个子类QueuedInputListener  InputDispatcher 中都有实现,就像上面分析到的,最终是调用到 InputDispatcher 中的notifyMotion !

之后就是InputDispatcher 的处理了,这里不继续。后续再说~

Linux/Android——Input系统之InputMapper 处理 (八)【转】的更多相关文章

  1. Linux/Android——Input系统之InputReader (七)【转】

    本文转载自:http://blog.csdn.net/jscese/article/details/42739197 在前文Linux/Android——Input系统之frameworks层Inpu ...

  2. Linux/Android——Input系统之frameworks层InputManagerService (六)【转】

    本文转载自:http://blog.csdn.net/u013491946/article/details/72638954 版权声明:免责声明: 本人在此发文(包括但不限于汉字.拼音.拉丁字母)均为 ...

  3. Linux/Android——input系统之 kernel层 与 frameworks层交互 (五)【转】

    本文转载自:http://blog.csdn.net/jscese/article/details/42291149 之前的四篇博文记录的都是linux中的input体系相关的东西,最底层以我调试的u ...

  4. input系统——android input系统

    AndroidInput系统--JNI NativeInputManager InputManger InputReader AndroidInput系统--InputReader AndroidIn ...

  5. Linux/Android——input子系统核心 (三)【转】

    本文转载自:http://blog.csdn.net/jscese/article/details/42123673 之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. ...

  6. Linux 下Input系统应用编程实战

    作者:杨源鑫(也是我们的校园代理) 经授权转载于公众号嵌入式开发圈,有些许修改. 什么是input子系统?不管是什么操作系统,都有一个程序用于管理各种输入设备,哪些是输入设备?比如,电脑键盘.鼠标,智 ...

  7. Linux & Android 多点触摸协议

    Linux & Android 多点触摸协议 Android4.0多点触摸入门 1 KERNEL 对于触摸屏的驱动我们简单的划分为两个主要的部分,一个是注册,另一个是上报. 1.1 注册 单点 ...

  8. Linux/Android——input_handler之evdev (四) 【转】

    转自:http://blog.csdn.net/u013491946/article/details/72638919 版权声明:免责声明: 本人在此发文(包括但不限于汉字.拼音.拉丁字母)均为随意敲 ...

  9. 图解Android - Android GUI 系统 (5) - Android的Event Input System

    Android的用户输入处理 Android的用户输入系统获取用户按键(或模拟按键)输入,分发给特定的模块(Framework或应用程序)进行处理,它涉及到以下一些模块: Input Reader: ...

随机推荐

  1. 【牛客小白月赛6】 J 洋灰三角 - 快速幂&逆元&数学

    题目地址:https://www.nowcoder.com/acm/contest/136/J 解法一: 推数学公式求前n项和: 当k=1时,即为等差数列,Sn = n+pn(n−1)/2 当k≠1时 ...

  2. 洛谷——P4053 [JSOI2007]建筑抢修

    P4053 [JSOI2007]建筑抢修 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的 ...

  3. 使用枚举(emum)代替常量类

    原文: 作者:逍遥不羁 来源:CSDN 原文:https://blog.csdn.net/javaloveiphone/article/details/52371706 版权声明:本文为博主原创文章, ...

  4. 树莓派 -- 输入设备驱动 (key)

    输入设备(如按键,键盘,触摸屏等)是典型的字符设备,其一般工作原理是底层在按键或触摸等动作发生时产生一个中断,然后CPU通过SPI,I2C总线读取键值. 在这些工作中之后中断和读键值是与设备相关的,而 ...

  5. Node.js中的Buffer

    Buffer介绍 为什么要用Buffer? 在Node/ES6 出现之前,前端工程师只需要进行一些简单的额字符串或者ODM操作就可以满足业务需求了,所有对二进制数据比较陌生. 在node出现之后,前端 ...

  6. node new Buffer()详解

    new Buffer(size) size {Number} 分配一个 size 字节大小的新 Buffer.size 必须小于等于 require('buffer').kMaxLength(在64位 ...

  7. jQuery对table排序

    <script> //col对应列,cmp两数比较方法,返回值为TRUE,FALSE function sort(col, cmp) { var table = $("#test ...

  8. 使用js生成条形码以及二维码

    一.用js生成条形码这种业务场景不是很常见的,最近刚好又接到这种需求 Google一下,发现github还真有这方面的轮子,感谢github,省去了我们很多造轮子的过程, 好了言归正传,首先引入jsb ...

  9. CSU1160

    十进制-十六进制 Time Limit: 1 Sec  Memory Limit: 128 MB Description 把十进制整数转换为十六进制,格式为0x开头,10~15由大写字母A~F表示. ...

  10. 洛谷P3373 线段树2(补上注释了)

    毒瘤题.找了一下午+晚上的BUG,才发现原来query_tree写的是a%p; 真的是一个教训 UPD:2019.6.18 #include<iostream> #include<c ...