Android Input 子系统初探

Android系统基于Linux内核实现,内核作为整个操作系统的核心,对下,它负责整个硬件的驱动、实现对硬件器件的控制管理;对上,它提供各种系统所需的核心功能。Android系统支持的输入设备较多,如按键、触摸屏、手柄等,面对种类繁杂的输入设备,内核通过抽象化的方式来使得各输入设备的的核心处理流程统一化,细节处理流程差异化(通过不同类型的回调实现),这就是Input子系统所要完成的内容,总结来说,它在内核中主要作用为:

  • 规范化Input Device的定义方式及其数据的上报格式;

  • 规范化Input Handler的定义方式及其需要实现的回调;

  • 为Input Device和Input Handler提供核心服务;

  • 提供标准化用户空间接口;

图1 Input事件处理整体框图

整体的Input事件处理框图如图1所示,本文主要围绕这张图来详述Input子系统的各个方面,如定义、初始化、注册匹配、事件传递、与用户空间的交互等。介于本人理解有限,如有叙述不当的地方,还请谅解指出。

一.Input子系统相关定义

在前序内容中,我们提前用到了Input Device、Input Handler等名词,但还没有进行相关的解释说明。本节的内容旨在了解Input子系统中几个重要的结构体定义,以便于Input子系统的后续介绍。

1. Input_dev

struct input_dev用来抽象所有的输入设备,由于不同的输入设备上报的事件或形式存在差异,抽象的input_dev必然需要包含差异的内容,形成一种x+(y1、y2、y3..)的方式(其中,x为所有输入设备共有的成员,y1/y2/y3为输入设备差异化成员),所以在实际的特定输入设备驱动开发工作中,只需要填充部分成员即可完成input_dev的定义。详细的成员定义说明如下:

2. Input_handler

struct input_handler用于抽象事件处理,不同的输入设备对应的事件处理方式会存在差异,linux内核抽象该结构体保证input事件的处理流程一致,具体的实现部分通过input_handler的函数指针回调完成,主要包括匹配、建立连接、事件传递/过滤等,具体的成员说明如下:

3. Input_handle

在抽象input_dev和input_handler之后,我们知道一个input_dev上报的事件可以被多个input_handler接收处理,一个input_handler也可以处理多个input_dev上报的事件,这样多个input_dev和多个input_handler之间可能会形成交织的网状(如下图2)。在这种情况下,需要一个桥梁来搭建两者之间的联系,两边的函数调用都可以通过这个“中介”进行,input_handle就是这个桥梁。

图2 device与handler示意图

Input_handle的定义比较简单,各成员说明如下:

二.Input子系统相关流程

主要流程包括input core初始化、input设备注册、input_handler注册、input设备与input_handler匹配、input事件传递。

1. input core初始化

Input core通过sybsys_initcall注册设定启动等级,保证其初始化会早于input设备和input_handler的注册(module_init方式注册),在初始化过程中主要完成:

1)input类注册;

2)Proc文件创建,主要用于input_handler和devices信息查看;

3)注册字符设备,主设备号为13;

2. input_dev注册

一般而言,Input设备驱动需要完成设备的控制和响应上报,其中响应上报是通过注册的input_dev来完成,所以input_dev的注册需要在input设备驱动的初始化过程中调用input_register_device完成,input_register_device执行的过程说明如下:

3. input_handler注册

Input handler的注册相对于input设备的注册更为简单,在填充struct input_handler后,直接调用input_register_handler完成handler的注册,input_register_handler的处理流程如下:

4. input_handler与input_dev匹配

Input_handler与input_dev的注册最终都会调用input_attach_handler完成自己与“相亲对象”的配对,配对完成后input_dev、input_handler、input_handle之间的关系如图3所示,设备驱动和事件处理层驱动都可以通过自身访问到input_handle,然后通过input_handle访问到自己的“对象”,具体的匹配代码说明如下:

图3 input_handle与owner关系图

当handler中match回调没有实现时只用根据input_dev中的id与input_handler中id_table包含的id进行匹配,如evdev_handler匹配所有Input设备,故所有的input设备都可以通过dev/input/event*路径获取原始上报数据。

在匹配成功后会调用connect回调,举例evdev_handler中的connect内容如下:

5. Input事件传递

不同的input设备上报的input事件的格式不同,比如触摸屏上报input事件时一般需要上报手指的id、x坐标、y坐标等信息(如图4为B协议报点格式, A协议报点无需上报id,会在inputReader中重新分配)。

图4 触摸屏报点事件格式

每一个事件上报都是通过input_event接口来完成,在判定事件类型是否支持后,主要是调用input_handle_event来完成:

