2011年01月27日
Androidのキー入力イベント処理のメモ
Androidでキー入力があったときに、それはどういう経路を伝わるのか?
電源キーを長押しするとシャットダウンのメニューが表示されるが、これはどこでやっている?
このあたりのことを調べるためにソースコードを追いかけたときのメモです。Androidのフレームワークの中の話で、アプリケーションからは見えない部分です。
Android 2.2のソースを見ました。2.3では少し変わっているようです。
カーネルからキーインプットイベントを得るところ
frameworks/base/libs/ui/EventHub.cpp
システムコール inotify_add_watch を使って /dev/input以下をまとめて監視しています。
キー入力は /dev/input/event0 で タッチパネルは /dev/input/event1 でした。
これは以下のような実験でわかります。Androidのコンソールで
# cat /dev/input/event0
この状態で何かキーを押すとコンソールになにかゴミが表示されます。キー入力がバイナリの数値で読めるためです。
止めたい時はコンソールでコントロールCを入力してcatを強制終了します。
JNI
ソースを逆にたどってEventHub.cppを使っているのは
frameworks/base/services/jni/com_android_server_KeyInputQueue.cpp
Javaでは
frameworks/base/services/java/com/android/server/KeyInputQueue.java
さらにさかのぼると
frameworks/base/services/java/com/android/server/WindowManagerservice.java
特殊キーの処理
電源キーを押したときにスリープモードに移行したり、長押しのときにはシャットダウンメニューを表示したりするのはここでやっています。
/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java
キーコードやキーのレイアウト
カーネルの中でのキーコードの定義はここにあります。
include/linux/input.h
例
#define KEY_POWER 116
Androidの中でのキーコードの定義はここ。
frameworks/base/core/java/android/view/KeyEvent.java
例
KEYCODE_POWER = 26
カーネルからのキーコードをAndroidのキーコードに対応付けを行うのはここ。
ターゲットの中の
/system/user/keylayout/qwerty.kl
例
key 116 POWER
これでカーネルからのKEY_POWER(=116)のキーコードがAndroidでのKEYCODE_POWER(=26)に対応付けがなされています。
キーのカスタマイズ
どの物理キーに何の役割を持たせるかをカスタマイズしたいときに考えらる方法は2つ。
1. カーネルのキーのデバイスドライバでそのキーで発行するキーコードを変更する。
2. Androidでのキーコードのマッピングを変更する。つまり /system/user/keylayout/qwerty.kl
カーネルを変更できるならば1.がシンプル。カーネルの変更ができない場合でも2.ならターゲットのシステム領域を書き換える権限があれば可能です。