Android 輸入子系統名義上由一個遍歷系統多個層的事件管道組成。
輸入管道
在最低層,物理輸入設備產生描述狀態變化的信號,例如按鍵和触摸接觸點。設備固件以某種方式對這些信號進行編碼和傳輸,例如向系統發送 USB HID 報告或在 I2C 總線上產生中斷。
然後這些信號由 Linux 內核中的設備驅動程序解碼。 Linux 內核為許多標準外圍設備提供驅動程序,尤其是那些遵守 HID 協議的外圍設備。但是,OEM 必須經常為在低級別緊密集成到系統中的嵌入式設備(例如觸摸屏)提供自定義驅動程序。
輸入設備驅動程序負責通過 Linux 輸入協議將特定於設備的信號轉換為標準輸入事件格式。 Linux 輸入協議在linux/input.h
內核頭文件中定義了一組標準的事件類型和代碼。這樣,內核之外的組件就不需要關心物理掃描碼、HID 使用、I2C 消息、GPIO 引腳等細節。
接下來,Android EventHub
組件通過打開與每個輸入設備關聯的evdev
驅動程序從內核讀取輸入事件。然後,Android InputReader 組件根據設備類對輸入事件進行解碼,並生成 Android 輸入事件流。作為此過程的一部分,Linux 輸入協議事件代碼根據輸入設備配置、鍵盤佈局文件和各種映射表轉換為 Android 事件代碼。
最後, InputReader
將輸入事件發送到 InputDispatcher,後者將它們轉發到適當的窗口。
控制點
輸入管道中有幾個階段會影響對輸入設備行為的控制。
驅動程序和固件配置
輸入設備驅動程序經常通過在寄存器中設置參數甚至上傳固件本身來配置輸入設備的行為。對於諸如觸摸屏之類的嵌入式設備尤其如此,其中大部分校準過程涉及調整這些參數或修復固件以提供所需的精度和響應能力並抑制噪聲。
驅動程序配置選項通常在內核板支持包 (BSP) 中指定為模塊參數,以便同一個驅動程序可以支持多種不同的硬件實現。
本文檔確實試圖描述驅動程序或固件配置,但它確實提供了有關設備校準的一般指導。
板配置屬性
內核板支持包 (BSP) 可以通過 Android InputReader 組件使用的 SysFS 導出板配置屬性,例如在觸摸屏上放置虛擬鍵。
有關不同設備如何使用板配置屬性的詳細信息,請參閱設備類部分。
資源疊加
一些輸入行為是通過config.xml
中的資源覆蓋來配置的,比如蓋子開關的操作。
這裡有一些例子:
config_lidKeyboardAccessibility
:指定蓋子開關對硬件鍵盤是可訪問還是隱藏的影響。config_lidNavigationAccessibility
:指定蓋子開關對觸控板是可訪問還是隱藏的影響。config_longPressOnPowerBehavior
:指定當用戶按住電源按鈕時應該發生什麼。config_lidOpenRotation
:指定蓋子開關對屏幕方向的影響。
有關每個配置選項的詳細信息,請參閱frameworks/base/core/res/res/values/config.xml
中的文檔。
鍵映射
Android EventHub
和InputReader
組件使用鍵映射來配置從 Linux 事件代碼到鍵、操縱桿按鈕和操縱桿軸的 Android 事件代碼的映射。映射可能與設備或語言有關。
有關不同設備如何使用鍵映射的詳細信息,請參閱設備類部分。
輸入設備配置文件
Android EventHub
和InputReader
組件使用輸入設備配置文件來配置特殊的設備特性,例如如何報告觸摸大小信息。
有關不同設備如何使用輸入設備配置映射的詳細信息,請參閱設備類部分。
了解 HID 用法和事件代碼
通常有幾個不同的標識符用於指代鍵盤上的任何給定鍵、遊戲控制器上的按鈕、操縱桿軸或其他控件。這些標識符之間的關係並不總是相同的:它們依賴於一組映射表,其中一些是固定的,而另一些則根據設備的特性、設備驅動程序、當前語言環境、系統配置而變化,用戶偏好和其他因素。
- 實物掃碼
物理掃描碼是與每個按鍵、按鈕或其他控件相關聯的設備特定標識符。由於物理掃描代碼通常因設備而異,因此固件或設備驅動程序負責將它們映射到標準標識符,例如 HID 用法或 Linux 密鑰代碼。
掃描代碼主要對鍵盤感興趣。其他設備通常使用 GPIO 引腳、I2C 消息或其他方式在低級別進行通信。因此,軟件堆棧的上層依賴設備驅動程序來理解正在發生的事情。
- 隱藏使用
HID 用法是一種標準標識符,用於報告控件的狀態,例如鍵盤鍵、操縱桿軸、鼠標按鈕或觸摸觸點。大多數 USB 和藍牙輸入設備都符合 HID 規範,這使得系統能夠以統一的方式與其接口。
Android 框架依靠 Linux 內核 HID 驅動程序將 HID 使用代碼轉換為 Linux 密鑰代碼和其他標識符。因此,HID 的使用主要是外圍設備製造商感興趣的。
- Linux 密鑰代碼
Linux 鍵碼是鍵或按鈕的標準標識符。 Linux 密鑰代碼在
linux/input.h
頭文件中使用以前綴KEY_
或BTN_
開頭的常量定義。 Linux 內核輸入驅動程序負責將物理掃描代碼、HID 使用和其他特定於設備的信號轉換為 Linux 密鑰代碼,並將有關它們的信息作為EV_KEY
事件的一部分傳遞。Android API 有時將與某個鍵關聯的 Linux 鍵碼稱為“掃描碼”。這在技術上是不正確的,但它有助於在 API 中區分 Linux 密鑰代碼和 Android 密鑰代碼。
- Linux 相對或絕對軸代碼
Linux 相對或絕對軸代碼是用於報告沿軸的相對移動或絕對位置的標準標識符,例如鼠標沿其 X 軸的相對移動或操縱桿沿其 X 軸的絕對位置。 Linux 軸代碼在
linux/input.h
頭文件中使用以前綴REL_
或ABS_
開頭的常量定義。 Linux 內核輸入驅動程序負責將 HID 使用和其他設備特定信號轉換為 Linux 軸代碼,並將有關它們的信息作為EV_REL
和EV_ABS
事件的一部分提供。- Linux 切換代碼
Linux 開關代碼是用於報告設備上開關狀態的標準標識符,例如蓋子開關。 Linux 開關代碼在
linux/input.h
頭文件中使用以前綴SW_
開頭的常量定義。 Linux 內核輸入驅動程序將開關狀態更改報告為EV_SW
事件。Android 應用程序通常不接收來自開關的事件,但係統可能會在內部使用它們來控制各種設備特定的功能。
- 安卓鍵碼
Android 鍵碼是在 Android API 中定義的標準標識符,用於指示特定鍵,例如“HOME”。 Android 鍵碼由
android.view.KeyEvent
類定義為以前綴KEYCODE_
開頭的常量。按鍵佈局指定如何將 Linux 按鍵代碼映射到 Android 按鍵代碼。根據鍵盤型號、語言、國家/地區、佈局或特殊功能,可能會使用不同的按鍵佈局。
使用設備和區域設置特定的鍵字符映射將 Android 鍵代碼的組合轉換為字符代碼。例如,當標識為
KEYCODE_SHIFT
和KEYCODE_A
的鍵同時按下時,系統會在鍵字符映射中查找組合併找到大寫字母“A”,然後將其插入當前聚焦的文本小部件中。- Android 軸代碼
Android 軸代碼是在 Android API 中定義的用於指示特定設備軸的標準標識符。 Android 軸代碼由
android.view.MotionEvent
類定義為以前綴AXIS_
開頭的常量。鍵佈局指定如何將 Linux 軸代碼映射到 Android 軸代碼。根據設備型號、語言、國家/地區、佈局或特殊功能,可能會使用不同的按鍵佈局。
- Android 元狀態
Android 元狀態是 Android API 中定義的標準標識符,用於指示按下了哪些修飾鍵。 Android 元狀態由
android.view.KeyEvent
類定義為以META_
前綴開頭的常量。當前元狀態由 Android InputReader 組件確定,該組件監視何時按下/釋放修飾鍵(例如
KEYCODE_SHIFT_LEFT
)並設置/重置適當的元狀態標誌。修飾鍵和元狀態之間的關係是硬編碼的,但是鍵佈局可以改變修飾鍵本身的映射方式,進而影響元狀態。
- Android 按鈕狀態
Android 按鈕狀態是在 Android API 中定義的標準標識符,用於指示按下了哪些按鈕(在鼠標或觸控筆上)。 Android 按鈕狀態由
android.view.MotionEvent
類定義為以前綴BUTTON_
開頭的常量。當前按鈕狀態由 Android InputReader 組件確定,該組件監視何時按下/釋放按鈕(在鼠標或觸控筆上)並設置/重置適當的按鈕狀態標誌。
按鈕和按鈕狀態之間的關係是硬編碼的。