参考转载:http://blog.csdn.net/dyfleoo/article/details/41210919
1、Android 按键流程处理:
ScanCode -> KeyCodeLabel -> KeyCode -> Keyevent
1) 键扫描码ScanCode是由linux的Input驱动框架定义的整数类型,可参考input.h头文件(./external/kernel-headers/uapi/linux/input.h)。
2) 按键码(KeyCode),这个按键码是一个整数,在上层的JAVA程序中主要通过这个值来判断系统的实现。
----
实现过程:
1, ScanCode -> KeyCodeLabel。
键盘布局文件(*.kl) 把ScanCode转换为KeyCodeLabel。 *.kl文件在源码的devices文件夹中如(/device/rockchip/rk30sdk_bnd/rk29-keypad.kl;frameworks/base/data/keyboards)或设备中的/system/usr/keylayout/*.kl。
key 138 HELP //这里的HELP就是我们定义的android键值的字符形式,138则是linux键值,该值可以参考input.h, HELP 不能无缘无故就使用,必然有定义位置,这个位置就是InputEventLabels.h
底层传到的键值在EVENTHUB.CPP文件的getevent事件里面可以接收到,然后在传到KeyLayoutMap.cpp的mapKey函数中进行上层的映射,在5.1的系统中上层的映射按键定义在InputEventLabels.h的头文件中定义,按键传送走的流程跟4.4的差不多。
谈谈KL文件的作用:
android上层已经有按键事件的定义了,底层驱动也有按键事件上报。但是缺少了中间的对接层,也就是说哪个按键对应哪种事件还不清楚。所以,需要为它们加入一个布局文件。按键的布局文件存放在frameworks/base/data/keyboards目录下,以.kl为后缀的文件都是键盘的布局文件。那么编绎后我们可以在out/target/product/system/usr/keylayout文件夹中找到很多如果可缀为kl(布局)的文件,具体读取哪个布局文件是根据驱动的名字来确定的,如果找不到与驱动名字相同的文件,就会读取默认文件Generic.kl。现在我们假设键盘在驱动层的名字为“my_keypad”,所以需要创建一个名为“my_keypad,kl”的布局文件。
在keyboard.cpp中的文件中,有下函数解析到底使用那个名字的KL文件
status_t KeyMap::load@frameworks/base/libs/androidfw/keyboard.cpp
{
if (deviceConfiguration) {
String8 keyLayoutName;
if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
....
}
// Try searching by device identifier.
if (probeKeyMap(deviceIdenfifier, String8::empty())) {
return OK;
}
// Fall back on the Generic key map.
// TODO Apply some additional heuristics here to figure out what kind of
// generic key map to use (US English, etc.) for typical external keyboards.
if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
return OK;
}
// Try the Virtual key map as a last resort.
if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
return OK;
}
}
查看input devices相关信息可以用如下命令:cat /proc/bus/input/devices 或者 getevent -i
getevent命令同时也可以用于查看用户层是否接收到相关的键值信息。