Android 中 KeyEvent keycode 配置 及 转换原理
一、Kernel 修改
1. 修改 input-event-codes.h 添加keycode 定义 (16 进制)
实话说,这个文件具体作用没啥,只是一个头文件定义,起到让程序员更好看代码 和 管理代码的作用,并无其他实质作用。
如果代码没写那么规范,它写在 c 文件中也是可以的。
甚至可以不定义这个 ,直接在上报 键值的地方 用 数字,这样也行,就是不规范而已。
@ input.h
@ \kernel\msm-3.18\include\uapi\linux\input-event-codes.h
//
#define KEY_CAMERA_FOCUS 0x210 // 注意是 16 进制
#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
2. 修改 msm8909-mtp.dtsi 添加上报 (16 进制)
msm8909-mtp.dtsi
gpio_keys {
compatible = "gpio-keys";
input-name = "gpio-keys";
pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
pinctrl-0 = <&gpio_key_active>;
pinctrl-1 = <&gpio_key_suspend>;
camera_focus {
label = "camera_focus";
gpios = <&msm_gpio 91 0x1>;
linux,input-type = <1>;
linux,code = <0x210>; // 注意是 16 进制
gpio-key,wakeup;
debounce-interval = <15>;
};
}
二、Android 代码修改
1. 修改 input-event-codes.h (16 进制)
和 Kernel 中定义一样,注意是 16 进制
@\bionic\libc\kernel\uapi\linux\input-event-codes.h
#define KEY_CAMERA_FOCUS 0x210 // 注意是 16 进制
#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
2. 修改 kl 文件(十进制)
注意: 此处是配置 十进制。
@\frameworks\base\data\keyboards\Generic.kl
key 528 FOCUS
@ \device\qcom\msm8909\gpio-keys.kl
key 528 FOCUS
如何确认生效?
修改整编后,看 \out\target\product\msm8937_32go\system\usr\keylayout\gpio-keys.kl 和 Generic.kl 这个 目录下有没有对应的修改。
3. native 层 keycodes 重映射(十进制)
此处主要功能是在 native 层对 input 输入子系统上报的值进行重映射。
3.1 修改 keycodes.h
@ \frameworks\native\include\android\keycodes.h
/**
* Key codes.
*/
enum {
AKEYCODE_UNKNOWN = 0,
AKEYCODE_SOFT_LEFT = 1,
...
AKEYCODE_NUM = 78,
/** Headset Hook key.
* Used to hang up calls and stop media. */
AKEYCODE_HEADSETHOOK = 79,
/** Camera Focus key.
* Used to focus the camera. */
AKEYCODE_FOCUS = 80,
/** '+' key. */
AKEYCODE_PLUS = 81,
/** Menu key. */
AKEYCODE_MENU = 82,
}
3.2 修改 InputEventLabels.h
此时在 InputEventLabels.h 的KEYCODES[] 索引中 通过DEFINE_KEYCODE(FOCUS) ,将 kl 中换 FOCUS 开始绑定在一起了。
你可以发现,其实他的索引,就刚好是 AKEYCODE_FOCUS 的值 ,也就是 80。
@\frameworks\native\include\input\InputEventLabels.h
static const InputEventLabel KEYCODES[] = {
DEFINE_KEYCODE(UNKNOWN),
DEFINE_KEYCODE(SOFT_LEFT),
...
DEFINE_KEYCODE(NUM),
DEFINE_KEYCODE(HEADSETHOOK),
DEFINE_KEYCODE(FOCUS), // *Camera* focus
DEFINE_KEYCODE(PLUS),
DEFINE_KEYCODE(MENU),
}
struct InputEventLabel {
const char *literal; // 字符串
int value; // keycode 键值
};
// 宏定义如下:
#define DEFINE_KEYCODE(key) { #key, AKEYCODE_##key }
解析: DEFINE_KEYCODE(FOCUS) 的意思为生成这样一个结构体
DEFINE_KEYCODE(key) { 528, AKEYCODE_FOCUS }
这样,就相当于,定义一个名字: “FOCUS” <---> AKEYCODE_FOCUS (80)
static const InputEventLabel KEYCODES[] = {
{"FOCUS", 80}
}
此入的 "FOCUS" 就是 在gpio-keys.kl中定义的。
4. 修改 attrs.xml(十进制)
其实,getevent 之所显示 KEYCODE_FOCUS 就是在这里定义的。
将 前面换 AKEYCODE_FOCUS = 80 索引号,转的换为 name = “KEYCODE_FOCUS”
注意: getevent -l 中显示的名字就是从这获取的。
@ \frameworks\base\core\res\res\values\attrs.xml
<!-- This enum provides the same keycode values as can be found in
{@link android.view.KeyEvent}. -->
<attr name="keycode">
<enum name="KEYCODE_UNKNOWN" value="0" />
<enum name="KEYCODE_SOFT_LEFT" value="1" />
...
<enum name="KEYCODE_NUM" value="78" />
<enum name="KEYCODE_HEADSETHOOK" value="79" />
<enum name="KEYCODE_FOCUS" value="80" />
<enum name="KEYCODE_PLUS" value="81" />
<enum name="KEYCODE_MENU" value="82" />
5. 修改 KeyEvent.java
@ \frameworks\base\core\java\android\view\KeyEvent.java
public class KeyEvent extends InputEvent implements Parcelable {
public static final int KEYCODE_UNKNOWN = 0;
public static final int KEYCODE_SOFT_LEFT = 1;
...
public static final int KEYCODE_NUM = 78;
public static final int KEYCODE_HEADSETHOOK = 79;
/** Key code constant: Camera Focus key.
* Used to focus the camera. */
public static final int KEYCODE_FOCUS = 80; // *Camera* focus
public static final int KEYCODE_PLUS = 81;
public static final int KEYCODE_MENU = 82;
上层监听的其实并不是 keycode = 528 ,而是该keycode=528 在kl 中的别名 FOCUS 在 KEYCODES[ ] 数组中的索引号。
因此,在 上层定义 KEYCODE_FOCUS = 80 ,它就是用于监听的,因此上层监听的就是 80。
三、小结
可以这样理解:
-
在驱动层定义 上报的是0x210
#define KEY_CAMERA_FOCUS 0x210 // 注意是 16 进制 -
通过 gpio-keys.kl 文件 将驱动的 528(0x210) 和 FOCUS 这个名字绑定在一起
key 528 FOCUS -
在native 层将定义 AKEYCODE_FOCUS = 80
注意,后面 AKEYCODE_FOCUS 这个名 和 前面 kl 中的FOCUS 有没有很像,后面有关联的。 -
在 InputEventLabels.h 通过 DEFINE_KEYCODE(FOCUS) 和 kl 文件中的FOCUS 绑定在一起了,其数组索引号就是 AKEYCODE_FOCUS = 80
这样,会生成一个数组,{“FOCUS”, 80} ,通过查 kl 的 获得的 FOCUS 就是用于此处的,
当输入子系统中,接收到键值时,通过这个数组,就能知道它的索引号。 -
在attrs.xml ,将索引号 和 name 绑定在一起,显示对应的名字
-
修改 KeyEvent.java,最终,上层接收到的键值,其实是它的索引号,也就是80
这样,就完成了,键值转换,
驱动上报 0x210,在native 层查表得到它的索引号,上层获得 和 使用 的就是它的索引号,包括,显示keyevent名字
整个转换过程为:
(kernel)0x210
------> 528
------>(gpio-keys.kl) FOCUS
------> (InputEventLabels.h)KEYCODES[]={"FOCUS", 80}
------> 80
| 如果要处理键值的话
| ------>(KeyEvent.java) public static final int KEYCODE_FOCUS = 80;
| ------> onXXXXevent(){ case KEYCODE_FOCUS: xxxxxxx; break; }
|
| 如果是 getevent -l 显示名字的话
| ------> (attrs.xml) <enum name="KEYCODE_FOCUS" value="80" />
------> 最终显示 "KEYCODE_FOCUS"
Date: 2019/09/25 - 21:25