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,一经查实,立即删除!

相关文章

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

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

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

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

Git-远程操作

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

对于鸿蒙的一点见解

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

Linux内存管理slub分配器

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

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

逆向知识第十讲,循环在汇编中的表现形式,以及代码还原 一丶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; } 高级代码很简单,只是一个简单…

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

如果技术圈是一个江湖&#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;判断队列满的条…

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

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

【干货】同步与互斥的失败例子

韦东山老师最新录制的驱动大全之<<同步与互斥>>收费视频已经在淘宝上架销售 &#xff0c;一共7节&#xff0c;良心价29元&#xff0c;同时已经同步到CSDN , 51CTO , 电子发烧友&#xff0c;腾讯课堂等平台。本文是其中一节《同步与互斥的失败例子》视频配套文档&am…

TCP三次握手

以下是我做的实验 &#xff0c;180.97.33.108 是百度 以下是我自己画的图 转载于:https://www.cnblogs.com/heben/p/7879439.html

Linux中断子系统-通用框架处理

背景Kernel版本&#xff1a;4.14ARM64处理器&#xff0c;Contex-A53&#xff0c;双核使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio1. 概述《Linux中断子系统&#xff08;一&#xff09;-中断控制器及驱动分析》讲到了底层硬件GIC驱动&#xff0c;以及Arch-Specif…

接口测试工具-fiddler的运用

本篇主要介绍一下fiddler的基本运用&#xff0c;包括查看接口请求方式&#xff0c;状态响应码&#xff0c;如何进行接口测试等 一&#xff0e;Fiddler的优点 独立的可以直接抓http请求小巧、功能完善快捷、启动就行代理方便二&#xff0e;什么是Fiddler Fiddler是一个http协议调…

微电子科学与工程要学计算机吗,微电子科学与工程专业就业前景如何 有前途吗...

微电子科学与工程专业就业前景如何&#xff1f;有前途吗&#xff1f;下面小编为大家整理了相关内容&#xff0c;以供参考&#xff0c;一起来看看吧&#xff01;微电子科学与工程专业就业前景微电子科学与工程专业近年来也逐渐热火起来了&#xff0c;竞争力也很大。微电子专业一…

我的丈母娘

2020年9月17日12点46分&#xff0c;刚进入新居我终于还是要写这篇文章了&#xff0c;想了很久&#xff0c;我觉得写一篇文章来记录下我的丈母娘。前段时间&#xff0c;小云妈妈骑车不小心把鼻子给摔破了&#xff0c;很严重&#xff0c;二哥马上回家带老人到医院检查并做了手术。…

OpenGL程序运行提示“glut32.dll丢失问题”

调试环境&#xff1a; Win10 (x64) &#xff0c;VS2015 解决方案 &#xff08;1&#xff09;将gult32.dll&#xff0c;glut.dll复制到C:\WINDOWS\SysWOW64 (如果是32位操作系统&#xff0c;则是WINDOWS\system32这个文件下) &#xff08;2&#xff09;将GL文件夹的路径添加到vs…

华为突然宣布,对物联网下手了!

5G时代到来物联网技术的应用离我们越来越近智慧交通、智能家庭、智慧园区越来越多的融入到我们的生活当中但国内物联网人才短缺每年人才缺口达百万之多作为5G技术的先锋华为云特别推出【IoT物联网开发全栈成长计划】三大阶段&#xff0c;从学习到实践全流程提升物联网开发技能还…

Linux内核品读 /基础组件/ 模块机制快速入门

哈喽&#xff0c;我是杰克吴&#xff0c;继续记录我的学习心得。一、关于兴趣的几点思考1. 享受不是兴趣&#xff0c;愿意付出才是&#xff1a;兴趣很容易跟享受混淆。享受是被动的&#xff0c;无需付出&#xff1b;而兴趣则要求你甘愿为了这件事情付出努力。2.任何事情&#x…

台式计算机时间不准,每天开机电脑时间都不正确怎么办?试试这个办法!

原标题&#xff1a;每天开机电脑时间都不正确怎么办&#xff1f;试试这个办法&#xff01;上面电脑运用时间长了&#xff0c;经常会出现开机提示时间不正确&#xff0c;在系统上设置好时间后&#xff0c;第二天开机电脑时间还不正确&#xff0c;是什么原因呢&#xff1f;无论是…

c语言从1打印到100再打印到1该如何编写?

我觉得这是一个送分题&#xff0c;奈何知乎人才太多了&#xff0c;给出了各种古怪的写法&#xff0c;如果是做项目的话&#xff0c;我比骄建议一些正常的写法&#xff0c;就是大家都能看得懂的&#xff0c;不要搞什么花里胡哨&#xff0c;不过你要是交流的话&#xff0c;既然是…