• Linux/Android——Input系统之InputMapper 处理 (八)【转】


    本文转载自: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 中:

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

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

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


    继续跟:

    [objc] view plain copy
     
    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.   
    6.     ALOGW("jscese dsp TouchInputMapper::process event type==0x%x, code==0x%x, valude ==0x%x  ",rawEvent->type,rawEvent->code,rawEvent->value);  
    7.   
    8.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
    9.         sync(rawEvent->when); //同步  
    10.     }  
    11. }  

    上面的几个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!

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

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

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

    [objc] view plain copy
     
    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.   
    7.     PointerCoords pointerCoords[MAX_POINTERS];  
    8.     PointerProperties pointerProperties[MAX_POINTERS];  
    9.     uint32_t pointerCount = 0;  
    10.   
    11. ...  
    12.   
    13.     getListener()->notifyMotion(&args);  //回调  
    14.   
    15. }  



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

    QueuedInputListener:

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

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

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

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



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

    [objc] view plain copy
     
    1. // --- QueuedInputListener ---  
    2.   
    3. QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :  
    4.         mInnerListener(innerListener) {  
    5. }  

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

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

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

    [objc] view plain copy
     
    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为例:

    [objc] view plain copy
     
    1. void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {  
    2.     listener->notifyMotion(this);  
    3. }  


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

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

  • 相关阅读:
    汇编与反汇编
    在Mac环境下跑汇编
    使用python-openCV对摄像头捕捉的镜头进行二值化并打上文字
    关于js中的setTimeout和setInterval
    在MacOX下安装python-opencv
    为什么在保护模式下IA-32处理器最高可访问4GB的内存
    Mac上常用的一些命令
    说说chrome上的JS调试
    Steganography-图片隐写术
    Makefile-filter和filter-out
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7813242.html
Copyright © 2020-2023  润新知