Linux/Android——Input系统之InputMapper 处理 (八)

前文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<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& 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<InputListenerInterface>& 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<InputListenerInterface>& listener) const {
    listener->notifyMotion(this);
}

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

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

时间: 2024-10-13 11:00:09

Linux/Android——Input系统之InputMapper 处理 (八)的相关文章

Linux/Android——Input系统之InputReader (七)

在前文Linux/Android--Input系统之frameworks层InputManagerService (六)  这里介绍了android层input服务的启动,其中启动了一个读取来自底层event事件的线程. 而在Linux/Android--input系统之 kernel层 与 frameworks层交互 (五)有分析到是通过一个event%d的设备文件交互的,也就是说android层是通过读取event%d来获取event的,这个工作就是InputReader 撰写不易,转载需注

Linux/Android——Input系统之frameworks层InputManagerService (六)

上一篇Linux/Android--input系统之 kernel层 与 frameworks层交互 (五)中有介绍kernel层一下以及与android这边frameworks层之间的联系,算是打通android 应用层与 kernel驱动层,对整个input系统的学习是至关重要的,其中frameworks层只是简单记录了几个接入点,这里开始分析frameworks层的细节部分. 撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/

Linux/Android——input子系统核心

之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备, 常用的输入设备也就是鼠标,键盘,触摸屏. 稍微细分一点整个输入体系,就是 硬件驱动层,input核心中转层,事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分别提供接口. 之前有分析usbtouchscreen的驱动,也就是硬件驱动部分,这里简单记录一下input核心中转处理

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

本文转载自:http://blog.csdn.net/jscese/article/details/42123673 之前的博客有涉及到linux的input子系统,这里学习记录一下input模块. input子系统,作为管理输入设备与系统进行交互的中枢,任何的输入设备驱动都要通过input向内核注册其设备, 常用的输入设备也就是鼠标,键盘,触摸屏. 稍微细分一点整个输入体系,就是 硬件驱动层,input核心中转层,事件处理层.层次之间传递都以event事件的形式,这其中input连接上下层,分

Linux/Android——input_handler之evdev

在前文Linux/Android--input子系统核心中概括了总体的结构,以及介绍了input核心的职责,其中有说道注册input设备时会去匹配已有的事件处理器handler, 而这个handler也是存放在一个链表里面的,这里介绍下input子系统中的事件处理input_handler机制. 撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42238377#t6 evdev: /kernel/drivers/input下众多事

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

本文转载自: 在前文Linux/Android——input子系统核心 (三)中概括了总体的结构,以及介绍了input核心的职责,其中有说道注册input设备时会去匹配已有的事件处理器handler, 而这个handler也是存放在一个链表里面的,这里介绍下input子系统中的事件处理input_handler机制. 撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42238377#t6 evdev: /kernel/driver

Linux input系统数据上报流程【转】

转自:https://segmentfault.com/a/1190000017255939 作为鸡生蛋系列文章,这里主要关注Linux input系统,主要为触摸事件上报流程. 读该文章最好有对linux驱动的入门知识.其实当你自己去分析了input系统后,再分析别的就相对很轻松了,linux里好多套路都差不多的. 本文例子以ft6236.c驱动为例, 当然你也可以用goodix或者别的触摸来分析.但是分析基于的内核版本用4.19.6(我写这篇文档时最新稳定版)(https://git.ker

iConvert Icons 图标转换生成利器,支持Windows, Mac OS X, Linux, iOS,和Android等系统

这是一款在线图标转换工具,生成的图标支持Windows, Mac OS X, Linux, iOS, 和 Android等主流系统. 可以上传图标文件转化成另一个平台下的图标文件,例如将windows系统下的icon图标格式转换成mac os下的icns图标格式,也可以通过上传图片从而生成你指定平台下的图标格式文件.例如上传png文件转换成windows系统下的icon图标文件. 官网在线应用地址:iConvert Icons 其也有app可供下载,但要付费. 原创文章,转载请注明: 转载自 h

热烈庆祝华清远见2014嵌入式系统(Linux&amp;Android)开发就业培训课程全面升级

近日,华清远见公开宣布:2014嵌入式系统 (Linux&Android)开发就业培训课程再次升级!据悉,华清远见如今已经持续10年,一直保持课程每年2次的更新的频率.华清远见的每 次课程更新都能够带给行业一些新的思路和方向,这次也不例外.通过知情人,我们了解到华清远见此次针对嵌入式培训和Anrdoid培训两个方向均有重大变 革. 首先,华清远见嵌入式系统 (Linux&Android)开发就业培训课程升级后主课程中全面采用自主研发的Cortex-A9 四核ARM硬件平台.这也是目前在嵌入