参考:http://blog.csdn.net/u010312937/article/details/53285286

   https://www.jianshu.com/p/7fca94b330ea

 注意:关于下面的一些时序图,如果看不清,可以使用下载后再看,源码我已经放在GitHub上,工具为bouml,

GitHub地址为:https://github.com/maogefff/Other/tree/master

也可以使用我将时序图转化为PNG图片以后的,GitHub地址为:https://github.com/maogefff/Other/tree/inputSystem

1. 框架

InputManagerService(IMS)

Linux内核,接受输入设备的中断,并将原始事件的数据写入设备节点中,设备节点作为内核与IMS的桥梁,将原始事件的数据暴露给用户空间,以便IMS可以从中读取事件

InputManagerService一个android系统服务,分为Java层和Native层两部分,java层负责与WMS通信,而Native层则是InputReader和InputDispatcher两个输入系统关键组件的运行容器

EventHub,直接访问所有的设备节点,通过一个名为getEvents()的函数将所有输入系统相关的待处理的底层事件返回给使用者,包括原始输入事件,设备节点的增删等

InputReader,是IMS中的关键组件之一,它运行一个独立的线程中,负责管理输入设备的列表和配置,以及进行输入事件的加工处理,它通过其线程循环不断地通过getEvents()函数从EventHub中将事件取出并进行处理,对于设备节点的增删事件,它会更新输入设备列表与配置,对于原始输入事件,InputReader对其进行翻译,组装,封装为包含更多信息,更多可读性的输入事件,然后交给InputDispatcher进行派发

InputReaderPolicy,为InputReader的事件加工处理提供一些策略配置,例如键盘布局信息等。

InputDispatcher,是IMS中的另一个关键组件,运行于一个独立的线程中,InputDispatcher中保管来自WMS的所有窗口的信息,收到InputReader的输入事件后,会在其保管的窗口中寻找合适的窗口,并将事件派发给此窗口

InputDispatcherPolicy,为InputDispatcher的派发过程提供策略控制,例如HOME键被InputDispatcherPolicy截取到PhoneWindowManager中处理,并阻止窗口收到HOME键按下的事件

WMS,并不是输入系统的一员,新建窗口时,WMS为新窗口和IMS创建了事件传递所用的通道,会将窗口的可点击区域,焦点窗口等信息实时更新到IMS的InputDispatcher中,使得InputDispatcher可以正确将事件派发到指定窗口

ViewRootImpl,对某些窗口,如壁纸窗口,SurfaceView的窗口来说,窗口就是输入事件派发的终点,而对其他的如Activity,对话框等使用了Android控件系统的窗口来说,输入事件的终点是控件

运行流程

简单来说,内核将原始事件写入到设备节点中,InputReader不断地通过EventHub将原始事件取出来并翻译加工成Android输入事件,然后交给InputDispatcher。InputDispatcher根据WMS提供的窗口信息将事件交给合适的窗口。窗口的ViewRootImpl对象再沿着控件树将事件派发给感兴趣的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作。所有这些参与者以IMS为核心,构建了Android庞大而复杂的输入体系。

2. 阅读代码后的总结

2.1 启动创建流程

图2.1非常重要;就是Android层输入子系统的创建流程,看不清可以github上下载下来看,黄色为JAVA代码,红色为CPP代码,蓝色为CPP代码所在文件

大致思路:

SystemServer创建整个输入子系统InputManagerService类用来管理整个输入子系统    (JAVA层)

InputManagerService调用构造函数然后调用nativeInit(调用到C++层)创建本地管理者NativeInputManager,然后创建各种累

下面有三个重要的功能类(这三个功能详看第一节)

EventHub:    实例化对象为eventHub

InputReader:   实例化对象为mReader

InputDispatcher:实例化对象为mDispatcher

还有三个重要的类:

InputManager:       实例化对象为minputManager     ;主要作用为管理下面两个线程,mReaderThread和mDispathcerThread

InputReaderThread:     实例化对象为mReaderThread    ;为一个线程的对象,主要作用为管理mReader

