概论
Android系统中,大体上分为三个层次kernel、framework、app层。对于kernel层,我们主要关心的是驱动,驱动层上报的事件都是原始数据。这些原始数据通过相应的机制上传到framework层的frameworks\base\service\input文件夹下的EventHub文件中对设备进行扫描区分具体的设备,并交由InputReader.cpp进行对数据的读取和分类。到达MotionEvent或者KeyEvent进行处理。此处这样说明总感觉到奇怪。
(2012-5-14 update)
在android中我们采用了一种从下而上,又从上而下的过程。在这个过程中我们首先是通过对输入设备的操作,从而使得硬件上报数据,而运行在系统中的线程等待接收数据,从而形成一种服务的关系。而从上而下的过程就是一种管理的过程,在这个过程中,我们上报的事件会得到合理的处理。
实际在代码中WindowManagerService中对InputManager进行了初始化,并且调用了start函数进行了启动。
此时大家一定想找到InputManager问个究竟,但是定睛一看,赫然显示两个InputManager。这可叫人如何是好?
本人猜想,应该此处的调用应该是InputManager.java。因为通常的调用都是从Java开始的。可能此处说法不严谨,但是鄙人认为科学都是“大胆假设、小心验证”。当然就从程序阅读本身也能找到根据。
因为此处的构造函数是有参数的。java中有而cpp中没有。(2012年5月7日修订)此处我们往下看的时候,发现在C++里面有函数的重载,而重载的构造函数中就有带有参数的构造函数。那到底此处我们是调用的哪个构造函数呢?当我们开始了解java和其他编程语言的相互调用之后我们发现在Android中我们都会通过JNI机制将本地的函数通过函数指针的形式提供给JAVA层进行调用。所以在命名上一般都以native开头。这样看来我们似乎对这一问题有了更深入的理解。
接着往下走发现在java中有回调函数和nativeInit,相信大家也是对这个函数比较感兴趣。但是此处还是要简单的说明下此回调函数。该函数则会利用windowManagerService,调用windowManagerService内部的其他方法。我们接着往下走,在nativeInit函数中将会创建一个此处会创建一个EventHub对象,以及InputManager对象。InputManager对象创建InputReaderThread以及InputDispatcherThread线程。在InputManager的构造函数中初始化了EventHub对象,通过传递参数给InptReader的构造函数。此处调用InputListener对事件进行监听,并且将消息放到消息队列中。自此WindowManagerService中对InputManager的初始化过程完成。
我们在通过EventHub获取数据之后,在inputreader函数中对原始的数据进行cook处理,处理之后形成应用程序能够识别的数据。这时候通过copyfrom函数将数据放到input中。最终通过inputlistener的flush函数进行监听,此过程就是调用notifyMotionevent函数此函数即通过inputdiapatcher进行分发。在数据分发的过程中,是通过flag对数据要进行分发还是拦截进行判断,并进行相应的处理。