<a href="http://www.jianshu.com/p/50fbec2baeb4">浮窗有哪些限制,如何越过用户授权实现浮窗功能?</a>
activity是如何接收到touch事件的?
前两个问题在前两篇文章中已经分析,在这篇文章中我们以第三个问题为切入点,简单分析一下窗口与用户输入的关系。
正常的思路是直接去寻找activity 的dispatchtouchevent方法,我们看看activity的dispatchtouchevent()方法的调用栈,在方法中加入thread.dumpstack()来查看调用栈。
输出:
一条粗略的线索:
viewrootimpl-deliverinputevent ->view.dispatchpointerevent->phonewindow$decorview.dispatchtouchevent->mainactivity.dispatchtouchevent,读者可以根据这个线索去跟踪源码。我们这里先不深入其中细节,先来看看decorview 到 activity.dispatchtouchevent 是如何调用的?
再来看看decorview的 dispatchtouchevent方法:
decorview 是view的子类重写了dispatchtouchevent方法,在这个方法中调用 callback,这个callback是window的一个静态内部接口类,activity实现了这个接口,activity的dispatchtouchevent() 方法正是从callback继承而来。
思路同上:dump出根视图的dispatchtouchevent()方法调用栈:
添加到windowmanagerservice中管理。所以activity的dispatchtouchevent方法其实是view传递过来的。
我们可以猜测粗略线索是:touch事件-》硬件设备-》某个服务-》 viewrootimpl --》view。
我们先来看看viewrootimpl和view到底有啥关系?首先,看看windowmanager的addview方法,windowmanager是个接口,我们看其实现类windowmangerimpl的源码:
在来看看windowmanagerglobal的源码:
在这里创建了viewrootimpl对象,并且把传单下来的view通过setview方法设置到其中的变量,来看看setview的源码:
}
由此得到关系图:
通过windowmanagerimpl.addview,最终把view添加赋值到了viewrootimpl的变量mview。viewrootimpl是view(窗口)和windowmanagerservice协议的纽带
从mvc的角度来看的话:可以认为view是v,viewrootimpl是controller,windowmanagerservice是model。view的绘制、刷新都需要通过viewrootimpl与windowmanagerservice交互,另外view的输入事件(键盘、触摸)也是由viewrootimpl传递给view的,那么viewrootimpl是如何监听到用户输入事件的呢?
回忆下上文点到的windowinputeventreceiver,这是viewrootimpl的一个内部类,我们dump出来的dispatchtouchevent最初的地方就是源于这个类,再往下就是messagequeue、looper的信息。由此可以推断windowinputeventreceiver是viewrootimpl和底层某个服务进行ipc交互的关键,这个服务是什么服务呢?
这部分涉及到anddroid系统的两个重要的模块:图形窗口和用户输入,分别对应的服务是windowmanagerservice和inputmanagerservice。windowmanagerservice负责图形窗口(view)的绘制、刷新等事物、inputmanagerservice管理用户输入事件处理。
1、inputmanagerservice 管理者两个角色inputreader和inputdispatcher 。
2、inputreader负责从硬件(eventhub)读取输入信号,转化成为事件,传递给inputdispatcher。
3、inputdispatcher将inputreader传递过来的事件分发到对应的场景,例如将touch事件分发到viewrootimpl。
那么inputmanagerservice(inputdispatcher)是如何将touch事件传递到viewrootimpl(windowinputeventreceiver)的呢?
用户输入事件处理模型是“生产者-消费者“模型,生产者发生在系统进程中,消费者发生在用户进程中。传递过程由ipc交互,这里的通讯是采用的socket通讯,消费者需要向生产者”注册“通讯管道,registerinputchannel建立连接。在viewrootimpl的setview()方法中创建了windowinputeventreceiver,并通过windowmanagerservice向inputmanagerservice注册inputchannel监听输入事件。
touchevent事件传递流程 :
<a href="http://www.cnblogs.com/samchen2009/p/3367496.html">《android 的窗口管理系统》</a>
<a href="http://www.cnblogs.com/samchen2009/p/3368158.html">《android的用户输入处理》</a>
<a href="http://blog.csdn.net/singwhatiwanna/article/details/50775201">《android中motionevent的来源和viewrootimpl》</a>