天天看点

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

<a href="http://www.jianshu.com/p/50fbec2baeb4">浮窗有哪些限制,如何越过用户授权实现浮窗功能?</a>

activity是如何接收到touch事件的?

前两个问题在前两篇文章中已经分析,在这篇文章中我们以第三个问题为切入点,简单分析一下窗口与用户输入的关系。

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

正常的思路是直接去寻找activity 的dispatchtouchevent方法,我们看看activity的dispatchtouchevent()方法的调用栈,在方法中加入thread.dumpstack()来查看调用栈。

输出:

一条粗略的线索:

viewrootimpl-deliverinputevent -&gt;view.dispatchpointerevent-&gt;phonewindow$decorview.dispatchtouchevent-&gt;mainactivity.dispatchtouchevent,读者可以根据这个线索去跟踪源码。我们这里先不深入其中细节,先来看看decorview 到 activity.dispatchtouchevent 是如何调用的?

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:
Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

再来看看decorview的 dispatchtouchevent方法:

decorview 是view的子类重写了dispatchtouchevent方法,在这个方法中调用 callback,这个callback是window的一个静态内部接口类,activity实现了这个接口,activity的dispatchtouchevent() 方法正是从callback继承而来。

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

思路同上:dump出根视图的dispatchtouchevent()方法调用栈:

添加到windowmanagerservice中管理。所以activity的dispatchtouchevent方法其实是view传递过来的。

我们可以猜测粗略线索是:touch事件-》硬件设备-》某个服务-》 viewrootimpl --》view。

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

我们先来看看viewrootimpl和view到底有啥关系?首先,看看windowmanager的addview方法,windowmanager是个接口,我们看其实现类windowmangerimpl的源码:

在来看看windowmanagerglobal的源码:

在这里创建了viewrootimpl对象,并且把传单下来的view通过setview方法设置到其中的变量,来看看setview的源码:

由此得到关系图:

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

通过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监听输入事件。

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

touchevent事件传递流程 :

Activity是如何接收到touch事件的(窗口与用户输入系统)Touch事件是如何分发到Activity上来的?Touch事件是如何分发到浮窗的根视图的?ViewRootImpl是个啥?用户输入与窗口参考资料:

<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>

上一篇: System V IPC

继续阅读