概述

按键信息上报是input系统里面一个最基本,最简单,也是最常用的功能.一般直接配置dts即可,但是也有可能有定制需求,比如自定义按键和上报特殊按键.

新增按键

内核已经实现了通用按键驱动,优先建议使用.

gpio_keys: gpio_keys {
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&gpio_keys_sensor>;
#address-cells = <1>;
#size-cells = <0>;
button0 {
label = "Lhead";
linux,code = <0x101>; /*BTN_1*/
debounce-interval = <10>;
gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
};
button1 {
label = "Rhead";
linux,code = <0x102>; /*BTN_2*/
debounce-interval = <10>;
gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
};
};

自定义按键

当前按键定义无法满足的情况下可以 自定义按键.主要修改以下文件:

[kernel]

内核按键定义:kernel/include/uapi/linux/input-event-codes.h 添加按键驱动,上报按键事件:kernel/drivers/input/keyboard/gpio_keys.c(或自己写驱动)

dts添加:kernel/arch/arm64/boot/dts/rockchip(board)/XXXX.dts

[android]

.kl文件添加键值:

frameworks/base/data/keyboards/Generic.kl(通用键值,可自定义kl文件) frameworks/base/data/keyboards/qwerty.kl 键值映射:

frameworks/native/include/input/InputEventLabels.h frameworks/native/include/android/keycodes.h frameworks/base/core/java/android/view/KeyEvent.java frameworks/base/core/res/res/values/attrs.xml

[系统目录]

/system/usr/keylayout/Generic.kl

[handle] 按键处理:可以增加响应处理逻辑 frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

特殊按键上报

对于HOME,POWR等特殊按键,apk正常是无法监听到的,但是也有方法:

对于9.0以下:

android.intent.action.ACTION_CLOSE_SYSTEM_DIALOGS

对于9.0以上:

filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);

也可以修改PhoneWindowManager.java中对应的处理逻辑:

@@ -6111,12 +6111,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {

}
- result &= ~ACTION_PASS_TO_USER;
+ result |= ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {

这样apk就可以监听到power按键了,其他特殊按键类似.

常见问题

按键误触发

如果按键配置为BTN_0~9,那么在按按键的时候,会导致页面按钮响应,处理按键事件.比如在拍照界面,BTN会被处理为按下拍照.这通常不是我们所希望的.

有两种修改方式:

方式一:

修改linux,code,对应其他未使用,且对activity无影响的code值.

方法二:

修改frameworks/base/data/keyboards/Generic.kl中的映射,重映射到其他code.

后台应用无法监听

对于power或其他按键,后台应用是无法监听的,此时可以采用广播的方式:

mContext.sendBroadcast(new Intent("com.xxx.keycode.power"));

这样所有注册了对应广播的apk都可以监听到了.

每次按键都有两次上报

每个按键都会上报两次(up,down),但是对于特殊按键(power等),使用上面的方法会广播两次,但是无法分辨up和dow,所以需要进一步改进

@@ -6111,12 +6111,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException e) {

}
- result &= ~ACTION_PASS_TO_USER;
+ result |= ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
+ mContext.sendBroadcast(new Intent("com.xxx.keycode.power.down"));
} else {
interceptPowerKeyUp(event, interactive, canceled);
+ mContext.sendBroadcast(new Intent("com.xxx.keycode.power.up"));
}
break;
}

这样就可以区分up和down了.

按键无触发或一直触发

对于高有效的按键(具有按键功能的设备):

如果默认上拉:会一直触发.

如果默认下拉:会几乎无法触发,或者非常难触发.

建议采用pcfg_pull_none.

rockchip,pins =
<1 18 RK_FUNC_GPIO &pcfg_pull_none>, //GPIO1_C2
<1 20 RK_FUNC_GPIO &pcfg_pull_none>; //GPIO1_C4
};