android Input子系统分析(内核层->android系统层)

Input Technical Information

Android 输入子系统支持许多不同的设备类,包括键盘,摇杆,轨迹球,鼠标和触摸屏.

这份文档描述了上层如何配置,校准,测试,和编写输入设备驱动.

 

Input Concepts

Overview

Key LayoutFiles

Key CharacterMap Files

InputDevice Configuration Files

MigrationGuide

Input Device Classes

Keyboard Devices

Touch Devices

Tools

Dumpsys

Getevent

Validate Keymaps

 

原文:http://source.android.com/tech/input.html

 

Overview

Android 输入子系统是由一条贯穿系统多层的事件管道线组成的.

 

 

Input Pipeline

在底层,物理输入设备会通过产生电子信号,比如按键或者触摸,来表示设备的状态改变了。接着设备固件会将这些信号编码并通过USB HID或者通过I2C总线产生中断上报给系统.

 

Linux内核收到这些信号后会通过设备驱动来解码。Linux内核为许多标准的外围设备特别是标准的HID协议提供了驱动。但如果是OEM的话,则需要客户自己为嵌入式设备提供底层驱动,就像比较常见的触摸屏一样.

 

Linux输入设备驱动通过linux输入协议,负责将设备特定的信号转换为标准的输入事件格式。Linux输入协议定义了一个标准的事件类型集,在代码的/include/linux/input.h头文件里面。就这样,内核外围的输入设备驱动部分就可以不用管像 scan codes, HID usages, I2C messages,GPIO pin 之类的物理特性了.

 

然后,Android EventHub 通过打开关联到设备上的事件设备驱动,读取输入设备事件。Android InputReader 接着根据设备类和Android输入事件流来解析输入事件。在这个过程中,linux协议事件码会通过输入设备的配置文件(*.idc),键盘的布局文件(*.kl),已经各种映射表(*.kcm)转换为Android事件码.

 

最终,InputReader把输入事件发送到InputDispatcher,InputDispatcher再将事件发送到合适的窗口.

 

 

Control Points

在输入管道线上,有几个地方会影响输入我们控制设备的行为

 

Driver and Firmware Configuration

输入设备驱动或者固件本身频繁地设置设备寄存器参数或者配置设备的行为。特别是像嵌入式触摸屏这种设备,需要通过不停地更改参数来校准,或者为了更高的精确度,或者为了抑制噪音,频繁地调整固件的各种参数。

 

在内核的BSP中,常常将驱动配置选项指定为模块参数,这样的话一个驱动就可以支持多个不同的硬件平台。

 

Board Configuration Properties

InputReader 可能会通过SysFS用到内核BSP里面设置的开发板配置属性,比如触摸屏的虚拟按键的布局。

   

Resource Overlays

少数输入行为是通过在config.xml进行资源覆盖来,比如一些开关效果。

下面是一些例子:

·         config_lidKeyboardAccessibility: 当实体键盘访问和隐藏的时候的特殊效果

·         config_lidNavigationAccessibility: 当触控板被访问和隐藏时候的特殊效果

·         config_longPressOnPowerBehavior: 当用户按下power键时候的特殊效果

·         config_lidOpenRotation: 当屏幕的方向改变时候的特殊效果

这里的每个配置选项的详细配置可以查看framworks/base/core/res/res/values/config.xml.

 

Key Maps

键盘映射用于Androdi EventHub和InputReader用来配置Linux按键、遥控杆方向、遥控手柄按键的事件码到Android事件码,映射方法可能会因设备或者语言不同而有所不同。

 

Input Device Configuration Files

输入设备配置文件提供给Android EventHub和InputReader配置特殊的设备特性,比如有多少触摸信息需要报告。

 

 

Understanding HID Usages and Event Codes

键盘、游戏控制器的按键、摇杆或其他控制设备各自有自己的设备标识符,这些标识符之间不一定都是形同的,他们依靠的映射表,有些设备有些按键可以互用,但大多时候受设备的特性、设备的驱动、不同的国家地区或者区域、系统配置、用户偏好还有其他因素影响。

 

Physical Scan Code

Scancode 是设备上每个按键,按钮或者其他控制连接到设备上的特殊标志符。因为scancode在不同是设备之间常常都是不同的,即同一个按钮在不同的设备上,对应的scancode大多都是不相同的,因此需要固件或者设备驱动来负责将这些scancode映射为标准的标志符,比如标准的HID设备或者linux设备的keycode。

 

Scancode主要用在键盘上。或者是其他通过GPIO、i2c、或者其他通信方式的设备,

 

HID Usage

HID Usage是一个标准的标识符,用于报告一些控制的状态,如键盘键,摇杆轴,鼠标键或触摸接触点.大多数USB和蓝牙输入设备符合HID规范,因此他们都能用相同的方式和系统衔接.

 

Android Framework 依靠Linux kernel HID 驱动来转换HID usage codes为linux keycodes或者其他标识符.因此HID usage对厂商很有吸引力.

 

Linux Key Code

