最近在Amlogic方案的定制化android软件上,做了添加按键的驱动工作,也熟悉了按键的基本流程,现在把核心步骤给总结如下:

1.基本流程:

./表示android源代码目录,按键属于输入设备,支持5种输入设备:触摸屏  GPIOkey  usb键盘  usb鼠标  powerkey。
android按键消息通过二次转换:将驱动report上来的SCANCODE(include/linux/input.h中),通过文件*.kl(默认为qwerty.kl)的映射,得到KEYCODE字串;通过二维表static const KeycodeLabel KEYCODES[],将上面的字符串转换成android 需要的键值信息(frameworks\base\libs\ui中的KeyLayoutMap.cpp)。如果是输入键,还需要查询keymap,得到相应的字符。

KEYLAYOUT 按键布局
文件:*.kl(默认为qwerty.kl)
文件格式:
key SCANCODE KEYCODE [FLAGS...]
第一列:key
第二列: SCANCODE是一个整数,是驱动里面定义的,在文件./kernel/include/linux/input.h
第三列: KEYCODE 是一个字串,定义在你描述的布局文件frameworks/base/include/ui/KeycodeLabels.h
另外可以设置相关的FLAGS:
SHIFT: 当按下,自动加上SHIFT键值
ALT:当按下,自动加上ALT
CAPS:当按下,自动带上CAPS大写
WAKE:当按下,当设备进入睡眠的时候,按下这个键将唤醒,而且发送消息给应用层。
WAKE_DROPPED:当按下,且设备正处于睡眠,设备被唤醒,但是不发送消息给应用层。
      接下来自下而上说明:

*驱动程序:./kernel/drivers/**/input(/saradc为例)目录。负责report键值到上层,其中键值定义在input.h中;驱动程序中会定义Device->name,如IR定义的设备名称为aml_keypad,它决定了根文件系统的按键布局或按键字符映射;获取设备名字:函数为int EventHub::pen_device(const char *deviceName),打开键盘设备的时候通过上面的 ioctl 获得设备名称,命令字 EVIOCGNAME 的定义在文件: kernel/include/linux/input.h 中。 #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */。

*根文件系统中:KeyLayout(按键布局)和KeyCharacterMap(按键字符映射),后缀名称分别为kl和kcm;如果使用USB键盘,则使用/system/usr/keylayout/qwerty.kl,定制系统一般放在./device/usr/keylayout/qwerty.kl目录下,如Amlogic使用SAR口做按键,则使用./device/**/adc_keypad.kl,IR按键,则使用./device/**/aml_keypad.kl;获取此文件方法:函数为int EventHub::openDevice(const char *deviceName){

....

const char* root = getenv("ANDROID_ROOT");
        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                 "%s/usr/keylayout/%s.kl", root, tmpfn);
        bool defaultKeymap = false;
        if (access(keylayoutFilename, R_OK)) {
            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                     "%s/usr/keylayout/%s", root, "qwerty.kl");
            defaultKeymap = true;
        }

....

}

如果没有定义键盘映射文件,那么默认使用系统的 /system/usr/keylayout/qwerty.kl 可以修改./system/usr/keylayout/qwerty.kl 文件改变Android公司的按键映射,定制系统一般放在./device/**/keylayout/qwerty.kl。

*EventHub: libui的一部分,实现了对驱动程序的控制。目录 ./frameworks/base/libs/ui/,读取RawEvent事件。

*Java框架层的处理:有KeyInputDevice等类来处理EventHub传递上来的信息,这些信息通过RawInputEvent和KeyEvent来表示。一般情况下,对于按键事件,以后者的形式传送给应用程序,而触摸屏和轨迹球事件以前者的形式转换形成MotionEvent事件传送给应用程序;

*Android应用程序层:通过重载onKeyDown()和onkeyUp()等方法接收KeyEvent(按键事件),通过重载onTouchEvent()和onTrackballEvent()等方法接收MotionEvent(运动事件);

*总之:驱动事件值--->key值(如KEY_STOP在./kernel/include/linux/input.h)--->KEYCODElable名称值(如MEDIA_STOP在./frameworks/base/include/ui/KeycodeLabels.h)--->KEYCODE值(如KEYCODE_MEDIA_STOP在./frameworks/base/core/java/android/view/KeyEvent.java)--->onKeyDown()或onkeyUp()功能处理。

