按键布局文件

按键布局文件(.kl 文件)将 Linux 按键代码和轴代码映射到 Android 按键代码和轴代码,并指定关联的政策标志。设备专属按键布局文件:

  • 对具有按键(包括音量、电源和耳机媒体按键等特殊按键)的内部(内置)输入设备而言是必要文件。
  • 对其他输入设备而言是可选文件,而对特殊用途的键盘和操纵杆而言则是推荐文件。

如果没有可用的设备专属按键布局文件,则系统将改选默认文件。

位置

按键布局文件由 USB 供应商、产品(可能还包括版本)ID 或输入设备名称来确定位置。系统会按顺序查阅以下路径:

  • /odm/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
  • /vendor/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
  • /system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
  • /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
  • /odm/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
  • /vendor/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
  • /system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
  • /data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
  • /odm/usr/keylayout/DEVICE_NAME.kl
  • /vendor/usr/keylayout/DEVICE_NAME.kl
  • /system/usr/keylayout/DEVICE_NAME.kl
  • /data/system/devices/keylayout/DEVICE_NAME.kl
  • /odm/usr/keylayout/Generic.kl
  • /vendor/usr/keylayout/Generic.kl
  • /system/usr/keylayout/Generic.kl
  • /data/system/devices/keylayout/Generic.kl

当构建包含设备名称的文件路径时,设备名称中除“0-9”“a-z”“A-Z”“-”或“_”之外的所有字符将替换为“_”。

常规按键布局文件

系统提供了一个特殊的内置常规按键布局文件,名为 Generic.kl。此按键布局旨在支持各种标准外部键盘和操纵杆。请勿修改常规按键布局!

语法

按键布局文件是由按键或坐标轴声明和标记组成的纯文本文件。

按键声明

按键声明包含关键字 key(后跟一个 Linux 按键代码编号和 Android 按键代码名称),或该关键字的用途(后跟 HID 用途和 Android 按键代码名称)。HID 用途以 32 位整数表示,其中高 16 位表示 HID 用途页面,低 16 位表示 HID 用途 ID。任何一项声明都可以后跟一组由空格分隔的可选政策标志。

key 1     ESCAPE
key 114   VOLUME_DOWN
key 16    Q                 VIRTUAL
key usage 0x0c006F          BRIGHTNESS_UP

可识别以下政策标志:

  • FUNCTION:按键应解读为如同也按下了 FUNCTION 键。
  • GESTURE:按键由用户手势(例如手掌摸触摸屏)生成。
  • VIRTUAL:按键是与主触摸屏相邻的虚拟软键(电容式按钮)。这会导致启用特殊的去抖动逻辑(请参阅下文)。

坐标轴声明

每个坐标轴声明都包含关键字 axis,后跟一个 Linux 坐标轴代码编号和限定符,用于控制坐标轴(包括至少一个 Android 坐标轴代码名称)的行为。

基本坐标轴

基本坐标轴仅会将 Linux 坐标轴代码映射到 Android 坐标轴代码名称。以下声明将 ABS_X(由 0x00 表示)映射到 AXIS_X(由 X 表示)。

axis 0x00 X

在上述示例中,如果 ABS_X 的值为 5,那么 AXIS_X 会设为 5

分轴

分轴将一个 Linux 坐标轴代码映射到两个 Android 坐标轴代码名称,以便小于或大于阈值的值在映射时可以分割到两个不同的坐标轴。当设备报告的单个物理轴对两个不同的互斥逻辑轴进行编码时,此映射非常有用。

ABS_Y 轴的值(由 0x01 表示)小于 0x7f 时,以下声明会将其映射到 AXIS_GAS;当该值大于 0x7f 时,会将其映射到 AXIS_BRAKE

axis 0x01 split 0x7f GAS BRAKE

在上述示例中,如果 ABS_Y 的值为 0x7d,那么 AXIS_GAS 设为 2 (0x7f - 0x7d),并且 AXIS_BRAKE 设为 0。相反,如果 ABS_Y 的值为 0x83,那么 AXIS_GAS 设为 0,并且 AXIS_BRAKE 设为 4 (0x83 - 0x7f)。最后,如果 ABS_Y 的值等于 0x7f 的分值,那么 AXIS_GASAXIS_BRAKE 均设为 0

反转坐标轴

反转坐标轴会反转坐标轴值的符号。以下声明将 ABS_RZ(由 0x05 表示)映射到 AXIS_BRAKE(由 BRAKE 表示),并通过求补来反转输出。

