《2022年android输入系统 .pdf》由会员分享,可在线阅读,更多相关《2022年android输入系统 .pdf(21页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、8.1 用户输入系统结构和移植内容Android 中,用户输入系统的结构相对简单,主要的输入硬件设备是键盘、触摸屏、轨迹球等。在 Android 的上层中, 可以通过获得这些设备产生的事件,并对设备的事件做出响应。在 Java 框架和应用程序层,通常使用运动事件获得触摸屏、轨迹球等设备的信息,用按键事件获得各种键盘的信息。Android 用户输入系统的基本层次结构如图8-1 所示。上页 下页8.1.1 用户输入系统的结构Android 用户输入系统的结构比较简单,自下而上包含了驱动程序、本地库处理部分、 Java类对输入事件的处理、对 Java程序的接口。 Android 用户输入系统的结构如
2、图8-2 所示。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 21 页 - - - - - - - - - 如图 8-2 所示,自下而上,Android 的用户输入系统分成几个部分:驱动程序:在 /dev/input 目录中,通常是Event 类型的驱动程序 EventHub:本地框架层的EventHub 是 libui 中的一部分,它实现了对驱动程序的控制,并从中获得信息 KeyLayout (按键布局)和KeyCharacterMap (按键字符映射)文件。同时,l
3、ibui 中有相应的代码对其操作。定义按键布局和按键字符映射需要运行时配置文件的支持,它们的后缀名分别为kl 和 kcm Java框架层的处理: 在 Java框架层具有KeyInputDevice 等类用于处理由EventHub 传送上来的信息, 通常信息由数据结构RawInputEvent 和 KeyEvent 来表示。通常情况下,对于按键事件,则直接使用KeyEvent来传送给应用程序层,对于触摸屏和轨迹球等事件,则由RawInputEvent 经过转换后,形成MotionEvent时间传送给应用程序层名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - -
4、 - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 21 页 - - - - - - - - - 在 Android 的应用程序层中,通过重新实现onTouchEvent 和 onTrackballEvent 等函数来接收运动事件(MotionEvent ),通过重新实现onKeyDown 和 onKeyUp 等函数来接收按键事件(KeyEvent )。这些类包含在 android.view 包中上页 下页8.1.2 移植的内容移植 Android 的用户输入系统,主要的工作分成以下两个部分:输入( input)驱动程序用户空间中动态配置的kl 和 kcm 文件
5、由于 Android 用户输入部分的 “ 硬件抽象层 ” 就是 libui 库中的 EventHub,这部分是系统标准的部分。因此,在实现特定硬件平台的Android 系统的时候,用户输入的硬件抽象层通常情况下不做改变。EventHub 使用 Linux 标准的 input 设备作为输入设备,其中又以实用Event 设备居多。 在这种情况下, 为了实现 Android 系统的输入,也必须使用Linux 标准 input 驱动程序作为标准的输入。由于标准化程度比较高,实现用户输入系统,在用户空间一般不需要更改代码。唯一的情况是使用不同的kl 和 kcm 文件,使用按键的布局和按键字符映射关系。上
6、页 下页8.2.1 input驱动程序Input 驱动程序是 Linux 输入设备的驱动程序,分成游戏杆(joystick)、鼠标( mouse和 mice)和事件设备(Event queue)3 种驱动程序。其中事件驱动程序是目前通用的驱动程序,可支持键盘、鼠标、触摸屏等多种输入设备。Input 驱动程序的主设备号是13,3 种驱动程序的设备号分配如下所示。 joystick 游戏杆: 031 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 21 页 - - - - -
7、 - - - - mouse 鼠标: 3262 mice 鼠标: 63 事件( Event)设备: 6495 实际上,每一种Input 设备占用 5 位,因此每种设备包含的个数是32 个。Event 设备在用户空间大多使用read、ioctl 、poll 等文件系统的接口进行操作,read 用于读取输入信息,ioctl用于获得和设置信息,poll 调用可以进行用户空间的阻塞,当内核有按键等中断时,通过在中断中唤醒poll的内核实现,这样在用户空间的poll 调用也可以返回。Event 设备在文件系统中的设备节点为:/dev/input/eventX 。主设备号为 13,次设备号递增生成,为 6
8、495,各个具体的设备在misc、touchscreen,keyboard 等目录中。Event 输入驱动的架构如图8-3 所示。输入设备驱动程序的头文件:include/linux/input.h 。输入设备驱动程序的核心和Event 部分代码分别是:drivers/input/input.c 和 drivers/input/ evdev.c 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 21 页 - - - - - - - - - input.h 中定义了 str
9、uct input_dev 结构,它表示Input 驱动程序的各种信息,对于Event 设备分为同步设备、键盘、相对设备(鼠标)、绝对设备(触摸屏)等。input_dev 中定义并归纳了各种设备的信息,例如按键、相对设备、绝对设备、杂项设备、LED 、声音设备,强制反馈设备、开关设备等。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 21 页 - - - - - - - - - 在具体的 Event 驱动程序的实现中,如果得到按键的事件,通常需要通过以下的接口向上进行通知
10、,这些内容也在 input.h 中定义如下所示:事实上,对不同设备内容的报告均是通过input_event() 函数来完成的,选择使用了不同参数而已。在手机系统中经常使用的键盘(keyboard)和小键盘( kaypad)属于按键设备EV_KEY ,轨迹球属于相对设备 EV_REL ,触摸屏属于绝对设备EV_ABS 。关于按键数值的定义的片断如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 21 页 - - - - - - - - - 可以使用 getevent
11、对 Event 设备进行调试,在Android 的模拟器环境中,使用getevent的情况如下所示:点击数字按键1,出现了上面的信息,0002 是按键的扫描码,00000001 和 00000000 分别是按下和抬起的附加信息。最前面的0001 实际上是输入设备的类型。使用 getevent可以最直接地获得按键的扫描码,对于Android 系统中用户输入设备的调试,可以从源头确定底层输入设备传递上来的信息。上页 下页8.2.2 用户空间的处理触摸屏和轨迹球上报的是坐标、按下、抬起等信息,信息量比较少。按键处理的过程稍微复杂,从驱动程序到 Android 的 Java层受到的信息,键表示方式经过
12、了两次转化,如图8-4 所示。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 21 页 - - - - - - - - - 键扫描码 Scancode是由 Linux 的 Input 驱动框架定义的整数类型。键扫描码Scancode经过一次转化后,形成按键的标签KeycodeLabel,是一个字符串的表示形式。按键的标签KeycodeLabel 经过转换后,再次形成整数型的按键码keycode。在 Android 应用程序层,主要使用按键码keycode 来区分。在本地框
13、架层libui 的头文件中KeycodeLabels.h,按键码为整数值的格式,其定义KeyCode(枚举值)如下所示:进而在定义了KeycodeLabels.h 中定义了从字符串到整数的映射关系,数组KEYCODES ,定义如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 21 页 - - - - - - - - - 数组 KEYCODES 表示的映射关系,左列的内容即表示按键标签KeyCodeLabel,右列的内容为按键码KeyCode (与 KeyCode
14、的数值对应)。 实际上,在按键信息第二次转化的时候就是将字符串类型KeyCodeLabel转化成整数的KeyCode。KeycodeLabel 的 Flags的定义如下所示:KeycodeLabel 表示按键的附属标识。提示: frameworks/base/core/Java/android/view/KeyEvent.Java 中定义了类android.view. KeyEvent 类,其中定义整数类型的数值与KeycodeLabels.h 中定义的KeyCode 枚举值是对应的。在本地框架层libui 的头文件中KeyCharacterMap.h,定义了按键的字符映射关系,KeyChar
15、acterMap 类的定义如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 21 页 - - - - - - - - - KeyCharacterMap 用于将按键的码映射为文本可识别的字符串(例如,显示的标签等)。KeyCharacterMap是一个辅助的功能:由于按键码只是一个与UI 无关整数, 通常用程序对其进行捕获处理,然而如果将按键事件转换为用户可见的内容,就需要经过这个层次的转换了。KeyCharacterMap 需要从本地层传送到Java层, JNI
16、 的代码路径如下所示:frameworks/base/core/jni/android_text_KeyCharacterMap.cpp KeyCharacterMap Java 框架层次的代码如下所示:frameworks/base/core/Java/android/view/KeyCharacterMap.Java android.view.KeyCharacterMap 类是 Android 平台的 API 可以在应用程序中使用这个类。android.text.method 中有各种 Linstener,可以之间监听KeyCharacterMap 相关的信息。DigitsKeyList
17、ener NumberKeyListener TextKeyListener。以上关于按键码和按键字符映射的内容是在代码中实现的内容,还需要配合动态的配置文件来使用。在实现 Android 系统的时候,有可能需要更改这两种文件。动态的配置文件包括: KL (Keycode Layout ):后缀名为kl 的配置文件名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共 21 页 - - - - - - - - - KCM (KeyCharacterMap):后缀名为kcm 的配
18、置文件Donut 及其之前配置文件的路径为:development/emulator/keymaps/ Eclair 及其之后配置文件的路径为:sdk/emulator/keymaps/ 这些配置文件经过系统生成后,将被放置在目标文件系统的/system/usr/keylayout/目录或者/system/usr/keychars/目录中。提示: kl 文件将被直接复职到目标文件系统中;由于尺寸较大,kcm 文件放置在目标文件系统中之前,需要经过压缩处理。KeyLayoutMap.cpp 负责解析处理kl 文件, KeyCharacterMap.cpp 负责解析 kcm 文件。上页 下页8.2
19、.3 移植需要注意的情况EventHub中基本的处理libui 库中 frameworks/base/libs/ui 中的 EventHub.cpp 文件是用户输入系统的中枢,主要的功能都是在这个文件中实现的。EventHub.cpp 中定义设备节点所在的路径,内容如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 21 页 - - - - - - - - - poll() 函数将会阻塞程序的运行,此时为等待状态,无开销,直到Input 设备的相应事件发生,事件发
20、生后poll() 将返回,然后通过read()函数读取 Input 设备发生的事件代码。注意,EventHub 默认情况可以在 /dev/input 之中扫描各个设备进行处理,通常情况下所有的输入设备均在这个目录中。实际上,系统中可能有一些input 设备可能不需要被Android 整个系统使用, 也就是说不需要经过EventHub的处理, 在这种情况下可以根据EventHub 中 open_device()函数的处理, 设置驱动程序中的一些标志,屏蔽一些设备。 open_device()中处理了键盘,轨迹球和触摸屏等几种设备,对其他设备可以略过。另外一个简单的方法就是将不需要EventHub
21、 处理的设备的设备节点不放置在/dev/input 之中。open_device()函数还将打开system/usr/keylayout/ 中的 kl 文件来处理,处理的过程如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 21 页 - - - - - - - - - 由此可见,默认情况下使用的就是qwerty.kl , 这里只是扫描各个后缀名为kl 的文件,然后交由 KeyLayoutMap去解析处理, KeyLayoutMap 是一个内部使用的类。2按键的增
22、加Android 已经定义了比较丰富、完整的标准按键。在一般情况下,不需要为Android 系统增加按键,只需要根据 kl 配置按键即可。在系统中有比较奇特按键的时候,需要更改Android 系统的框架层来更改按键。增加按键需要更改的文件较多,主要的文件如下所示。 frameworks/base/include/ui/KeycodeLabels.h :中的 KeyCode 枚举数值和KeycodeLabel 类型 Code 数组(以NULL 为结尾) frameworks/base/core/Java/android/view/KeyEvent.Java :定义整数值, 作为平台的API 供
23、Java应用程序使用frameworks/base/core/res/res/values/attrs.xml:表示属性的资源文件,需要修改其中的name=keycode的 attr。框架层增加完成后,只需要更改kl 文件,增加按键的映射关系即可。提示:在系统需要增加按键的时候,一种简易的做法是使用Android 中已经定义的 “ 生僻 ” 按键码作为这个新增按键的键码。使用这种方式Android 的框架层不需要做任何改动。这种方式的潜在问题是当某些第三方的应用可能已经使用那些生僻按键时,将意外激发系统的这种新增的按键。上页 下页名师资料总结 - - -精品资料欢迎下载 - - - - - -
24、 - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 21 页 - - - - - - - - - 8.3 模拟器中的实现驱动程序GoldFish 虚拟处理器键盘输入部分的驱动程序是event 驱动程序,在标准的路径中,相关文件如下所示:drivers/input/keyboard/goldfish_events.c 这个驱动程序是一个标准的event 驱动程序, 在用户空间的设备节点为/dev/event/ event0,其核心的内容为:events_interrupt 实现的是按键事件的中断处理函数,当中断发生后,读取虚拟寄存器的内容
25、,将信息上报。实际上,虚拟寄存器中的内容由模拟器根据主机环境键盘按下的情况得到。 8.3.2 用户空间的配置文件在模拟器环境中, 使用了默认的所有的KL 和 KCM 文件,由于模拟器环境支持全键盘,因此基本上包含了大部分的功能。在模拟器环境中,实际上按键的扫描码对应的是桌面电脑的键盘(效果和鼠标点击模拟器的控制面板类似),键盘的某些按键按下后,转化为驱动程序中的扫描码,然后再由上层的用户空间处理。这个过程和实际系统中是类似的。显然,通过更改默认的KL 文件,又可以更改实际按键的映射关系。上页 下页8.4 MSM 中的实现MSM 的 mahimahi 平台具有触摸屏,轨迹球和简易的按键,这些功能
26、在Android 中的8.4.1 触摸屏,轨迹球和按键驱动程序MSM 的 Mahimahi 平台的用户输入设备包括了以下几个Event 设备。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 21 页 - - - - - - - - - /dev/input/event4 :几个按键 /dev/input/event2 :触摸屏 /dev/input/event5 :轨迹球MSM 触摸屏的驱动程序在drivers/input/touchscreen 目录中的 synapt
27、ics_i2c_rmi.c,这是一个 i2c 触摸屏的驱动程序。MSM 系统包含了按键和轨迹球的功能,具体的驱动程序在arch/arm/mach-msm/目录board-mahimahi-keypad.c 文件中实现。board-mahimahi-keypad.c 中的全局定义如下所示:实现包括了驱动程序和用户空间的内容。按键和轨迹球是通过GPIO 系统来实现的,因此定义了gpio_event_info 类型的数组。 mahimahi-keypad 和mahimahi-nav 分别是两个设备的名称。gpio_event_info 指针各式的数组mahimahi_input_info 中包含了m
28、ahimahi_keypad_matrix_info.info ,mahimahi_keypad_key_ info.info ,jogball_x_axis.info.info和jogball_y_axis.info.info 。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 15 页,共 21 页 - - - - - - - - - 按键驱动是一个利用GPIO 矩阵的驱动, 由 gpio_event_matrix_info 矩阵定义, 定义还需要包含按键的GPIO矩阵和 inpu
29、t 设备的信息,内容如下所示:mahimahi_keypad_key_matrix _info和 mahimahi_keypad _info 是 gpio_event_matrix_info 类型的结构体, 分别负责两个和一个按键的处理,实际上,MSM 的 Mahimahi 平台基本上只有三个按键:Power,音量增加按键和音量减少按键。音量增加和音量减少的扫描码分别是KEY_VOLUMEUP(=115)和KEY_VOLUMEDOWN(=114)。提示:音量控制的两个按键在全键盘的qwerty.kl 有所定义, 同时符合 Linux 的 input 设备和 Android 的按键标准。轨迹球部
30、分也是由GPIO 实现的,由X 方向和 Y 方向两部分组成,内容如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 16 页,共 21 页 - - - - - - - - - 这里的轨迹球是用jog_axis_info 类型的结构体进行定义的,这种设备的类型(type)是相对设备EV_REL 。8.4.2 用户空间的配置文件除了默认的 AVRCP.kl 和 qwerty.kl 之外, MSM 的 mahimahi 平台增加了h2w_headset.kl 和mahimahi-ke
31、ypad.kl 。8.5 OMAP中的实现 8.5.1 触摸屏和键盘的驱动程序Omap 的 Zoom 平台的输入设备包含了触摸屏和键盘(Qwerty 全键盘)。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 17 页,共 21 页 - - - - - - - - - Omap 的 Zoom 平台的触摸屏驱动程序在drivers/input/touchscreen 目录中的 synaptics_ i2c_rmi.c ,这是一个i2c 的触摸屏的驱动程序。Omap 的 Zoom 平台的键
32、盘驱动程序在drivers/input/keyboard/ 目录的 twl4030_keypad.c 文件中实现。twl4030 使用的是 i2c 的接口。因此这个驱动程序本身是经过一次封装。twl4030_keypad.c 中核心的内容是中断处理的相关内容,do_kp_irq 就是标准 Linux 的中断的处理函数,其内容如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 18 页,共 21 页 - - - - - - - - - twl4030_keypad.c 文件中调用
33、的twl4030_i2c_read 和 twl4030_i2c_write 是在 drivers/ mfd/twl4030-core.c中实现的,实际上就是对i2c 总线的操作的封装。 8.5.2 用户空间的配置文件Omap 的 Zoom 平台的键盘基本上是全键盘,但是其数字键和字母键是共用的。因此使用全键盘的配置文件基本上可以。上页8.6 虚拟按键的实现虚拟按键 (Virtual Key )是 Eclair 版本开始增加的新特性。Virtual Key 的功能是利用触摸屏,模拟按键发生的事件,这样就可以利用触摸屏的边缘,实现一些可以自定义的按键效果。名师资料总结 - - -精品资料欢迎下载
34、- - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 19 页,共 21 页 - - - - - - - - - 虚拟按键的实现效果如图8-5 所示。在 Android 系统中,触摸屏设备发送的是RawInputEvent(原始输入事件),而按键发送的是KeyEvent(按键事件)。 KeyEvent 直接发送给应用程序层, RawInputEvent 在 Android 的 Java框架中被转换成MotionEvent发送给应用程序层。在 Android 系统中虚拟按键的实现方法是:在某种情况下,将RawInputEvent 转
35、换成 KeyEvent。frameworks/base/services/Java/com/android/server 目录中的 InputDevice.Java 文件负责处理虚拟按键的主要文件。虚拟按键的处理相对简单,需要根据以下文件对虚拟按键的内容进行配置:/sys/board_properties/virtualkeys.devicename 在 InputDevice.Java 文件中通过readVirtualKeys ,对进行消息的转化。根据配置文件将RawInputEvent 转换成按键相关的内容。virtualkeys.devicename 是虚拟按键的适配文件,需要在目标文件系统的/sys/board_ properties/目录中。虚拟按键配置文件的格式如下所示:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 20 页,共 21 页 - - - - - - - - - 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 21 页,共 21 页 - - - - - - - - -