一个Linux key code是一个标准的按键或按钮的标识符.Linux key code是定义在的linux/Input.h头文件,用前缀的KEY_或BTN_的开头来表示的常量. Linux内核输入驱动负责转换物理扫描码,HID用法和其他特定设备的信号为Linuxkey code,并发送和EV_KEY相关的信息.

 

Android的API有时引用"scan code"来表示Linux key code.从技术上讲这是不正确的,但它有助于区分Linuxkey code 和Android的API中的key code.

 

Linux Relative or Absolute Axis Code

Linux relative 或 absolute axis code 是一个标志的标识符,用来上报一个轴的相关移动或者绝对位置的事件,比如一个鼠标沿X轴或沿X轴移动,或者操纵杆的绝对位置的改变. Linux axis code定义在Linux/input.h头文件里面,以前缀为REL_或ABS_的常量. Linux内核输入驱动程序负责转换HID usages和其他特定设备的信号为Linuxaxis code,并上报和EV_REL和EV_ABS事件有关的信息.

 

Linux Switch Code

Linuxswitch code 是一个标准的标识符,用来上报一个设备的开关事件,比如一个合盖的开关,Linux switch code定义在Linux/input.h头文件里面,以SW_开头的常量.Linux kernel 输入驱动把开关状态改变的事件作为EV_SW事件上报.

 

Android应用程序通常不从开关接收事件,但该系统可以通过使用它们实现各种设备需要的功能.

 

Android Key Code

Android Key Code 是一个定义在Android API里面的标准的标识符,比如“HOME”按键的HOME就是一个标识符.Android Key Code是定义在android.view.KeyEvent 类,以KEYCODE_的一个常量.

 

键布局指定一个Linux key code 如何映射为Android key code,键布局之间的差异和键的模式,语言,国家,布局和特殊的功能.

 

Android key codes的组合转换为字符码需要用本地指定的键字符映射.例如,当一个按键标识为KEYCODE_SHIFT和KEYCODE_A同时按下,系统先在字符映射查找组合,并查找首字母A’,然后在当前光标处插入映射文件指定的文本字符.

 

Android Axis Code

Android axis code 是一个标准的标识符定义在Android API,用来表示一个特定的设备轴.Android axis codes 是定义在android.view.MotionEvent类,一个以KEYCODE_开头的常量.

 

键布局指定了Linux Axis codes是如何映射为Android axis codes. 键布局之间的差异和键的模式,语言,国家,布局和特殊的功能.

 

Android Meta State

Android Meta State 是一个标准的标识符,定义在Android API 里面,用来指定那个修饰键被按下. Android meta states 定义在android.view.KeyEvent类,以META_开头的常量.

 

当类似KEYCODE_SHIFT_LEFT修饰键被pressed/released,或者sets/resets,Android InputReader 组件会确定meta state.

 

修饰键和meta state直接的关系是硬件确定的,但可以通过修改key layout来影响meta states.

 

Android Button State

Android button State 是一个标准的标识符,定义在Android API 里面,用来指定哪个按钮(鼠标或者笔尖)被按下. Android button states 定义在android.view.MotionEvent类,以BUTTON_开头的常量.

 

当按钮(鼠标或者笔尖)被pressed/released,或者sets/resets,Android InputReader 组件会确定当前button state.

 

Buttons 和 buttons是由硬件编码确定的他们之间的关系的.


Key Layout Files

键布局文件(.kl文件)负责映射linux key code或者axis code为Android key code或者axis code,并指定相关的属性标识.

所有按键(包含特殊键,比如volume、power、media等等)的输入设备都需要键映射文件.

特定的设备不必一定需要键布局文件,但专用键盘和操纵杆建议创建键布局文件.

如果没有为设备建立键布局文件,那么系统会选择一个默认的布局文件.

 

Location

键布局文件名可用USBvendor、product(或者version)id组成的字符串,或使用输入设备名称加上后缀来.kl.

系统根据一定的顺序来查找.kl文件,下面路径是系统查找kl文件的顺序:

     /system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl

     /system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl

     /system/usr/keylayout/DEVICE_NAME.kl

     /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl

     /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl

     /data/system/devices/keylayout/DEVICE_NAME.kl

     /system/usr/keylayout/Generic.kl

     /data/system/devices/keylayout/Generic.kl

当上面的文件中有一个查找到以后,系统会将除0-9、A-Z、a-z、-或者"外的其他字符用'代替.

 

GenericKey Layout File (通用键布局文件)

Generic.kl文件是Android为了支持各种各样的标准键盘和操纵杆,内置的一个通用键布局文件.

请不要修改通用键布局!

 

Syntax (键布局文件语法)

键布局文件是一个纯文本的文件,包含有按键和轴的声明和标识.

    

Key Declarations (键声明)

键声明由key开头,紧接着linuxkey code(即scan code),接着是Android key code,在后面可以选择性地添加一些键的属性.

     key 1     ESCAPE

     key 114   VOLUME_DOWN       WAKE

     key 16    Q                 VIRTUAL     WAKE

 

