参考: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. jenkins任务构建失败重试插件Naginator Plugin

    jenkins任务失败重新构建插件Naginator Plugin jenkins任务经常会因为一些偶然因素失败,这时重新构建一次就肯能成功:jenkins的Naginator Plugin插件可以重 ...

  2. Centos 安装 erlang 环境

    系统 Centos 6.5 64位 Erlang 18.3.4 安装依赖组件 yum install -y gcc gcc-g++ unixODBC unixODBC-devel wxBase wxG ...

  3. (zxing.net)一维码Code 128的简介、实现与解码

    一.简介 一维码Code 128:1981年推出,是一种长度可变.连续性的字母数字条码.与其他一维条码比较起来,相对较为复杂,支持的字元也相对较多,又有不同的编码方式可供交互运用,因此其应用弹性也较大 ...

  4. .net图表之ECharts随笔08-bar柱状图

    之前一直都是跟着修改demo,感觉用得很吃力,现在结合上配置手册就好很多了,其实说到底就是参数的配置,所以配置手册尤为重要. 当然,这其中还是很多坑,希望可以找到对应的解决方案吧!!! 1. tool ...

  5. mysql 判断表字段或索引是否存在 - 举一反三

    判断字段是否存在: DROP PROCEDURE IF EXISTS schema_change; DELIMITER // CREATE PROCEDURE schema_change() BEGI ...

  6. scrapy实战2,使用内置的xpath,re和css提取值

      以伯乐在线文章为爬取目标blog.jobbole.com,发现在"最新文章"选项中可看到所有文章   一般来说,可以用scrapy中自带的xpath或者css来提取数据,定义在 ...

  7. 使用java执行ffmpeg命令进行推流操作

    视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播放该文件.项目中用制作的player.swf播放器. 多媒体视频处理工具FFmpe ...

  8. Rabbitmq 消息对列 生产者与消费者的具体实现 springboot

    RabbitMQ 基本介绍 RabbitMQ的设计理念是.只要有接收消息的队列. 邮件就会存放到队列里. 直到订阅人取走. . 如果没有可以接收这个消息的消息队列. 默认是抛弃这个消息的.. 我实现的 ...

  9. 本机号码认证黑科技:极光(JG)开发者服务推出“极光认证”新产品

    近日,中国领先的大数据服务商极光(JG)推出全新产品--极光认证JVerification.极光认证是极光针对APP用户注册登陆,二次安全验证等身份验证场景打造的一款本机号码认证SDK,验证用户提供的 ...

  10. Go语言容器

    Map 是一种无序的键值对的集合.Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值. Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它.不过,Map 是无 ...