继上一篇文章,客户提出新的问题,所以这个问题还没有完成。
感觉有些问题,绕还绕不过,必须得找到Root Case,然后再提出解决方案。整理一下这个问题的过程。
1,Issue description
客户提供的蓝牙手柄,进入中文输入法的时候,丧失“确定”和“返回”功能,表现为“按键失灵”
2,What’s the issue
手柄(Joystick)输入设备具有一点的特殊性,按键可复用,可定制。我遇到这个手柄是复用功能,即一个按键启动上报两个键值。
如上图所示,X键具备“DPAD_CENTER”和“BUTTON_X”的功能,同理,B键具备“BACK”和“BUTTON_B”的功能。通过getevent可以看出端倪,如下是一次按键打印
/dev/input/event6: 0004 0004 000900b9
/dev/input/event6: 0004 0004 000900b8
/dev/input/event6: 0004 0004 00090004 //这3个是一个MSC事件,是scan(#define MSC_SCAN 0x04 ),这三个扫描键对应的键值是DPAD_CENTER
/dev/input/event6: 0001 0133 00000001 //这一个KEY类型的事件(#define EV_KEY 0x01 ),键值为BUTTON_X(#define BTN_X 0x133 ),Value为按下
/dev/input/event6: 0000 0000 00000000 //SYNC信号
/dev/input/event6: 0004 0004 000900b9
/dev/input/event6: 0004 0004 000900b8
/dev/input/event6: 0004 0004 00090004
/dev/input/event6: 0001 0133 00000000
/dev/input/event6: 0000 0000 00000000 //对应的是抬起
3,How to Debug
大致是从上到下打开debug观察,正常和异常的时候的对比
input driver->input hub->input read->input dispatch->viewrootimpl.
具体的过程,在《2.4G输入设备按键丢失的问题(1)》有提到。可以知道到viewrootimpl都是正常的。
4,slove it
在上篇中已经提到,最初的方法是绕过问题,通过修改对应的kl文件把两个不同的键值映射成一个功能键,但留下了后患,因为进入某些游戏,需要通过接受BUTTON_X和BUTTON_B来处理一些事,比如,进入商店,进入设置==。
5,slove it again
问题出在应用端,那还是由应用端面来解决。再通过应用程序的打印来观察,是因为某些应用是重写的onKeyDwon/Up事件,如果进来的按键不是需要处理的,那么就直接return ture。这样父类(Activity.java)也没有处理,直接扔掉了。修改了一个应用,大致如下:(其实思路清楚了,修改起来只需要调整一下逻辑,就不详细赘述)
|| keyCode == KeyEvent.KEYCODE_SPACE) {
chooseCandidate(-1);
+ } else if (keyCode == KeyEvent.KEYCODE_BUTTON_X
+ || keyCode == KeyEvent.KEYCODE_BUTTON_B) {
+ return false;
}
6,think more
并不是每个应用都会考虑到这种特殊的Input设备,但总不能每个都这样处理?比如Android自带的Browser也无法很好的处理这种设备,我想是否可以调整两个功能键的顺序。
比如,当按一下X键,设备发出来的是一个SCAN_ENV,对应值为BUTTON_X,然后再是KEY_ENV,对应的是DPAD_CENTER。如果上层的应用先接受到DPAD_CENTER,就不会丢掉有用按键,这个应该可以好好尝试下,在Framework下修改,就避免改所有应用。