下面是系统可识别的属性标识符:

     WAKE: 当键按下后,设备会从睡眠中唤醒。因为历史原因,这个标识的行为和下面的WAKE_DROPPED一样.

     WAKE_DROPPED: 当键按下后,设备会从睡眠中唤醒,但按键本身在唤醒发生后会丢失,即按键只唤醒设备,但按键本身并不处理.

     SHIFT: 表示这个键需要在SHIFT键按下后才会被解析.

     CAPS_LOCK: 表示这个键需要在CAPS LOCK键按下后才会被解析.

     ALT: 表示这个键需要在ALT键按下后才会被解析.

     ALT_GR: 表示这个键需要在RIGHT ALT键按下后才会被解析.

     FUNCTION: 表示这个键需要在FUNCTION键按下后才会被解析.

     VIRTUAL: 表示这个键是一个虚拟的按键(电容键),这和主触摸屏密切相关。这个会触发特殊抖动处理逻辑,看下面.

     MENU: 已过时的属性,不要使用.

     LAUNCHER: 已过时的属性,不要使用.

 

AxisDeclarations (轴声明)

AxisDeclarations 由关键字axis,后面紧接linux 轴码数,后面紧接着至少一个android 轴码名来控制轴的行为.

 

Basic Axes(基轴)

基轴简单地将linux 轴码映射为android的轴码名.

下面的声明映射ABS_X(图示为0x00)为AXIS_X(图示为X)

     axis 0x00 X

上面的例子中,如果ABS_X是5,那么AXIS_X将设为5.

 

Split Axes(分割轴)

一个分割轴映射linux 轴码为两个android轴码名,比如这个值小于或者大于阀值时,那么映射的时候会映射为两个不同的轴.当设备只上报了一个物理轴时会解码为两个不同的互斥的逻辑轴.

 

下面的声明为当ABS_Y(图示为0x01)值小于0x7f时,映射为AXIS_GAS;大于0x7f时映射为AXIS_BRAKE.

axis 0x01 split 0x7f GAS BRAKE

上面的例子中,如果ABS_Y的值是0x7d,那么AXIS_GAS设为2,AXIS_BRAKE设为0.相反地,如果ABS_Y值是0x83,则AXIS_GAS被设置为0,并且AXIS_BRAKE设置为4(0×83-  0x7f)中。最后,如果该值的ABS_Y等于0x7f的分割值的,那么AXIS_GAS和AXIS_BRAKE都被设置为0。

 

Inverted Axes(倒置轴)

倒置轴将得到的轴值的符号取反.

下面的声明映射ABS_RZ(0X05表示)为AXIS_BRAKE(BRAKE表示),并反转否定它然后输出,。

axis 0x05 invert AXIS_RZ

在上面例子中,如果ABS_RZ值是2,那么AXIS_RZ被设置为-2。

 

Center Flat PositionOption(中心位置选项)

Linux输入协议为输入设备驱动程序提供了一种方法,用来指定摇杆轴的中心位置,但不是所有的设备,其中一些设备提供的是不正确的值。

中心位置指的是轴在一个范围区间的中心位置,就像一个方向盘,当用户不触摸它的时候,它默认的轴位置就是中心位置.

要解决这个问题,后面可以跟一个选项用来为轴指定中心位置的值.

axis 0x03 Z flat 4096

上面的例子中,Z轴的中心位置指定为4096.

 

Comments(注释)

注释行以'#'开始的,继续行结束。像这样:

# A comment!

空行会被忽略。

 

Examples

Keyboard  (键盘)

# This is an example of a key layout file for a keyboard.

 

key 1     ESCAPE

key 2     1

key 3     2

key 4     3

key 5     4

key 6     5

key 7     6

key 8     7

key 9     8

key 10    9

key 11    0

key 12    MINUS

key 13    EQUALS

key 14    DEL

 

# etc...

 

System Controls (系统控制)

# This is an example of a key layout file for basic system controls, such as

# volume and power keys which are typically implemented as GPIO pins that

# the device decodes into key presses.

 

key 114   VOLUME_DOWN       WAKE

key 115   VOLUME_UP         WAKE

key 116   POWER             WAKE

Capacitive Buttons (电容按钮)

# This is an example of a key layout file for a touch device with capacitive buttons.

 

key 139    MENU           VIRTUAL

key 102    HOME           VIRTUAL

key 158    BACK           VIRTUAL

key 217    SEARCH         VIRTUAL

 

Headset Jack MediaControls (耳机插孔媒体控制)

# This is an example of a key layout file for headset mounted media controls.

# A typical headset jack interface might have special control wires or detect known

# resistive loads as corresponding to media functions or volume controls.

# This file assumes that the driver decodes these signals and reports media

# controls as key presses.

 

key 163   MEDIA_NEXT        WAKE

key 165   MEDIA_PREVIOUS    WAKE

key 226   HEADSETHOOK       WAKE

Joystick (摇杆)

# This is an example of a key layout file for a joystick.

 

# These are the buttons that the joystick supports, represented as keys.

key 304   BUTTON_A

key 305   BUTTON_B

key 307   BUTTON_X

key 308   BUTTON_Y

key 310   BUTTON_L1

key 311   BUTTON_R1

key 314   BUTTON_SELECT