2.按键功能修改:

从上面总之的流程中可知,修改按键做法比较简单,只要每个key的按键功能正常的话,只需更换驱动事件对应的key值,故我们先检查整个流程是否打通,打通的话就是改两端而已,要么在onKeyDown()或onkeyUp()上加功能而已。

3.按键功能添加:

对keypad来说,以SAR为例涉及到的有以下几个:
        1.首先在*.kl文件中,添加新的键值信息:Example: key   100    MEDIA_PLAY_PAUSE ,把100定义到input.h中#define KEY_PLAYPAUSE 100

注意:新加的键值不要与已有的重复。
        2.  ./kernel/drivers/**/input/Adc_keypad.c驱动对应的board-8726m-refc03.c中的
              adc_kp_key[]对应的键位添加自定义的键码  如 :{KEY_PLAYPAUSE ,    "playpause", CHAN_5, 419, 60},
       3.   ./frameworks/base/include/ui/keycodeLabels.h
           在数组static const KeycodeLabel KEYCODES[] 中添加 新定义的信息
                { "PLAYPAUSE", 120 },

4.   ./ frameworks/base/native/include/android/Keycodes.h

枚举类型 中添加
                    AKEYCODE_PLAYPAUSE = 120

5.  ./frameworks/base/core/res/res/values/attrs.xml
                <enum name="KEYCODE_BUTTON_PLAYPAUSE"  value="120"/>

6.   ./frameworks/base/core/java/android/view/KeyEvent.java
              public static final int KEYCODE_PLAYPAUSE         = 120;
              注意:要修改为    private static final int LAST_KEYCODE           = KEYCODE_PLAYPAUSE;
                            
        7.   ./frameworks/base/libs/ui/input.cpp

在bool KeyEvent::isSystemKey(int32_t keyCode)()中,同样需要添加:
                 case AKEYCODE_PLAYPAUSE:

8.   通过以上的更改,新的键值就添加上去了,注意上面标红色的数字表示必须相同的,另外由于更改了 KeyEvent,影响到了API, 所以需要make update-api
            
            如果对新键值进行处理,可以通过获取相应的keycode,对它进行处理;对于按键事件的处理一般如下文件中
 frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java,综上可知,我们可以根据需求定义自己的键值,并对键值所对应的事件信息进行合理化处理。

补充:  在写程序时,需要捕获KEYCODE_HOME、KEYCODE_ENDCALL、KEYCODE_POWER这几个按键,但是这几个按键系统做了特殊处理,在进行dispatch之前做了一些操作,HOME除了Keygaurd之外,不分发给任何其他APP,ENDCALL和POWER也类似,应用程序在View和Activity的onKeyDown/Up中是监听不到的,所以需要我们系统处理之前进行处理,我的做法是自己定义一个FLAG,在自己的程序中添加此FLAG,然后在WindowManagerServices.java中获取当前窗口的FLAG属性,如果是我们自己设置的那个FLAG,则不进行特殊处理,直接分发按键消息到我们的APP当中,由APP自己处理。这部分代码最好添加在

@Override

boolean preprocessEvent(InputDevice device, RawInputEvent event)方法中,这个方法是KeyInputQueue中的一个虚函数,在处理按键事件之前的一个“预处理”。

注意:对HOME键的处理好像必需要修改PhoneWindowManager.java中的interceptKeyTi方法,具体可以参考对KeyGuard程序的处理。

4.参考资料下载地址:http://download.csdn.net/detail/acm2008/3913716

5.相关兄弟文章

(1)Android按键消息传播流程(WindowManagerService.java)

(2)Android输入事件流程

(3)Android中Key Event流程

(4)android:添加usb键盘+按键布局和映射的修改

