键盘布局、定义
键布局映射文件通常放在/system/usr/keylayout和/data/usr/keylayout
Android默认将去读/system/usr/keylayout/qwerty.kl这个配置文件
键字符映射位于:/system/usr/keychars和/data/usr/keychars
Android默认将去读/system/usr/keylayout/qwerty.kcm这个配置文件
键映射文件通常以UTF8文本文件格式存储于设备,通常有如下特性:
注释:用#表示,以#开头的内容都将被忽略。
空白:所有的空行被忽略
键定义:键定义遵循如下格式
key SCANCODE KEYCODE [FLAGS...],
当扫描码是一个数字,键码定义在你描述的布局文件android.keylayout.xxx,另外可以设置相关的FLAGS:
SHIFT: 当按下,自动加上SHIFT键值
ALT:当按下,自动加上ALT
CAPS:当按下,自动带上CAPS大写
WAKE:当按下,当设备进入睡眠的时候,按下这个键将唤醒,而且发送消息给应用层。
WAKE_DROPPED:当按下,且设备正处于睡眠,设备被唤醒,但是不发送消息给应用层。
keySCANCODE 定义:
文件:kernel\include\linux\input.h
/*
* Keys and buttons
*
* Most of the keys/buttons are modeled after USB HUT 1.12
* (see http://www.usb.org/developers/hidpage).
* Abbreviations in the comments:
* AC - Application Control
* AL - Application Launch Button
* SC - System Control
*/
#define KEY_RESERVED0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
...
#define KEY_011
#define KEY_MINUS 12
#define KEY_EQUAL 13
...
#define KEY_BACK158/* AC Back */
KEYCODE 定义
frameworks\base\include\androidfw\KeycodeLabels.h
#include <android/keycodes.h>
struct KeycodeLabel {
const char *literal; // KEYCODE
int value; //用于在keymap索引字符的value 对应keyevent.java中的键值
};
static const KeycodeLabel KEYCODES[] = {
{ "SOFT_LEFT", 1 },
{ "SOFT_RIGHT", 2 },
{ "HOME", 3 },
{ "BACK", 4 },
...
}
frameworks\base\libs\androidfw\Keyboard.cpp
通过函数
int32_t getKeyCodeByLabel(const char* label) {
return int32_t(lookupValueByLabel(label, KEYCODES));
}把scan code转换成andriod上层 KeyEvent.java 中用到的keycode
例: public static final int KEYCODE_HOME = 3;
键盘映射文件示例:
android/src/device/product/generic/tuttle2.kl
# Copyright 2007 The Android Open Source Project
key 2 1
...
key 11 0
key 158 BACK WAKE_DROPPED
key 230 SOFT_RIGHT WAKE
key 60 SOFT_RIGHT WAKE
key 107 ENDCALL WAKE_DROPPED
key 62 ENDCALL WAKE_DROPPED
key 229 MENU WAKE_DROPPED
*。kcm文件实例:
type ALPHA
key A {
label: 'A'
number: '2'
base: 'a'
shift, capslock: 'A'
alt: '#'
shift+alt, capslock+alt: none
}
key B {
label: 'B'
number: '2'
base: 'b'
shift, capslock: 'B'
alt: '<'
shift+alt, capslock+alt: none
}
按键处理流程
驱动层轮询查询按键输入,有输入事件时把Event放入RawEvent队列,RawEvent队列中的每个RawEvent最后都会通过一系列转化,最终变为KeyEvent被发送给另外一个线程,即输入线程,也就是一个Activity的主线程。android 上层在文件 frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java中处理分发消息
无论是虚拟按键还是物理按键都是要经过驱动层注册为输入设备,然后上报到kernel/drivers/input/input.c中。这里有相关函数的定义。然后通过、sys上报到frameworks/services/input/EventHub.cpp中,在这里会对设备进行扫描并且判断是哪种设备,然后在InputReader.cpp中对原始数据进行读取。在framewoks/services/input/InputDispatcher.cpp中实现数据的派发。在framework/base/core/jni/android_view_KeyEvent.cpp中实现通过JNI机制向上层的KeyEvent.java提供数据。并且在frameworks/base/core/java/android/view/KeyEvent.java中向上层的APP开发人员提供接口