key 315   BUTTON_START

key 316   BUTTON_MODE

key 317   BUTTON_THUMBL

key 318   BUTTON_THUMBR

 

# Left and right stick.

# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd.

# This confuses applications that rely on the flat value because the joystick actually

# settles in a flat range of +/- 4096 or so.  We override it here.

axis 0x00 X flat 4096

axis 0x01 Y flat 4096

axis 0x03 Z flat 4096

axis 0x04 RZ flat 4096

 

# Triggers.

axis 0x02 LTRIGGER

axis 0x05 RTRIGGER

 

# Hat.

axis 0x10 HAT_X

axis 0x11 HAT_Y

 

WakeKeys

唤醒键是特殊的按键,可以将设备从睡眠中唤醒,比如power按键.

默认情况下,内部键盘设备,没有按键是一个唤醒键.对于外部键盘设备,所有的按键都是唤醒键.

注意WindowManagerPolicy组件是负责执行唤醒键的行为。此外,按键保护可能会阻止某些键的功能为唤醒键。了解唤醒键的行为的最好的地方在PhoneWindowManager.interceptKeyBeforeQueueing.

 

VirtualSoft Keys

输入系统提供了特殊的功能来实现虚拟的软键.

有下面三种情况:

1、如果以图形的方式将软键显示在屏幕上,比如在Galaxy Nexus,则图形界面的实现在System UI package里面的Navigation Bar组件实现.

      因为图形虚拟软键在系统的上层实现,没有包含键盘的布局文件,所以下面的信息没有应用.

2、如果虚拟的软键用主触摸屏的一个扩展的可触摸区域来实现,例如在Nexus One上,会用虚拟按键映射文件转换X / Y触摸坐标为Linux key code,然后用按键布局文件翻译Linux key code为Android key code.

      查看TouchDevices 章节查看更多有关虚拟按键映射文件.

      触摸屏输入设备的按键布局文件必须指定相应的键映射,并为每个键加上VIRTUAL标识.

3、如果虚拟软键是电容按键,通过从主屏幕分出一块区域来来实现的,例如在Nexus S上,内核设备驱动或者固件负责转换触摸为linux key code ,然后通过输入子系统用键布局文件将其转换为androidkey code.

 

输入设备电容按键的键映射文件必须指定相应的按键映射并为每个键添加VIRTUAL标识.

当虚拟软键的触摸屏和我们人体近距离接触时,或者手指从屏的上面到下面滑动,或者从下面到上面滑动时,用户很容易按到屏幕上的电容按钮.

为了防止这种情况的发证,输入系统通过去抖的方法,比如虚拟软键按下后,如果时间很短,虚拟软键的按键会被忽略掉.这段有效的时间即为virtual key quiet time.

打开虚拟软键防抖,我们需要做以下两件事.

第一,我们需要为触摸屏或者电容按键输入设备提供一个键布局文件,并为每个键添加VIRTUAL标识.

key 139    MENU           VIRTUAL

key 102    HOME           VIRTUAL

key 158    BACK           VIRTUAL

key 217    SEARCH         VIRTUAL

然后,我们在framework的config.xml里面设置virtual key quiet time

<!-- Specifies the amount of time to disable virtual keys after the screen is touched

     in order to filter out accidental virtual key presses due to swiping gestures

     or taps near the edge of the display.  May be 0 to disable the feature.

     It is recommended that this value be no more than 250 ms.

     This feature should be disabled for most devices. -->

<integer name="config_virtualKeyQuietTimeMillis">250</integer>

 

Validation

确保使用验证工具来验证你的键布局文件.


KeyCharacter Map Files

键字符映射文件(*.kcm文件)负责通过转换器将Androidkey codes的组合键映射为Unicode 字符.

所有内置的有按键的输入设备都需要设备特定的键布局文件,目的仅仅是告知系统这个设备有特殊的用途(不是一个全键盘).

对于外部键盘可以不用指定设备特定的键布局文件,常常也完全不需要这个文件.因为系统提供了通用的键字符映射,可以适应大多数的外部键盘.

如果没有设备特定的键布局文件可用,系统会选择一个默认的代替.

 

 

Location

键字符映射文件可用USB vendor 、 product (或者version(可选))id来命名,或者用输入设备名.

系统会参照下面的路径按顺序查找键字符映射文件:

/system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm

/system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm

/system/usr/keychars/DEVICE_NAME.kcm

/data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm

/data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm

/data/system/devices/keychars/DEVICE_NAME.kcm

/system/usr/keychars/Generic.kcm

/data/system/devices/keychars/Generic.kcm

/system/usr/keychars/Virtual.kcm

/data/system/devices/keychars/Virtual.kcm

当构造一个文件路径包含了设备名,那么文件里面所有字符除了‘0-9’,a-z,A-Z,-,‘ 以外,其他字符都用’取代.

 

Generic Key Character Map File (通用键字符映射文件)

系统内置了一个键字符映射文件Generic.kcm,这个键字符映射目的是支持多种标准的外部键盘.

不要修改通用件字符映射!

 

Virtual Key Character Map File

