1、前言
在Android開發中可能會遇到添加新的按鍵的需求,本文將簡單介紹如何在Android系統中完成一個新的按鍵的添加。
當系統有新的按鍵需要添加時,Linux內核下的鍵碼到Android系統中鍵碼是如何進行轉換映射的?
2、內核添加設備節點
首先,我們需要在Linux內核添加新的按鍵值,在Linux內核中提供了按鍵的驅動程序gpio_keys.c,該驅動是基於設備樹實現的,因此,先添加自己的設備節點,如下:
gpio_keys { status = "okay"; compatible = "gpio-keys"; #address-cells = <1>; #size-cells = <0>; input-name = "test-keys"; pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend"; pinctrl-0 = <&gpio_key_active>; pinctrl-1 = <&gpio_key_suspend>; key1@1 { label = "key1"; gpios = <&msm_gpio 96 1>; linux,code = <116>; linux,input-type = <1>; }; key2@2 { label = "key2"; gpios = <&msm_gpio 98 0>; linux,code = <102>; linux,input-type = <1>; }; };
在該設備樹節點中,定義了兩個按鍵,分別是key1(鍵碼值為116)和key2(鍵碼值為102),關於該設備節點的更詳細介紹,可以查看下面的設備樹綁定文檔:
AOSP/kernel/Documentation/devicetree/bindings/gpio/gpio_keys.txt
關於Linux內核中的鍵碼值定義在文件:
AOSP/kernel/include/uapi/linux/input.h
鍵碼值如下所示:
#define KEY_RESERVED 0 #define KEY_ESC 1 #define KEY_1 2 #define KEY_2 3 #define KEY_3 4 #define KEY_4 5 #define KEY_5 6 #define KEY_6 7 #define KEY_7 8 ... ... ...
添加設備樹節點完成后,將Linux內核進行編譯並燒寫,查看新添加的設備節點是否已經添加完成:
$ cd/sys/class/input/input2/device $ cat uevent
查看設備節點的uevent信息,如下所示,則在Linux內核中完成了新的按鍵設備節點添加:
3、鍵值上報到應用層
在上面,已經完成了Linux內核中按鍵的設備節點的添加,但是這僅僅是在Linux內核里面的鍵值,因此,我們需要修改按鍵的布局文件,並完成按鍵的鍵值上報到應用層。
(1)添加按鍵布局文件
按鍵布局文件是用來完成映射過程的,文件以kl結尾,用於將Linux內核中input子系統上報的鍵值轉換成對應得按鍵值供Android系統上層使用,在下面的目錄添加test-keys.kl文件:
AOSP/device/qcom/msm8909/
如下所示:
key 116 POWER key 102 HOME
需要注意的是,按鍵布局文件的名稱必須與input輸入設備的名稱一致,否則將EvenHub在加載設備時將找不到對應得kl文件而加載默認的kl文件,從而鍵值轉換錯誤,在kl文件中,key是固定的,中間的數字代表的是Linux內核對應得鍵碼。
接下來需要將按鍵的kl文件添加到系統中:
在AndroidBoard.mk中添加編譯的命令,文件如下:
AOSP/device/qcom/msm8909/AndroidBoard.mk
添加的內容如下:
include $(CLEAR_VARS) LOCAL_MODULE := test-keys.kl LOCAL_MODULE_TAGS := optional eng LOCAL_MODULE_CLASS := ETC LOCAL_SRC_FILES := $(LOCAL_MODULE) LOCAL_MODULE_PATH := $(TARGET_OUT_KEYLAYOUT) include $(BUILD_PREBUILT)
修改base.mk文件,否則該kl文件將不會被打包,文件如下:
AOSP/device/qcom/common/base.mk
添加內容如下:
# add new kl
KEYPAD += test-keys.kl
(2)Android上層添加按鍵
在上面,我們已經完成了按鍵布局文件的添加,接下來將在Android Framework層完成按鍵的添加。
需要注意的是,在實例中,關於POWER和HOME的按鍵,Android系統中默認已經定義了,如果需要添加新的,則需要自己完成定義:
首先需要添加按鍵對應得KeycodeLable,文件:
AOSP/frameworks/native/include/input/InputEventLabels.h
添加內容如下:
static const InputEventLabel KEYCODES[] = {
...
...
DEFINE_KEYCODE(SYSTEM_NAVIGATION_LEFT),
DEFINE_KEYCODE(SYSTEM_NAVIGATION_RIGHT),
{ NULL, 0 } };
接下來,進行鍵碼定義,在文件:
AOSP/frameworks/native/include/android/keycodes.h
添加內容如下:
enum {
...
... /** fingerprint navigation key, left. */ AKEYCODE_SYSTEM_NAVIGATION_LEFT = 282, /** fingerprint navigation key, right. */ AKEYCODE_SYSTEM_NAVIGATION_RIGHT = 283 };
還需要修改java定義,在文件:
AOSP/frameworks/base/core/java/android/view/KeyEvent.java
添加內容如下:
public class KeyEvent extends InputEvent implements Parcelable { ... ... ... /** Key code constant: Consumed by the system for navigation left*/ public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; /** Key code constant: Consumed by the system for navigation right */ public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;
private static final int LAST_KEYCODE = KEYCODE_SYSTEM_NAVIGATION_RIGHT; ... ... ... }
需要注意的是,該文件的鍵碼必須與前面定義的一致。
接下來修改資源文件:
AOSP/frameworks/base/core/res/res/values/attrs.xml
到這里,Android系統添加新鍵值就完成了,接下來進行按鍵測試。
4、按鍵測試
將系統重新編譯,並且將新的鏡像進行燒寫,使用下面命令查看,新的按鍵與布局文件:
# dumpsys input
輸出如下:
從打印的結果來看,已經匹配上對應得keylayout文件,在上面的添加實例為POWER相應的鍵值,當按鍵被觸發后,Android終端的屏幕將會被點亮,測試完成。