輸入

Android Input HAL 圖示

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) 可能會透過 SysFS 匯出板載設定屬性,這些屬性會由 Android InputReader 元件使用,例如在觸控螢幕上放置虛擬鍵。

如要進一步瞭解不同裝置如何使用電路板設定屬性,請參閱裝置類別相關章節。

資源重疊

部分輸入行為會透過 config.xml 中的資源重疊設定,例如蓋子開關的操作。

舉例來說:

  • config_lidKeyboardAccessibility:指定機蓋切換鈕對實體鍵盤可用或隱藏的影響。

  • config_lidNavigationAccessibility:指定蓋子開關對觸控板可用或隱藏狀態的影響。

  • config_longPressOnPowerBehavior:指定使用者按住電源鍵時應發生的情況。

  • config_lidOpenRotation:指定蓋子開關對螢幕方向的影響。

如要進一步瞭解各設定選項,請參閱 frameworks/base/core/res/res/values/config.xml 中的說明文件。

按鍵對應

Android EventHubInputReader 元件會使用按鍵對應,為按鍵、搖桿按鈕和搖桿軸設定從 Linux 事件代碼對應至 Android 事件代碼的對應關係。對應項目可能會因裝置或語言而異。

如要進一步瞭解不同裝置如何使用鍵盤地圖,請參閱裝置類別相關章節。

輸入裝置設定檔

Android EventHubInputReader 元件會使用輸入裝置設定檔案,設定特殊裝置特性,例如如何回報觸控大小資訊。

如要進一步瞭解不同裝置如何使用輸入裝置設定對應,請參閱裝置類別相關章節。

瞭解 HID 用途和事件代碼

通常會使用多個不同的 ID 來參照鍵盤上的任一特定按鍵、遊戲控制器上的按鈕、搖桿軸或其他控制項。這些 ID 之間的關係不一定相同:它們取決於一組對應表,其中有些是固定的,有些則會因裝置特性、裝置驅動程式、目前語言代碼、系統設定、使用者偏好設定和其他因素而異。

實體掃描代碼

實體掃描碼是裝置專屬的 ID,與每個按鍵、按鈕或其他控制項相關聯。由於實體掃描碼通常因裝置而異,因此韌體或裝置驅動程式會負責將這些碼對應至標準 ID,例如 HID 用途或 Linux 鍵碼。

掃描碼主要用於鍵盤。其他裝置通常會使用 GPIO 針腳、I2C 訊息或其他方式進行低層通訊。因此,軟體堆疊的上層會依賴裝置驅動程式來解讀發生的情況。

HID 用途

HID 用途是用來回報控制項狀態的標準 ID,例如鍵盤按鍵、搖桿軸、滑鼠按鈕或觸控接觸點。大多數 USB 和藍牙輸入裝置都符合 HID 規格,因此系統可以以統一的方式與這些裝置互動。

Android 架構會依賴 Linux 核心 HID 驅動程式,將 HID 使用代碼轉譯為 Linux 鍵碼和其他 ID。因此,周邊製造商主要會對 HID 用途感興趣。

Linux 鍵碼

Linux 鍵碼是鍵或按鈕的標準 ID。Linux 鍵碼是在 linux/input.h 標頭檔案中定義,使用開頭為 KEY_BTN_ 的常數。Linux 核心輸入驅動程式負責將實體掃描代碼、HID 用法和其他裝置專屬信號轉譯為 Linux 鍵碼,並將相關資訊提供為 EV_KEY 事件的一部分。

Android API 有時會將與金鑰相關聯的 Linux 金鑰程式碼稱為「掃描碼」。這在技術上並不正確,但有助於在 API 中區分 Linux 鍵碼和 Android 鍵碼。

Linux 相對或絕對軸代碼

Linux 相對或絕對軸代碼是用於回報沿著軸的相對移動或絕對位置的標準 ID,例如滑鼠沿著 X 軸的相對移動,或搖桿沿著 X 軸的絕對位置。Linux 軸程式碼是在 linux/input.h 標頭檔案中定義,使用開頭為 REL_ABS_ 的常數。Linux 核心輸入驅動程式負責將 HID 用法和其他裝置專屬信號轉譯為 Linux 軸代碼,並在 EV_RELEV_ABS 事件中提供相關資訊。

Linux 切換程式碼

Linux 切換程式碼是用於回報裝置上切換器狀態的標準 ID,例如蓋子切換器。Linux 切換代碼是在 linux/input.h 標頭檔案中定義,使用開頭為 SW_ 的常數。Linux 核心輸入驅動程式會將切換狀態變更回報為 EV_SW 事件。

Android 應用程式通常不會接收來自切換鈕的事件,但系統可能會在內部使用這些事件,控制各種裝置專屬功能。

Android 金鑰碼

Android 鍵碼是 Android API 中定義的標準 ID,用於表示特定鍵,例如「HOME」。Android 鍵碼是由 android.view.KeyEvent 類別定義為以 KEYCODE_ 前置字串開頭的常數。

按鍵版面配置會指定 Linux 按鍵程式碼如何對應至 Android 按鍵程式碼。鍵盤型號、語言、國家/地區、版面配置或特殊功能可能會使用不同的按鍵配置。

使用裝置和語言代碼專屬的按鍵字元對應表,將 Android 按鍵程式碼組合轉換為字元程式碼。舉例來說,當同時按下 KEYCODE_SHIFTKEYCODE_A 鍵時,系統會在鍵字元對應表中查詢組合,並找出大寫字母「A」,然後插入目前聚焦的文字小工具中。

Android 軸向程式碼

Android 軸代碼是 Android API 中定義的標準 ID,用於指示特定裝置軸。Android 軸代碼由 android.view.MotionEvent 類別定義為以 AXIS_ 前置字串開頭的常數。

按鍵版面配置會指定 Linux 軸向程式碼如何對應至 Android 軸向程式碼。視裝置型號、語言、國家/地區、版面配置或特殊功能而定,可能會使用不同的按鍵版面配置。

Android 元狀態

Android 中繼狀態是 Android API 中定義的標準 ID,用於指出按下哪些修飾鍵。Android 元狀態由 android.view.KeyEvent 類別定義為開頭為 META_ 的常數。

目前的中繼狀態是由 Android InputReader 元件決定,該元件會監控 KEYCODE_SHIFT_LEFT 等修飾符鍵的按下 / 釋放時間,並設定 / 重設適當的中繼狀態標記。

修飾鍵與中繼狀態之間的關係是硬式編碼,但按鍵配置可變更修飾鍵本身的對應方式,進而影響中繼狀態。

Android 按鈕狀態

Android 按鈕狀態是 Android API 中定義的標準 ID,用於指出按下哪些按鈕 (滑鼠或觸控筆)。Android 按鈕狀態是由 android.view.MotionEvent 類別定義為開頭為 BUTTON_ 的常數。

目前的按鈕狀態是由 Android InputReader 元件決定,該元件會監控按鈕 (在滑鼠或觸控筆上) 的按下 / 放開時間,並設定 / 重設適當的按鈕狀態標記。

按鈕和按鈕狀態之間的關係已硬式編碼。

其他資訊

  1. Linux 輸入事件代碼
  2. Linux 多點觸控通訊協定
  3. Linux 輸入裝置驅動程式
  4. Linux 力回饋
  5. HID 資訊,包括 HID 使用表