系统为虚拟键盘设备内置了一个特殊键字符映射文件 virtual.kcm.

 

虚拟键盘设备是一个虚构的id为-1的设备(具体查看Keycharactermap.VIRTUAL_KEYBOARD). 从Android Honeycomb 3.0开始,所以都的android设备都有这个虚拟键盘设备. 虚拟键盘设备目的是提供一个内置的设备,可以为IME或者测试仪器使用,并将击键上报到应用里面,这样的话,设备甚至不需要内置键盘.

 

虚拟键盘被假定是一个全QWERTY的布局,并且在所有的设备上都一样. 这使得应用可以用虚拟键盘设备并且总是获取到相同的结果.

 

不要修改虚拟键字符映射!

 

Syntax(键映射文件语法)

键字符映射文件是一个纯文本的文件,包含有键盘类型的声明和键的声明.

 

Keyboard Type Declaration

键盘类型声明用来描述键盘的整体行为. 字符映射文件必须包含一个键盘类型声明. 为清楚起见,通常将声明放在文件的顶部.

    type FULL

下面的类型是系统可识别的类型:

         NUMERIC:数字键盘

                            数字键盘支持用multi-tap文本输入,这个可能需要多次击键产生所需的字母或者符号.

                            这种类型的键盘是专为拇指打字设计的.

                            对应KeycharacterMay.NUMERIC

         PREDICTIVE:包含全部字母,但每个键有超过一个字母的键盘.

                            这种类型的键盘是专为拇指打字设计的.

                            对应KeycharacterMay. PREDICTIVE

         ALPHA:包含全部字母,并且可能有一些数字的键盘.

支持直接文字输入,但键盘的尺寸可能是一个精简的键盘.和完整的键盘相比,一些符号可能只能通过屏幕字符采集才能访问.另外,为了增加打字速度和准确性,framework为alpha键盘提供了特殊优化,比如自动拼写、开关/锁SHIFT和ALT键.

                            这种类型的键盘是专为拇指打字设计的.

         FULL:PC风格的全键盘

                            这种类型的键盘类似PC的键盘.所以的符号都可以直接通过击键来访问,没有在屏幕上的支持或者优化,比如自动拼写.

                            这种类型的键盘是专为两手打字设计的.

         SPECIAL_FUNCTION:键盘用于执行系统功能,而不是输入.

                            一个只支持一些系统功能,比如HOME, POWER功能,没有实际打字输入功能的键盘.

 

Generic.kcm和virtual.kcm键字符映射都是FULLkeyboard.

 

Key Declarations

每个键声明由A         ndroidkey code的名字、一个开括号、键的属性和行为、闭括号组成.

key A {

    label:                              'A'

    base:                               'a'

    shift, capslock:                    'A'

    ctrl, alt, meta:                    none

}

 

Properties

每个键属性建立了键到行为的映射关系.为了使键字符映射文件更为紧凑,几个属性可以通过逗号分隔,然后映射到相同的行为上去.

 

在上面的例子中,label属性标志的是‘A’的行为.同样地,ctrl 、alt 、meta 属性都一齐指定为none 状态.

 

下面是系统可识别的属性:

         label:印在物理键上的标签,当它包含单个字符的时候,按键通过KeyCharacterMap.getDisplayLabel方法返回这个字符的值.

         number:当数字文本控件获得焦点后,这个属性会指定这个键的行为,比如当用户输入一个电话号码的时候.

                   紧凑的键盘常常整合了多个符号到一个键上面,例如,同一个键可能用于输入‘1’和‘a’或者‘#’和‘q’.对于这些键,number属性会指定那个符号会显示到数字显示框内.

                   一些典型的数字符号指的是'0' 到 '9''#''+''('')'',', 和 '.'.

         base:当按键没有修饰属性的时候,使用base指定的字符.

         <modifier> or<modifier1>+<modifier2>+...:当键按下并且指定的所有修饰属性都要激活才能输出指定的字符.

              比如,键修饰的属性字符是shift,当LEFT SHIFT或者RIGHT SHIFT 其中一个按下时,输出指定的字符.

              类似地,键修饰属性为rshift + ralt ,当RIGHT SHIFT和RIGHT ALT一起按下时,才会输出指定的字符.

 

下面的modifier是系统可以识别的modifier属性:

shift: Applies when either the LEFT SHIFT or RIGHT SHIFT modifier is pressed.

lshift: Applies when the LEFT SHIFT modifier is pressed.

rshift: Applies when the RIGHT SHIFT modifier is pressed.

alt: Applies when either the LEFT ALT or RIGHT ALT modifier is pressed.

lalt: Applies when the LEFT ALT modifier is pressed.

ralt: Applies when the RIGHT ALT modifier is pressed.

ctrl: Applies when either the LEFT CONTROL or RIGHT CONTROL modifier is pressed.

lctrl: Applies when the LEFT CONTROL modifier is pressed.

rctrl: Applies when the RIGHT CONTROL modifier is pressed.

meta: Applies when either the LEFT META or RIGHT META modifier is pressed.

lmeta: Applies when the LEFT META modifier is pressed.

rmeta: Applies when the RIGHT META modifier is pressed.