axis 0x05 invert BRAKE

在上述示例中,如果 ABS_RZ 的值为 2,那么 AXIS_BRAKE 设为 -2

中心平面选项

由于存在噪声,即使在操纵杆未被使用时,操纵杆设备也可能会报告输入事件。这种噪声通常来自左侧杆和/或右侧杆,会导致驱动程序报告接近 0 的位置值。“中心平面”值用于指定预期会从处于静止状态的控制杆获得的噪声量。

Linux 输入协议为输入设备驱动程序提供了一种用于指定操纵杆轴中心平面值的方式,但并非所有驱动程序都会报告该值,并且有些驱动程序会提供不正确的值。为了解决这个问题,可以在轴声明后面加一个 flat 选项,用于指定轴的中心位置周围多宽的区域应被视为中心区域。

例如,如果设备驱动程序报告的 AXIS_X 值介于 0 到 100 之间,那么 Android 输入系统会将 0 映射到 -1,并将 100 映射到 1。该范围的中心在未缩放的坐标中为 50,在经过缩放的坐标中为 0。如果平面值等于 10,那么开发者应假定报告的任何介于 -0.1 到 0.1 之间的 AXIS_X 值(在未缩放的坐标中,则是介于 40 到 60 之间)均为噪声,并将来自操纵杆的这些值视为零。

注意:尽管按键布局文件会指定驱动程序坐标空间的值,但 android.view.InputDevice.MotionRange#getFlat() 报告的值是在 Android 坐标空间内的值。

axis 0x03 Z flat 4096

在以上示例中,中心平面值设为了 4096

注释

注释行以“#”开头,并持续到这一行的结束位置:

# A comment!

空白行会被忽略。

示例

键盘

# 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...

系统控件

# 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
# the device decodes into key presses.

key 114   VOLUME_DOWN
key 115   VOLUME_UP
key 116   POWER

电容式按钮

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

key 139    MENU           VIRTUAL
key 172    HOME           VIRTUAL
key 158    BACK           VIRTUAL
key 217    SEARCH         VIRTUAL

耳机插孔媒体控件

# 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
key 165   MEDIA_PREVIOUS
key 226   HEADSETHOOK

操纵杆

# 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 in a range of -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

虚拟软键

在下列使用情形中,输入系统提供了特殊的功能来实现虚拟软键:

  1. 如果虚拟软键以图形方式显示在屏幕上(例如在 Galaxy Nexus 上),它们将由系统界面包中的导航栏组件实现。由于要在系统的高层中实现图形虚拟软键,因此不涉及按键布局文件,以下信息将不适用。
  2. 如果虚拟软键作为属于主触摸屏一部分的扩展可触摸区域进行实现(例如在 Nexus One 上),输入系统会使用虚拟按键映射文件将 X/Y 触摸坐标转换为 Linux 按键代码,然后使用按键布局文件将 Linux 按键代码转换为 Android 按键代码(如需详细了解虚拟按键映射文件,请参阅触摸设备)。触摸屏输入设备的按键布局文件必须指定相应的按键映射并使每个按键都包含 VIRTUAL 标志。
  3. 如果虚拟软键作为独立于主触摸屏的电容式按钮进行实现(例如在 Nexus S 上),内核设备驱动程序或固件会负责将触摸转换为 Linux 按键代码,然后输入系统使用按键布局文件将其转换为 Android 按键代码。电容式按钮输入设备的按键布局文件必须指定相应的按键映射并使每个按键都包含 VIRTUAL 标志。

如果虚拟软键位于触摸屏内或离触摸屏很近,那么当用户在屏幕底部附近触摸或在屏幕上从上往下或从下往上滑动手指时,容易不小心按到按钮。为了避免出现这种情况,输入系统会应用一个短暂的去抖动,以便在最近触摸触摸屏之后的短时间内忽略虚拟软键按压(该延迟称为“虚拟键安静时间”)。

如需启用虚拟软键去抖动,请执行以下操作:

  1. 为触摸屏或电容式按钮输入设备提供按键布局文件,并为每个按键设置 VIRTUAL 标志。
    key 139    MENU           VIRTUAL
    key 172    HOME           VIRTUAL
    key 158    BACK           VIRTUAL
    key 217    SEARCH         VIRTUAL
    
  2. 在框架 config.xml 资源的资源叠加层中设置虚拟按键安静时间的值。
    <!-- Specifies the amount of time to disable virtual keys after the screen
    is touched 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>
    

验证

您应使用验证按键映射工具验证您的按键布局文件。