InputDispatcherThread:  实例化对象为mDispathcerThread ;为一个线程的对象,主要作用为管理mDispatcher

图2.1 创建输入系统时序图

图2.2 类之间的包含关系

2.2 InputReaderThread和EventHub的流程

(一). InputReaderThread流程:

InputReader如下图2.3所示,主要负责三个方面的工作:

1. 获得事件(事件是通过EventHub获取,包括:1. 设备节点的增删事件; 2. 原始输入事件

2. 对事件进行简单的处理(1. 对于设备节点的增删事件(更新设备列表和配置); 2. 原始输入事件(进行翻译和组装)

3. 将处理后的事件分发给dispatch

(二). EventHub流程:

EventHub如2.3所示,主要负责检测设备节点增删事件和原始输入事件

通过inotify检测/dev/input文件夹是否有节点增删,通过epoll分别检测/dev/input/xxx里面的内容是否有修改

1. 通过epoll_wait等待获取事件(无事件等待)

2. 获取增删事件后

3. 获取原始输入事件后

下面是伪代码:

getEvents(RawEvent* buffer)
{
//检测目录是否有增删
fd1 = inotify.init("/dev/input"); //打开具体设备节点
fd2 = open("/dev/input/event0");
fd3 = open("/dev/input/event1"); //同时检测文件和文件夹
int pollResult = epoll_wait(fd1, fd2, fd3); switch(){
case 增加了一个设备节点:
buffer.type = DEVICE_ADDED;
fd4 = open("dev/input/xxx");
epoll_wait(fd1, fd2, fd3, fd4); //在epoll_wait里再增加一个fd4
break; case 减少了一个设备节点:
buffer.type = DEVICE_REMOVE;
epoll_wait(fd1, fd2, fd3); //在epoll_wait里再删除掉fd4
break; case 文件内容修改了:
buffer.xxx = xxx; //构造RawEvent
break;
}
}

黄色代码类名,蓝色代表所在文件(注意:时序图在EventHub.cpp当中有点问题,loop不是包含第三个,而是包含整个)

图2.3 readThread时序图 

3. InputManagerService(IMS)流程分析

3.1 启动流程:

frameworks/base/services/java/com/android/server/SystemServer.java

    public static void main(String[] args) {
new SystemServer().run();
}
...
private void run() {
    ...
     // Start services.
try {
startBootstrapServices();
startCoreServices();
startOtherServices(); //其他服务里面
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
     ...
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
    private void startOtherServices() {
...
NsdService serviceDiscovery= null;
WindowManagerService wm = null; //窗口管理服务
...
InputManagerService inputManager = null; //输入管理服务
... Slog.i(TAG, "Input Manager");
//创建输入系统
inputManager = new InputManagerService(context); Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
//将输入系统加入系统服务当中,以便其他人可以方便的访问(包括应用程序)
ServiceManager.addService(Context.INPUT_SERVICE, inputManager); mActivityManagerService.setWindowManager(wm); //设置输入系统的回调函数:设置向WMS发起回调
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
//启动输入系统服务
inputManager.start();
...
}

i.mx android6 输入子系统分析(未完)的更多相关文章

  1. 7.Linux 输入子系统分析

    为什么要引入输入子系统? 在前面我们写了一些简单的字符设备的驱动程序,我们是怎么样打开一个设备并操作的呢? 一般都是在执行应用程序时,open一个特定的设备文件,如:/dev/buttons .... ...

  2. 12.Linux之输入子系统分析(详解)

    版权声明:本文为博主原创文章,转载请标注出处:   在此节之前,我们学的都是简单的字符驱动,涉及的内容有字符驱动的框架.自动创建设备节点.linux中断.poll机制.异步通知.同步互斥/非阻塞.定时 ...

  3. linux input输入子系统分析《四》:input子系统整体流程全面分析

    1      input输入子系统整体流程 本节分析input子系统在内核中的实现,包括输入子系统(Input Core),事件处理层(Event Handler)和设备驱动层.由于上节代码讲解了设备 ...

  4. linux内核输入子系统分析

    1.为何引入input system? 以前我们写一些输入设备(键盘.鼠标等)的驱动都是采用字符设备.混杂设备处理的.问题由此而来,Linux开源社区的大神们看到了这大量输入设备如此分散不堪,有木有可 ...

  5. SpaceSyntax【空间句法】之DepthMapX学习:第四篇 凸多边形图分析[未完]

    这一篇正式讲解分析类型中的第一个,凸多边形分析,流程图参照上一篇的. 博客园/B站/知乎/CSDN @秋意正寒(我觉得这一篇肯定很多盗图的,那么我在版头加个本篇地址吧) https://www.cnb ...

  6. Universal-Image-Loader(UIL)使用方法&流程图&源码分析 ----- 未完

    GitHub源码: Android-Universal-Image-Loader Features Multithread image loading (async or sync) 多线程加载(同步 ...

  7. SQL注入蠕虫分析//未完待续

    蠕虫代码: DECLARE @S VARCHAR(4000);SET @S=CAST(0x4445434C415245204054205641524348415228323535292C4043205 ...

  8. Linux输入子系统 转载

    NQian 记录成长~ 首页 新随笔 联系 订阅 管理 随笔 - 305  文章 - 0  评论 - 254 12.Linux之输入子系统分析(详解)   在此节之前,我们学的都是简单的字符驱动,涉及 ...

  9. Linux输入子系统框架分析(1)

    在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...

随机推荐

  1. 在jquery中怎么使用css类名和id来获取元素?

    在jquery中,你可以很容易的使用CSS类名和id类获取元素. 例如: 1.ID:#id $('#idA')——选择id为idA的所有元素,不管元素的标签名如何. $('div#idA')——选择i ...

  2. 解决“找不到请求的 .Net Framework Data Provider。可能没有安装.”错误

    问题: 这几天在装.NET 的开发环境,在装好VS2013和Oracle 11g之后,做了一个测试项目,运行调试没问题 但是涉及到数据库相关操作,如新建数据集.连接数据库等在调试的时候则会出现如下错误 ...

  3. 在VC++中执行VBS代码

    此代码来自https://blog.csdn.net/zhu2695/article/details/13770671 作者: zhu2695   时间:2013年10月31日 13:08:41 #i ...

  4. [uwp]MVVM模式实战之必应壁纸查看器

    最近学习MVVM,至于什么是MVVM我也在这儿不多说了,一是关于它的解释解释网上非常多,二是我怕自己讲不清,误导自己没关系,误导别人就不好了.. 好了,废话结束,看是实战...... 这个必应壁纸的d ...

  5. RabbitMq初探——消息持久化

    消息持久化 前言 通过上一节,我们知道,有消息确认机制,保证了当消费者进程挂掉后,消息的不丢失. 但是如果rabbitmq挂掉呢?它的队列和消息都会丢失的.为了保证消息在rabbitmq挂掉重启后不丢 ...

  6. 自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 (转载)

    自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本   转自:https://www.cnblogs.com/ailiailan/p/8304989.html 作为测试, ...

  7. Syncthing源码解析 - 启动过程

    我相信很多朋友会认为启动就是双击一下Syncthing程序图标,随后就启动完毕了!如果这样认为,对,也不对!对,是因为的确是这样操作,启动了Syncthing:不对是因为在调试Syncthing启动过 ...

  8. Delphi XE2 新增 System.Zip 单元,压缩和解压缩文件

    Delphi XE2 新增 System.Zip 单元, 可用一句话压缩整个文件夹了 单元内主要就是 TZipFile 类, 最方便使用的是它的类方法: TZipFile.ExtractZipFile ...

  9. java学习笔记—Servlet技术(11)

    如果大家要开发一个动态的网站,那么就必须要学习一种动态的网页开发技术.那么在SUN提供的JavaEE中主要包含两种开发动态网页的技术:Servlet和JSP技术. Servlet技术简介 Servle ...

  10. 利用django form 模块处理post请求

    在django框架中,利用 form 模块处理post请求提交的数据,可以大大提高开发效率,减小代码冗余度,提高性能 models.py 中: from django.db import models ...