sym: Applies when the SYMBOL modifier is pressed.

fn: Applies when the FUNCTION modifier is pressed.

capslock: Applies when the CAPS LOCK modifier is locked.

numlock: Applies when the NUM LOCK modifier is locked.

scrolllock: Applies when the SCROLL LOCK modifier is locked.

 

属性列表中的顺序是很重要的.当映射一个键为一个行为时,系统扫描按照顺序扫描相关的属性,找到后返回最后对应标志的行为.

因此,后面定义的键属性会覆盖前面定义的键属性.

 

Behaviors

每个属性映射到一个行为,最常见的行为就是输入一个字符,但也有其他的.

 

下面的行为是系统可识别的:

         none:不输入一个字符.

                   当没有指定一个字符时,默认的属性就是none. 指定none是可选的,但它提高了精确度.

 

         ‘X’:键入指定的文本字符.

                   这个行为会将指定的字符键入获焦的文本控件内. 这个字符可能是ASCII字符,或是下面的定义的字符:

o'\\': 输入反斜线符号

o'\n': 输入新的一行 (use this for ENTER / RETURN).

o'\t': 输入一个TAB字符

o'\'': 输入一个 ’ 字符

o'\"': 输入一个冒号字符

o'\uXXXX': 输入一个格式为XXXX的十六进制Unicode 字符.

        

fallback <Android key code name>: 执行默认的操作如果这个键没有被应用程序处理.

这个行为会导致当应用程序不处理指定的键时,系统会去模拟一个不同的按键功能. 对于一个新的按键,并不是所有的应用都知道怎么去处理,因此这个属性可以用来支持新的按键的默认行为,例如ESCAPE或数字键盘键(当numlock 没有按下时).

                  

fallback被执行后,应用会接收到两个键按下:一个是原始的键,另外一个是fallback. 如果在键弹起时应用处理了原始的键,          然后fallback键事件会被cancel掉.(KeyEvent.isCanceled 会返回true)                  

 

系统保留了两个Unicode字符用来执行指定的功能:

        '\uef00':当这个行为被执行后,text控件会销毁并删除光标前的四个字符,并把它们解释为十六进制的数字,并插入Unicode 码.

        '\uef01':当这个行为被执行后,text 控件显示一个包含各种特殊符号的字符选择器对话框。

 

系统可识别下面的结合变音的废键字符的Unicode 字符

· '\u0300': 重音符

· '\u0301': 尖音符 

· '\u0302': 抑扬音音符 ^

· '\u0303': 波浪号音符 ~

· '\u0308': 变音音符

当一个字符后面紧随一个废键的话,废键和紧随的字符会被结合起来.比如,当用户输入一个重音音符后面紧随一个a字符,结果输出的会是'à'.

 

查看keyCharterMap.getDeadChar可知道废键的处理.

 

Comments

注释行以#开始,直到行的最后.例如

# A comment!

空白行会被忽略掉.

 

How Key Combinations are Mapped to Behaviors

当用户同时按下SHIFT键和A键.系统首先寻找KEYCODE_A对应的属性和行为.

key A {

    label:                              'A'

    base:                               'a'

    shift, capslock:                    'A'

    ctrl, alt, meta:                    none

}

系统会从上到下,从左到右查找,label和number属性会被忽略掉,因为这两个是特殊的.

 

第一个找到的属性是base,不管有没修饰符键(ctrl、alt、shift等)按下,base属性都会先采用.因此,如果后面没有指定特定的属性覆盖默认的属性,就要指定默认的行为.因为系统用的是base属性,因此事实上系统用的行为时‘a’(输入一个字符a).

 

接着系统会继续扫描下面的属性,如果下面再次指定了属性就用新的覆盖掉base属性. 如果遇到shift就会使用SHIFT+A,所以系统会忽略掉base属性并选择shift属性相应的行为,上面的例子中是’A’

 

然后会继续扫描列表,但其他的属性都不会使用(因为CAPS LOCK 、 CONTROL 、ALT 、 META都没有按下).

 

所以SHIFT+A组合键输出的结果最终将是’A’.

 

CONTROL + A

当用户同时按下CONTROL和A的时候,考虑一下会发生什么事呢.

 

首先,系统会扫描属性表,它会先扫描到base属性,然后会继续扫描,直到扫描到control属性. 正好,control属性出现在base属性后面,所以control属性会覆盖掉base属性的行为.

 

所以组合键CONTROL+A的最终行为时none.

 

ESCAPE

现在假设用户按下了ESCAPE按键

key ESCAPE {

    base:                               fallback BACK

    alt, meta:                          fallback HOME

    ctrl:                               fallback MENU

}

这个时候系统会获取到fallback BACK行为,一个回调的行为. 因为没有字符字母显示,所以不会有字符输入.

 

当处理这个键的时候,系统会首先把KEYCODE_ESCAPE传送给应用程序.如果应用程序不处理它,系统会再尝试一次,但这次会传送给应用程序回调行为的请求.

 

所以应用程序识别并支持KEYCODE_ESCAPE,并有机会去处理这个键,但其他应用程序不能代替执行回调动作,因为它的动作是KEYCODE_BACK.

 