android定制化软件修改或添加按键驱动的核心操作步骤讲解相关推荐

  1. linux修改ssh登陆端口号,Linux 6 修改ssh默认远程端口号的操作步骤

    linux 默认的ssh远程端口是22,有时默认端口会遭到别有用心的人们扫描或攻击,为了时我们的系统更加安全那就需要修改远程端口号 操作步骤: 1.修改ssh_config配置文件 vim /etc/ ...

  2. iis端口号 linux,Linux 6 修改ssh默认远程端口号的操作步骤

    linux 默认的ssh远程端口是22,有时默认端口会遭到别有用心的人们扫描或攻击,为了时我们的系统更加安全那就需要修改远程端口号 操作步骤: 1.修改ssh_config配置文件vim /etc/s ...

  3. RK3326 8.1系统定制化通用修改

    目录 一.修改默认中文 二.修改默认时区 三.修改永不息屏 四.修改最大音量级别和默认音量级别 五.隐藏顶部状态栏电量图标 六.修改开机logo 七.修改开机动画 八.user/userdebug版本 ...

  4. tems测试软件怎么统计指标,TEMS测试数据计算公式和统计操作步骤(6页)-原创力文档...

    TEMS路测分析 一.统计公式和专业术语 路测数据统计计算公式: 采样点覆盖率(信号电平覆盖率): (RxLev>=-94的采样点)/(总采样点数)×100%:其中RxLev通话时候取RxLev ...

  5. Android studio3.6 加载系统内置矢量图标icon的操作步骤

    用Android studio开发过程中,不可避免要用到很多图标,其中最常用的是xml格式的矢量图标,那么这些图标是怎么做出来的呢,两种方法:第一,使用AS系统内部嵌入的图标:第二,使用网上第三方所做 ...

  6. 无线网密码怎么改服务器停用,无线网怎么修改密码?更改无线网密码的操作步骤...

    无线网络无处不在,只要连上无线,就可以畅享网络世界.在我们享受无线带来的方便时,同样也担心被他人蹭网,因此最好的办法就是定期的修改无线网密码.那么无线网要怎么修改密码呢?操作方法其实很简单,下面我们一 ...

  7. 实现手机来电铃声,通知铃声、警告铃声等音频定制化功能(一,添加扫描分区myimage)

    需求功能说明: 该定制需求在各个国家民族差异化为背景下产生的,要求在系统中增加一个新的分区如myimage,用以实现存放定制资源,以符合不同国家民族的用户的体验.例如在myimage下新建media文 ...

  8. Android定制化自己的开锁界面

    android 在4.0以前,解锁界面是采用横滑的方式,在4.0之后,就采用了中心圆环的解锁方式,4.0和4.1都是有三个图标的,分别是:向上的google搜索应用,向左的拍照应用以及向右的正常解锁功 ...

  9. STM32工程添加模块、代码移植操作步骤

    1.直接复制粘贴第一个新建的工程,然后改名 2.在工程里新建一个WokePace文件用来放其他模块文件 3.去别的工程直接把想要的模块复制到该文件夹下,每个模块都有一个main.c和main.h,也可 ...

最新文章

  1. LLVM编译器基础架构与DragonEgg示例
  2. 四因素三水平正交试验表_案例 | 螺栓装配失效试验研究
  3. java可以编写蠕虫病毒吗,暴力蠕虫来袭!网友们直呼:惊不惊喜,意不意外,怕不怕!...
  4. 鲜活数据数据可视化指南_数据可视化实用指南
  5. 前端学习(926):淘宝flexiblejs源码分析之核心原理
  6. Java-数据结构与算法-二分查找法
  7. MyBatis课程5
  8. 带你学习javascript的函数进阶(二)
  9. 电脑端用起来特别爽的四款软件,哪一款才是你的最爱?
  10. Zabbix实现微信报警
  11. ubuntu最好用的划词翻译词典:有道词典和GoldenDict
  12. 四川创峄信息科技有限公司企业公章管理
  13. Java之~~包(package)
  14. 致那些徘徊在测试界的屌丝
  15. Trinity的安装与使用
  16. php twig中文手册,安装 · Twig 中文文档 · 看云
  17. “钱三篇”后续之汇率(上)
  18. 【原创】Quartus II 简单设计流程
  19. WebRTC的音频编码(转)
  20. 开发一款外卖App应该具备哪些功能?

热门文章

  1. CF631C 单调栈
  2. 学习篇(一)- Spring自动装配的方式
  3. 微信聊天记录导出小试
  4. CES2018前瞻:在未来 我们需要关注这些领域
  5. 云台山走出来的慈善家——李亮先生
  6. day18总结和作业
  7. 阿里技术分享:电商IM消息平台,在群聊、直播场景下的技术实践
  8. QWebEngineView QWebEngineDownloadItem 下载网页资源
  9. 中国人民大学信息学院79级同学聚会感言
  10. 2017年软件测试就业前景趋势