入力

Android 入力 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 に送信し、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 使用状況

HID 使用状況は、キーボードのキー、ジョイスティックの軸、マウスボタン、指で接触される点などのコントロールの状態をレポートするために使用される標準の識別子です。USB 入力デバイスと Bluetooth 入力デバイスの大半は HID 仕様に準拠しており、システムとのインターフェースが統一されています。

Android フレームワークでは、Linux カーネルの HID ドライバを使用して、HID 使用状況コードを Linux キーコードなどの識別子に変換します。したがって、通常は周辺機器メーカーが HID 使用状況を扱います。

Linux キーコード

Linux キーコードは、キーまたはボタンの標準の識別子です。Linux キーコードは、KEY_ または BTN_ というプレフィックスで始まる定数を使用して、linux/input.h ヘッダー ファイルで定義されます。Linux カーネル入力ドライバは、物理スキャンコード、HID 使用状況などのデバイス固有の信号を Linux キーコードに変換し、それらに関する情報を EV_KEY イベントの一部として提供します。

Android API では、キーに関連付けられている Linux キーコードを「スキャンコード」と呼ぶ場合があります。厳密には正しくありませんが、これによって Linux キーコードを API の Android キーコードと識別できます。

Linux の相対軸コードまたは絶対軸コード

Linux の相対軸コードまたは絶対軸コードは、X 軸に沿ったマウスの相対的な動きや X 軸に沿ったジョイスティックの絶対的な位置など、軸に沿った相対的な動きや絶対位置をレポートするための標準識別子です。Linux の軸コードは、REL_ または ABS_ というプレフィックスで始まる定数を使用して、linux/input.h ヘッダー ファイルで定義されます。Linux のカーネル入力ドライバは、HID 使用状況やその他のデバイス固有の信号を Linux の軸コードに変換し、それらの情報を EV_REL イベントおよび EV_ABS イベントの一部として提供します。

Linux のスイッチコード

Linux のスイッチコードは、カバースイッチなどのデバイス上のスイッチの状態をレポートするための標準識別子です。Linux のスイッチコードは、SW_ というプレフィックスで始まる定数を使用して、linux/input.h ヘッダー ファイルで定義されます。Linux のカーネル入力ドライバは、スイッチ状態の変化を EV_SW イベントとしてレポートします。

Android アプリケーションは通常はスイッチからイベントを受信しませんが、内部でこれらを使用してさまざまなデバイス固有の機能を制御します。

Android キーコード

Android キーコードは、特定のキー(「HOME」など)を示すために Android API で定義された標準識別子です。Android キーコードは、android.view.KeyEvent クラスによって、KEYCODE_ というプレフィックスで始まる定数として定義されます。

キーレイアウトでは、Linux キーコードを Android キーコードにマッピングする方法を指定します。キーボードのモデル、言語、国、レイアウト、特別な機能に応じて、異なるキーレイアウトを使用できます。

Android キーコードの組み合わせは、デバイスとロケールごとに異なるキー文字マップを使用して文字コードに変換されます。たとえば、KEYCODE_SHIFTKEYCODE_A として識別されるキーが同時に押されると、キー文字マップの組み合わせが検索され、大文字の「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 コンポーネントによって決定されます。このコンポーネントは、マウスやタッチペンのボタンが押されたタイミング、または離されたタイミングをモニタリングし、適切なボタン状態フラグを設定またはリセットします。

なお、ボタンとボタン状態の関係はハードコードされています。

参考資料

  1. Linux 入力イベントコード
  2. Linux マルチタッチ プロトコル
  3. Linux 入力ドライバ
  4. Linux フォース フィードバック
  5. HID に関する情報(HID 使用状況の表を含む)