NUMPAD_0 with orwithout NUM LOCK

数字键盘键有不同的处理,它需要依赖NUM LOCK键是否锁上.

 

NUM LOCK按下时,下面的键声明确保KEYCODE_NUMPAD_0输出是0.当NUM LOCK没有按下,键上传给应用的是普通的键,如果没有处理,回调键KEYCODE_INSERT会代替上传.

key NUMPAD_0 {

    label, number:                      '0'

    base:                               fallback INSERT

    numlock:                            '0'

    ctrl, alt, meta:                    none

}

正如我们看到的,回调键的声明极大地兼容和其它旧的应用程序不能识别或者支持类似PC全键盘上的所有键.

 

 

 

Examples

Full Keyboard

# This is an example of part of a key character map file for a full keyboard

# include a few fallback behaviors for special keys that few applications

# handle themselves.

 

type FULL

 

key C {

    label:                              'C'

    base:                               'c'

    shift, capslock:                    'C'

    alt:                                '\u00e7'

    shift+alt:                          '\u00c7'

    ctrl, meta:                         none

}

 

key SPACE {

    label:                              ' '

    base:                               ' '

    ctrl:                               none

    alt, meta:                          fallback SEARCH

}

 

key NUMPAD_9 {

    label, number:                      '9'

    base:                               fallback PAGE_UP

    numlock:                            '9'

    ctrl, alt, meta:                    none

}

Alphanumeric Keyboard

# This is an example of part of a key character map file for an alphanumeric

# thumb keyboard.  Some keys are combined, such as `A` and `2`.  Here we

# specify `number` labels to tell the system what to do when the user is

# typing a number into a dial pad.

#

# Also note the special character '\uef01' mapped to ALT+SPACE.

# Pressing this combination of keys invokes an on-screen character picker.

 

type ALPHA

 

key A {

    label:                              'A'

    number:                             '2'

    base:                               'a'

    shift, capslock:                    'A'

    alt:                                '#'

    shift+alt, capslock+alt:            none

}

 

key SPACE {

    label:                              ' '

    number:                             ' '

    base:                               ' '

    shift:                              ' '

    alt:                                '\uef01'

    shift+alt:                          '\uef01'

}

Game Pad

# This is an example of part of a key character map file for a game pad.

# It defines fallback actions that enable the user to navigate the user interface

# by pressing buttons.

 

type SPECIAL_FUNCTION

 

key BUTTON_A {

    base:                               fallback BACK

}

 

key BUTTON_X {

    base:                               fallback DPAD_CENTER

}

 

key BUTTON_START {

    base:                               fallback HOME

}

 

key BUTTON_SELECT {

    base:                               fallback MENU

}

 

 

Compatibility Note(兼容性注意事项)

Android 3.0 以前,Android 键字符映射用的是极不相同的语法,并且在编译的时候,兼容二进制文件格式(.kcm.bin).

 

尽管新的格式用的是相同的拓展名.kcm, 但语法有极大的不同(功能更强大);

 

根据Android Honeycomb 3.0,所有Android键字符映射文件必须用这份文档中所用的语法解析文本文件格式.旧的语法已经不再支持了,并且就的.kcm.bin文件也不能被系统识别.

 

Language Note

Android 目前不持多语言键盘.并且,内置的通用的键字符映射默认是US English 键盘布局.

 

OEM 如果设计为其他语言,则需要为他们的键盘提供键字符映射

 

Android将来的版本可能会提供更好的多语言键盘或者用户可选的键盘布局.

 

Validation

Validate Keymaps工具来验证你的键字符映射文件.


InputDevice Configuration Files

输入设备配置文件(.idc文件)包含影响输入设备行为的特殊设备配置属性.

 

标准外设,如HID键盘和鼠标通常都都是没必要用输入设备配置文件的,因为系统默认的行为通常确定他们一连接上就可以使用.换句话说,内置的嵌入式设备,尤其是触摸屏,几乎总是请求输入设备配置文件来指定他们的行为.

 

Rationale(基本原理)

Android自动检测和配置大多数输入设备Linux 内核输入设备驱动上报上了的事件类型和属性.

 

例如,如果一个输入设备支持EV_REL事件类型和REL_X和REL_Y码,也支持EV_KEY事件类型和BTN_MOUSE,然后系统会归类这个输入设备为一个鼠标. 鼠标的默认的行为是在当前的屏幕上跟踪鼠标的移动显示鼠标光标,并在鼠标点击时模拟触摸动作.尽管鼠标可以进行不同配置,但默认的功能对于标准的鼠标外设已经够用了.

 

当然,输入设备的归类是比较不确定的.例如,多点触摸屏和touchpad 至少支持EV_ABS事件类型和ABS_MT_POSITION_X和ABS_MT_POSITION_Y码. 然而,这些设备的预期用途是很不相同的,并且不能总被自动识别.同时,还需要弄清楚设备上报压力和大小的信息,因此触摸设备,特别是内置的触摸屏等,通常需要IDC文件.

 

Location

