原文出处: http://blog.csdn.net/skdev/archive/2010/03/08/5355542.aspx
7 键盘
系统在KeyInputQueue服务里创建了一个线程,在这个线程里不断读取输入事件,然后对这个事件进行处理。
7.1 按键输入队列服务
按键输入事件有多种方式,如:键盘敲击、触摸屏触击、鼠标点击及多点触摸,主要是按下和放开的事件。
7.1.1 输入事件的数据结构
文件:frameworks/base/core/java/android/view/RawInputEvent.java
7.1.2 输入事件服务
文件:frameworks/base/services/java/com/android/server/KeyInputQueue.java
7.1.2.1 获取事件
调用readEvent,将输入事件读取到ev类,即RawInputEvent的变量里,readEvent对应jni的android_server_KeyInputQueue_readEvent
7.1.2.2 处理键盘事件
处理键盘事件,并将该事件加入事件队列。
7.2硬件调用
文件:frameworks/base/services/jni/com_android_server_KeyInputQueue.cpp
将从eventhub读到的变量存到android/view/RawInputEvent类对应的变量里。
7.3 EventHub库
文件:frameworks/base/libs/ui/EventHub.cpp
7.3.1 读取输入设备状态
openPlatformInput() 打开/dev/input/ 目录下的所有输入设备文件。
打开设备后,不断轮循所有设备,直到读取有POLLIN事件产生的设备的状态。
7.3.2 导入键盘配置文件
由以上代码可知,会优先加载/system/usr/keylayout/输入设备名称.kl
如: /sys/class/input/input1/name = keypad,则会加载/system/usr/keylayout/keypad.kl,如果该文件不存在,则加载默认文件/system/usr/keylayout/qwerty.kl,该文件的原型在:sdk/emulator/keymaps/qwerty.kl ,eclair以前的版本都是放在development/ emulator/keymaps/qwerty.kl
7.3.3 按键映射
如7.3.2所示代码,先加载配置文件:
如7.3.1所示代码,再将读取到的按键码进行转换:
err = mDevices[i]->layoutMap->map(iev.code, outKeycode, outFlags);
文件:frameworks/base/libs/ui/KeyLayoutMap.cpp
由以上代码可知,是以如下方式对配置文件进行解析的:
BEGIN: 如果第一个关键字是key,则转入SCANCODE,否则退出。
SCANCODE: 将第二个关键字转为数字,即扫描码scancode,转向KEYCODE。
KEYCODE: 将第三个关键字与KEYCODES列表配对,找出关键码keycode,转向FLAG。
FLAG:如果第四个关键字是key,则保存刚扫描的键码,然后转向SCANCODE,否则将该关键字与FLAGS列表配对,找出flags值,然后转向BEGIN。
注:KEYCODES列表和FLAGS列表的定义在:
frameworks/base/include/ui/KeycodeLabels.h
Map的功能是根据scancode,找到对应的keycode.
qwerty.kl 的部分配置:
7.4 字符映射
7.4.1 加载字符配置表
文件:frameworks/base/core/java/android/view/KeyCharacterMap.java
ctor_native 原型如下:
文件:frameworks/base/core/jni/android_text_KeyCharacterMap.cpp
KeyCharacterMap::load原型如下:
文件:frameworks/base/libs/ui/KeyCharacterMap.cpp
以上所提及代码要实现的功能是:先查看hw.keyboards.%u.devname的属性,若存在则打开/system/usr/keychars/%s.kcm.bin文件,否则打开默认文件:/system/usr/keychars/qwerty.kcm.bin
文件:frameworks/base/libs/ui/EventHub.cpp
参考<<7.3.2 导入键盘配置文件>>里的:
在代码里设置了KeyCharacterMap::load 中hw.keyboards.%u.devname所需要的值,即设备名称,如: /sys/class/input/input1/name = keypad,则会加载/system/usr/keychars/keypad.kcm.bin
例:
/sys/class/input/input1/name = keypad
则要打开的文件路径是:
/system/usr/keylayout/keypad.kl
/system/usr/keychars/keypad.kcm.bin
若以上文件不存在,则使用默认文件:
/system/usr/keylayout/qwerty.kl
/system/usr/keychars/qwerty.kcm.bin
7.4.2字符映射
文件:frameworks/base/core/java/android/view/KeyCharacterMap.java
getMatch_native 原型如下:
文件:frameworks/base/core/jni/android_text_KeyCharacterMap.cpp
getMatch的原型如下:
文件:frameworks/base/libs/ui/KeyCharacterMap.cpp
qwerty.kcm的部分配置:
找到keyCode对应的所有字符,然后再根据modifiers选择对应的字符
7.5 流程总结
当有按键响应时,内核传给ANDROID的是scancode,ANDROID将scancode经配置表(如qwerty.kl)找到keycode标识符,然后由内部表KEYCODES列表找到keycode的数字值,再由keycode的数字值经字符配置表(如qwerty.kcm)找到对应的字符值。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/skdev/archive/2010/03/08/5355542.aspx