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

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


                                   

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


SingleTouchInputMapper:

 原型定义在InputReader.h 中:

 class SingleTouchInputMapper : public TouchInputMapper {public:    SingleTouchInputMapper(InputDevice* device);    virtual ~SingleTouchInputMapper();    virtual void reset(nsecs_t when);    virtual void process(const RawEvent* rawEvent);protected:    virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);    virtual void configureRawPointerAxes();    virtual bool hasStylus() const;private:    SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;};

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


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

继续跟:

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

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

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

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

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

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


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



QueuedInputListener:

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

// --- InputReader ---InputReader::InputReader(const sp& eventHub,        const sp& policy,        const sp& listener)   //这里注意最后一个参数~...{    mQueuedListener = new QueuedInputListener(listener); //构造了一个QueuedinputListener...}

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

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


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

// --- QueuedInputListener ---QueuedInputListener::QueuedInputListener(const sp& innerListener) :        mInnerListener(innerListener) {}

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

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

回到前面,调用 QueuedInputListener::notifyMotion,将这个notifyMotion push进mArgsQueue 链表队列,然后在 loopOnce() 中做完上述一次事件的获取以及分发处理之后将会调用  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);  //这里依次调用上面push进来的不同种类notify的notify函数,NotifyConfigurationChangedArgs /  NotifyKeyArgs / NotifyMotionArgs / NotifySwitchArgs / NotifyDeviceResetArgs 这几种        delete args;    }    mArgsQueue.clear();}

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

void NotifyMotionArgs::notify(const sp& listener) const {    listener->notifyMotion(this);}

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


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


更多相关文章

  1. android MapView 定位与Overlay onTap事件处理
  2. Android中EventBus(事件总线)传递数据
  3. 〖Android〗屏幕触屏事件录制与回放
  4. Android View Touch的事件分发机制
  5. 【Android FFMPEG 开发】Android Studio 工程配置 FFMPEG ( 动态
  6. Android Touch事件分发机制详解之由点击引发的战争
  7. 浅谈Android事件分发机制
  8. Android 监听Home键按键事件

随机推荐

  1. Android中ProgressBar用法简单实例
  2. Android获取字体高度和设置行高
  3. android binder机制之——(创建binder服务
  4. android 5.0后矢量图形
  5. android中sqlite的使用
  6. android 检查网络状态
  7. 【Android 基础】Animation 动画介绍和实
  8. Android Paint之 setXfermode PorterDuff
  9. Android_Google android SDK源码(1)
  10. Android(安卓)源码下编译APK