输入设备配置文件可用USB vendor 、 product (或者version(可选))id来命名,或者输入设备名.

系统会参照下面的路径按顺序查找输入设备配置文件:

· /system/usr/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc

· /system/usr/idc/Vendor_XXXX_Product_XXXX.idc

· /system/usr/idc/DEVICE_NAME.idc

· /data/system/devices/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc

· /data/system/devices/idc/Vendor_XXXX_Product_XXXX.idc

· /data/system/devices/idc/DEVICE_NAME.idc

当构造一个文件路径包含了设备名,那么文件里面所有字符除了‘0-9’,a-z,A-Z,-,‘ 以外,其他字符都用’取代.           

 

Syntax

输入配置文件是一个纯文本的文件,包含属性赋值和注释.

 

Properties

每个属性赋值包括属性名,等号=,和属性值,占用新的一样:

property = value

 

属性名是一个非空的字母文本标识符. 属性名中不能有空格.每个输入系统组件定义了一系列的属性用来配置它的功能.

 

属性值是非空的字符串,整数,或浮点型的书. 属性值不能包含空格或者其他保留字符 \ 或者 ”.

 

属性名和属性值是区分大小写的.

 

 

Comments

注释行以#开始,直到行的最后.例如

# A comment!

空白行会被忽略掉.

 

Example

# This is an example of an input device configuration file.

# It might be used to describe the characteristics of a built-in touch screen.

 

# This is an internal device, not an external peripheral attached to the USB

# or Bluetooth bus.

device.internal = 1

 

# The device should behave as a touch screen, which uses the same orientation

# as the built-in display.

touch.deviceType = touchScreen

touch.orientationAware = 1

 

# Additional calibration properties...

# etc...

 

 

Common Properties

下面的属性是系统所有输入设备类共用的.

 

了解每种输入设备类特殊属性用法请查阅相关的文档.

 

device.internal

Definition: device.internal = 0 | 1

指定输入设备是否是内置的设备还是一个外接的设备.

·         If the value is 0, the device is external.

·         If the value is 1, the device is internal.

·         如果没有指定这个值,则默认为0,所有的USB设备和蓝牙设备都默认为0,其他设备默认为1.

 

这个属性策略性地决定了设备的唤醒方式.

 

内部输入设备通常不用从睡眠中唤醒显示器,除非显示地配置在键布局文件中或者硬编码规则中. 这个区分防止无效的按键触摸事件导致唤醒设备,比如说手机放在口袋的时候. 通常只定义一个唤醒键.

 

相反地,外部输入设备通常可以强制性地唤醒设备,因为他们只是假定被关掉了或者在传输数据中没有插入. 例如,当用户按下外部键盘的时候,用户的意图是想唤醒这个设备,并且有反应.

 

因此,为所有的输入设备确定device.internal属性值是很重要的.

 

Validation

Validate Keymaps工具来验证你的键字符映射文件.

 

Migration Guide

这个章节包含了一些有用的信息,帮助你移植到一个新的Android版本.

 

Migrating to Android Gingerbread 2.3

In Gingerbread, 我们添加了输入设备配置文件的概念(在这个版本还涉及到输入设备的校准文件).

 

需要为所有的触摸屏提供一个输入设备配置文件. 并需要花时间去校准相关的触摸大小信息.

 

Migrating to Android Honeycomb 3.0

In Honeycomb,我们修改了键字符映射文件格式并开始用更大的输入设备配置文件. 我们同事也添加了支持全PC风格键盘和引用了一个新的键映射“Generic”,这替换了旧的模拟器指定的“qwerty”键映射(这个键映射没打算用来做通用的键映射).

 

确定用新的语法更新你的所有键的键字符映射文件.

 

如果你的外设依赖旧的“qwerty”键映射,让回你可能需要为模拟器提供新的特殊设备键映射俩映射旧的功能. 你要为每个设备标识符用USB product id / vendor id或设备名创建一个新的键映射.

 

为所有特殊功能的输入设备提供键字符映射文件是十分重要的.这些文件需要包含新的一行,用来设置键盘类型为SPECIAL_FUNCTION.

 

一个确保所有的内置的输入设备的相应的配置文件是正确的的方法,就是运行Dumpsys来查看设备是否不恰当地运行Generic.kcm文件.

 

Migrating to Android Honeycomb 3.2

In Honeycomb 3.2,我们添加了支持摇杆和拓展的键布局文件格式来支持摇杆轴的映射.

 

Migrating to Android Ice Cream Sandwich4.0

InIce Cream Sandwich 4.0,我们改动了设备驱动需求,用来支持标准Linux 多点触摸输入协议,并添加“B”协议的支持.我们也支持数字化平板和手写笔触摸设备.

 

你可能需要更新你的输入设备驱动来正确地实现标准的Linux 多点触摸输入协议.

 

你还需要更新你的输入设备配置文件,因为一些属性已经变得更简单,更系统了.

 

http://blog.csdn.net/xiaoxiaoyu1107/article/details/39400199

posted @ 2014-11-24 22:37  MMLoveMeMM  阅读(5464)  评论(0编辑  收藏  举报