android Input子系統分析



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 messagesGPIO pin 之類的物理特性了.

 

然後,Android EventHub 通過打開關聯到設備上的事件設備驅動,讀取輸入設備事件。Android InputReader 接着根據設備類和Android輸入事件流來解析輸入事件。在這個過程中,linux協議事件碼會通過輸入設備的配置文件(*.idc),鍵盤的佈局文件(*.kl),已經各種映射表(*.kcm)轉換爲Android事件碼.

 

最終,InputReader把輸入事件發送到InputDispatcherInputDispatcher再將事件發送到合適的窗口.

 

 

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 EventHubInputReader用來配置Linux按鍵、遙控杆方向、遙控手柄按鍵的事件碼到Android事件碼,映射方法可能會因設備或者語言不同而有所不同。

 

Input Device Configuration Files

輸入設備配置文件提供給Android EventHubInputReader配置特殊的設備特性,比如有多少觸摸信息需要報告。

 

 

Understanding HID Usages and Event Codes

鍵盤、遊戲控制器的按鍵、搖桿或其他控制設備各自有自己的設備標識符,這些標識符之間不一定都是形同的,他們依靠的映射表,有些設備有些按鍵可以互用,但大多時候受設備的特性、設備的驅動、不同的國家地區或者區域、系統配置、用戶偏好還有其他因素影響。

 

Physical Scan Code

Scancode 是設備上每個按鍵,按鈕或者其他控制連接到設備上的特殊標誌符。因爲scancode在不同是設備之間常常都是不同的,即同一個按鈕在不同的設備上,對應的scancode大多都是不相同的,因此需要固件或者設備驅動來負責將這些scancode映射爲標準的標誌符,比如標準的HID設備或者linux設備的keycode

 

Scancode主要用在鍵盤上。或者是其他通過GPIOi2c、或者其他通信方式的設備,

 

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_SHIFTKEYCODE_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/resetsAndroid 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/resetsAndroid InputReader 組件會確定當前button state.

 

Buttons buttons是由硬件編碼確定的他們之間的關係的.


Key Layout Files

鍵佈局文件.kl文件負責映射linux key code或者axis codeAndroid 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設爲2AXIS_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_RZ0X05表示AXIS_BRAKEBRAKE表示),並反轉否定它然後輸出

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 codeAndroid 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

然後,我們在frameworkconfig.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-zA-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:包含全部字母,並且可能有一些數字的鍵盤.

支持直接文字輸入,但鍵盤的尺寸可能是一個精簡的鍵盤.和完整的鍵盤相比,一些符號可能只能通過屏幕字符采集才能訪問.另外,爲了增加打字速度和準確性,frameworkalpha鍵盤提供了特殊優化,比如自動拼寫、開關/SHIFTALT.

                            這種類型的鍵盤是專爲拇指打字設計的.

         FULL:PC風格的全鍵盤

                            這種類型的鍵盤類似PC的鍵盤.所以的符號都可以直接通過擊鍵來訪問,沒有在屏幕上的支持或者優化,比如自動拼寫.

                            這種類型的鍵盤是專爲兩手打字設計的.

         SPECIAL_FUNCTION:鍵盤用於執行系統功能,而不是輸入.

                            一個只支持一些系統功能,比如HOME, POWER功能,沒有實際打字輸入功能的鍵盤.

 

Generic.kcmvirtual.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 SHIFTRIGHT 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

}

系統會從上到下,從左到右查找,labelnumber屬性會被忽略掉,因爲這兩個是特殊的.

 

第一個找到的屬性是base,不管有沒修飾符鍵(ctrlaltshift等)按下,base屬性都會先採用.因此,如果後面沒有指定特定的屬性覆蓋默認的屬性,就要指定默認的行爲.因爲系統用的是base屬性,因此事實上系統用的行爲時‘a’(輸入一個字符a.

 

接着系統會繼續掃描下面的屬性,如果下面再次指定了屬性就用新的覆蓋掉base屬性. 如果遇到shift就會使用SHIFT+A,所以系統會忽略掉base屬性並選擇shift屬性相應的行爲,上面的例子中是’A’

 

然後會繼續掃描列表,但其他的屬性都不會使用(因爲CAPS LOCK CONTROL ALT META都沒有按下).

 

所以SHIFT+A組合鍵輸出的結果最終將是’A’.

 

CONTROL + A

當用戶同時按下CONTROLA的時候,考慮一下會發生什麼事呢.

 

首先,系統會掃描屬性表,它會先掃描到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_XREL_Y碼,也支持EV_KEY事件類型和BTN_MOUSE,然後系統會歸類這個輸入設備爲一個鼠標. 鼠標的默認的行爲是在當前的屏幕上跟蹤鼠標的移動顯示鼠標光標,並在鼠標點擊時模擬觸摸動作.儘管鼠標可以進行不同配置,但默認的功能對於標準的鼠標外設已經夠用了.

 

當然,輸入設備的歸類是比較不確定的.例如,多點觸摸屏和touchpad 至少支持EV_ABS事件類型和ABS_MT_POSITION_XABS_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-zA-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 多點觸摸輸入協議.

 

你還需要更新你的輸入設備配置文件,因爲一些屬性已經變得更簡單,更系統了.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章