该接口中,首先根据type、code判定该事件的disposition,当disposition为INPUT_PASS_TO_DEVICE时,将该事件传递给input_dev设备自身的event函数处理;当disposition为INPUT_PASS_TO_HANDLERS时,即将该事件传递给事件处理层处理,此处一般是将所有的事件存储在dev的vals数组中(此处,在disposition为INPUT_SLOT时表明上次处理的点与本次不同,故多添加一个ABS_MT_SLOT事件);当disposition为INPUT_FLUSH时或者传递的事件达到数组的极限时才将事件传递给事件处理层处理( input_sync时,disposition才能取得INPUT_FLUSH这个值)。

input_get_disposition函数是将根据type和code判定事件的disposition,此处只关心EV_SYN、EV_KEY、EV_ABS事件。EV_KEY事件中当设置了按键自动重发时的value值为2,!!test_bit(code, dev->key) != !!value语句中都进行了两次取反操作是为了避免出现0、1之外的数据,如果本次上报的按键事件与上次不同才会进行上报给事件处理层(dev->key保存了最近按键事件的所有状态),否则不予处理。

在收到sync事件或者event buffer size接近最大值时开始同步事件,此时传递的为一包事件,input_pass_values接口主要是寻找input_dev设备对应的handle处理存储的数据,另外设置的输入设备支持EV_REP事件,则会在此处设置定时器自动重发按键事件(按键值为2)。

所有的input设备都会和evdev_handler匹配,此处假设匹配的handler为evdev_handler,则events指向的函数为evdev_events:

evdev_pass_values只是将传过来的所有事件存储在client->buffer中;kill_fasync函数用于发送通知事件,告诉上层client->buffer中有数据可以读了。

6. Input事件传递给用户空间

当应用层或框架层调用read函数读取/dev/input/event*文件时,会调用evdev_read返回数据,其中event_fetch_next_event是判断client->buffer这个循环缓冲区中的头尾指针是否相等(相等时buffer中没有数据),不相等时取出一个input_event类型的事件放入到event中;input_event_to_user函数是将此事件copy到应用层,input_event_size函数是用来获取一个input_event事件的大小,循环复制client->buffer中的事件到应用层的buffer中。

上层谁会来打开文件读这些事件?一种是getevent工具,另外一种是android框架层的inputflinger服务,其主要会创建InputReader和InputDispatcher两个线程。InputReader负责与底层的事件打交道,其先通过eventHub读取所有的事件, 然后通过设备属性或事件特征找到对应的mapper处理将底层事件转换为android设计的事件类型;InputDispatcher负责与窗口打交道,将收到的事件派发给对应注册的窗口。

参考文献

1. https://www.cnblogs.com/lifexy/p/7542989.html

2. https://blog.csdn.net/qq_39937242/article/details/82631165

推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ruby零碎笔记

Ruby零碎笔记 飞机上阅读pdf的笔记,因为不联网,内容不多而且比较零散,以tips的形式记录 tips 查看当前作用域的变量puts local_variables ruby中方法传递参数时,括号是可选的脚本开始运行时,main对象会被自动创建&…

网管日志-06.07.25

昨天晚上回家的时候已经是23:30左右了,尽管电信的工程师已经测试出了光信号衰减状况,也进行了相应的处理,最后达到了单芯光纤-11db的“理想”状态,可能用户也对这个值非常满意,我们也折腾到了大半夜。我是在地下网络机…

html5控制符置于底层,HTML5占位符在焦点上消失

Stefano J. Attardi写了一个不错的jQuery插件,只是这样。它比罗伯特的更稳定,并且当场得到焦点时,还会变淡到更浅的灰色。我修改他的插件读取占位符属性,而不是手动创建跨度。This fiddle具有完整代码:HTMLJS// Origin…

spring AspectJ的Execution表达式

Aspectj切入点语法定义 在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式 execution(* com.sample.service.impl..*.*(..)) execution()是最常用的切点函数,其语法如下所示…

计算机excl知识题,2019职称计算机考试Excel模拟题及答案(1.18)

【导语】2019年职称计算机考试备考正在进行中,为了方便考生及时有效的备考,那么,无忧考网为您精心整理了2019职称计算机考试Excel模拟题及答案(1.18),把握机会抓紧练习吧。如想获取更多职称计算机考试的模拟题及备考资料&#xff…

CPU中的程序是怎么运行起来的

总述最近一位朋友问我,开发的代码是怎么在芯片运行起来的,我就开始给他介绍代码的预编译、汇编、编译、链接然后到一般的文件属性,再到代码运行。但是大佬问了我一句,CPU到底是怎么执行到每一个逻辑的,就讲了哈CPU的架…

MspEmu W.I.P.

转载于:https://www.cnblogs.com/sesexxoo/archive/2006/07/29/6190717.html

Git-远程操作

远程分支:远程跟踪分支remote branch是对远程分支状态的引用,是不能移动的,它会根据远程分支变化以及网络通信自动移动。Git服务器包含了远程分支master,在My Computer中的remote branch就是远程跟踪分支,是对git服务器…

计算机语言学 自然语言处理程序,利用知网进行(计算机)自然语言处理

摘要:自然语言理解,特别是中文信息处理,一直是计算机界的难题.让计算机来理解和处理丰富的自然语言,极具挑战性.自然语言的计算机处理是一个多学科交叉研究领域.来自计算机科学,语言学,数学等不同学科的研究人员构成了目前这一领域的主要研究力量.自然语言处理就是研…

对于鸿蒙的一点见解

周五我在东莞出差,下班后看了开发者大会的视频回放,回到酒店,我跟邓总说,我们今天不要拍视频,也不要打王者了,你给我下鸿蒙的代码来看看,然后,那天晚上我们都没有上线王者&#xff0…

今天雨很大

早上就开始下雨了,一直到现在. 来公司发现翻译来了,一个星期前面试过的那个. 不知道做什么了,看来只能开始英文的B2B了.一直忙来忙去,突然早一天完成了工作,余下的一天不知道做什么. 昨天晚上在家里的机子练习时,多学会了一些东西,看来有必要多看一些别人的例子,…

Linux内存管理slub分配器

背景Kernel版本:4.14ARM64处理器,Contex-A53,双核使用工具:Source Insight 3.5, Visio1. 概述之前的文章分析的都是基于页面的内存分配,而小块内存的分配和管理是通过块分配器来实现的。目前内核中&#xf…

大学计算机科学不会编码,华中科技大学人员编号编码管理办法

第一条 为进一步推进学校管理的信息化、规范化和系统化,加强对我校教职工、学生等各类人员基本信息的统一管理,结合学校实际情况,制定本管理办法。第二条 凡在我校工作、学习的教职工、学生、短期聘用人员及其他人员,均拥有由10…

逆向知识第十讲,循环在汇编中的表现形式,以及代码还原

逆向知识第十讲,循环在汇编中的表现形式,以及代码还原 一丶do While在汇编中的表现形式 1.1高级代码: #include "stdafx.h"int main(int argc, char* argv[]) {int nSum 0;int i 0;do {nSum nSum i;} while (i <100);return 0; } 高级代码很简单,只是一个简单…

数据库基础系列之一:MySQL账户

1.mysql用户创建&#xff1a; shell> mysql --userroot mysql mysql> GRANT ALL PRIVILEGES ON *.* TO montylocalhost IDENTIFIED BY something WITH GRANT OPTION; mysql> GRANT ALL PRIVILEGES ON *.* TO monty"%" IDENTIFIED BY something WITH GRANT…

计量经济学实验报告计算机,计量经济学-实验报告.doc

.PAGE.资料.经济与政法学院计量经济学实验报告班级&#xff1a; 国贸1312姓名&#xff1a; 纪方方学号&#xff1a; 2013104208实验课程计量经济学实验名称OLS的估计和检验(受约束回归模型)实验目的和内容1&#xff0e;利用SPSS计算OLS估计量2&#xff0e;对模型估计结果进行检…

做技术知道了哪些事情代表自己成熟了?

如果技术圈是一个江湖&#xff0c;每个人初入江湖的时候都懵懵懂懂的&#xff0c;从懵懂到老练&#xff0c;从老练到老油条&#xff0c;这个是一个过程&#xff0c;过程中总是有一些比较有用的观点&#xff0c;这些观点&#xff0c;就表示你从小白上升到老白的过渡。这些观点&a…

数据结构复习笔记(2)

1&#xff0c; 若入栈的元素为n,则可得到的输出序列数量为 (2n)!/(n1)(n!)(n!)。2&#xff0c; 用两个长度相同的栈S1,S2构造一个队列。在S1中进行入队操作&#xff0c;S2中进行出队操作 &#xff0c;判断队列空的条件是&#xff0c;S1和S2同时为空&#xff0c;判断队列满的条…

html兼容webki,评IE10对HTML5的完美支持

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼近期Windows 8的消息充斥着整个网络。微软将IE10集成在系统中&#xff0c;并且宣称IE10会很好的支持HTML5。本文是对IE10支持HTML5的研究报告。预览&#xff1a;HTML5初探 在过去的几年里我们做了一系列测试来评估主要的移动平台对…

用于MCU,基于FreeRTOS的micro(轻量级)ROS

编辑整理&#xff1a;strongerHuang作者&#xff1a;Francesca Finocchiaro关注我的读者中应该有部分是做ROS相关的工作&#xff0c;今天就来分享一个基于FreeRTOS的micro&#xff08;微型&#xff09;ROS。一、关于ROSROS&#xff1a;Robot Operating System,&#xff0c;即机…