处理流程及示意图:

1,硬件配置:

kernel-3.18\arch\arm\boot\dts\projectxxx.dts

&keypad {

mediatek,kpd-key-debounce= <1024>;

mediatek,kpd-sw-pwrkey= <116>;

mediatek,kpd-hw-pwrkey= <8>;

mediatek,kpd-use-extend-type= <0>;

/*HWKeycode [0~71] -> Linux Keycode*/

mediatek,kpd-hw-map-num= <72>;

// kpd-hw-init-map为硬件扫描的矩阵列表。跟具体硬件接法相关。即为linux_code

mediatek,kpd-hw-init-map= <115 114 0 0 0 0 0 0 0 158 0 0 0 0 0 0 0 0 0 0 0 0 0 0

00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >;

mediatek,kpd-pwrkey-eint-gpio= <0>;

mediatek,kpd-pwkey-gpio-din  = <0>;

mediatek,kpd-hw-dl-key0= <0>;

mediatek,kpd-hw-dl-key1= <1>;

mediatek,kpd-hw-dl-key2= <8>;

mediatek,kpd-hw-recovery-key= <0>;

mediatek,kpd-hw-factory-key  = <1>;

status= "okay";

};

硬件接法,软件注意各个IO的功能配置,以确保按键扫描时获取到正确的值。

2,kernel驱动:

按下按键后,会出发中断,然后进去中断处理程序中进行按键的扫描:

static void kpd_keymap_handler(unsignedlong data)

{

inti, j;

boolpressed;

u16new_state[KPD_NUM_MEMS], change, mask;

u16hw_keycode, linux_keycode;

kpd_get_keymap_state(new_state);

wake_lock_timeout(&kpd_suspend_lock,HZ / 2);

for(i = 0; i < KPD_NUM_MEMS; i++) {

change= new_state[i] ^ kpd_keymap_state[i];

if(!change)

continue;

for(j = 0; j < 16; j++) {

mask= 1U << j;

if(!(change & mask))

continue;

hw_keycode = (i << 4) + j;//获取到硬件扫描的HW_code值,这个与硬件接法相关。

/*bit is 1: not pressed, 0: pressed */

pressed= !(new_state[i] & mask);

if(kpd_show_hw_keycode)

kpd_print("(%s)HW keycode = %u\n", pressed ? "pressed" : "released",hw_keycode);

BUG_ON(hw_keycode>= KPD_NUM_KEYS);

linux_keycode = kpd_keymap[hw_keycode];//根据对应的hw_coed,按照dts中的对应,映射获取到linux_code.

if(unlikely(linux_keycode == 0)) {

kpd_print("Linuxkeycode = 0\n");

continue;

}

kpd_aee_handler(linux_keycode,pressed);

input_report_key(kpd_input_dev, linux_keycode, pressed);//通过INPUT发送linux_code的input subsystem。

input_sync(kpd_input_dev);

kpd_print("reportLinux keycode = %u\n", linux_keycode);

}

}

memcpy(kpd_keymap_state,new_state, sizeof(new_state));

kpd_print("savenew keymap state\n");

enable_irq(kp_irqnr);

}

3,input 子系统对按键的处理:

具体请参照:input子系统按键处理

adb可以参看proc/bus/input下面的devices和handler。

Devices的key:

I: Bus=0019 Vendor=2454 Product=6500Version=0010

N: Name="mtk-kpd"

P: Phys=

S:Sysfs=/devices/soc/10011000.keypad/input/input1

U: Uniq=

H: Handlers=event1

B: PROP=0

B: EV=3

B: KEY=40000000 1c0000 0 0 0

Hander:

N: Number=0 Name=sysrq (filter)

N: Number=1 Name=evdev Minor=64//这个是我们所用到的

主要是对下面三个结构体进行配置:

Device: input的核心层,主要文件input.c,建立设备节点,对驱动层提供统一的接口。如主要的input_report_key() 就是他提供的。作用我觉得主要是对下形成对硬件,驱动进行接口的统一,对上次配合事件层提供相应的匹配接口。

Handler:event事件层,主要文件evdev.c。主要作用是用户核心层的device相匹配,匹配成功后,然后新建handle。产生事件的节点。并且对上提供读写相关的接口。供上层获取或者写入相应的键值。evdev_read,evdev_write;到这里应该是kernel层的任务就完成了。

Handle:通过handler->connect(),将device与handler匹配连接起来。主要是匹配id。个人觉得只是形成一个简单的综合体,方便对匹配成功的device和handler的访问。

static ssize_t evdev_read(struct file*file, char __user *buffer,

size_t count, loff_t *ppos)

{

structevdev_client *client = file->private_data;

structevdev *evdev = client->evdev;

structinput_event event;

size_tread = 0;

interror;

if(count != 0 && count < input_event_size())

return-EINVAL;

for(;;) {

if(!evdev->exist || client->revoked)

return-ENODEV;

if(client->packet_head == client->tail &&

(file->f_flags & O_NONBLOCK))

return-EAGAIN;

/*

* count == 0 is special - no IO is done but wecheck

* for error conditions (see above).

*/

if(count == 0)

break;

while(read + input_event_size() <= count &&

evdev_fetch_next_event(client,&event)) {

if(input_event_to_user(buffer + read, &event))//将获取到的event信息反馈到用户层

return-EFAULT;

read+= input_event_size();

}

if(read)

break;

if(!(file->f_flags & O_NONBLOCK)) {

error= wait_event_interruptible(evdev->wait,

client->packet_head!= client->tail ||

!evdev->exist|| client->revoked);

if(error)

returnerror;

}

}

returnread;

}

4,inputmanager对按键事件的获取和向上派发:

参照文档:inputmanager对按键事件的获取和向上派发

说明:

调试的时候,可以用adb来进行调试。Input keyevent  26//power key

先大致介绍一下整个流程,再做重点分析。输入事件流程一共涉及到下面这几个文件:

/frameworks/base/services/Java/com/Android/server/WindowManagerService.java

/frameworks/base/services/java/com/android/server/InputManager.java

/frameworks/base/services/jni/com_android_server_InputManager.cpp

/frameworks/base/libs/ui/InputReader.cpp

/frameworks/base/libs/ui/InputDispatcher.cpp

/frameworks/base/libs/ui/EventHub.cpp

其中,WindowManagerService.java和InputManager.java主要向Android为窗口系统提供服务,EventHub.cpp主要用来读取设备文件中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它们之间的对接层。

它们的关系是:WindowManagerService通过InputManager提供的接口开启一个线程驱动InputReader不断地从/dev/input/目录下面的设备文件读取事件,然后通过InputDispatcher分发给连接到WindowManagerService服务的客户端。

InputReader从设备文件中读取的是RawEvent,在交给InputDispatcher进行分发之前,它需要先把RawEvent进行转化分类,拆分成KeyEvent、MotionEvent、TrackEvent各种类型等。这篇文章主要关注的就是这个RawEvent的拆分过程,所以我们的重点在EventHub.cpp中。并且,为了简单化分析过程,在这里我的分析只关注触摸屏事件。看它是如何从RawEvent被拆分成应用层用户事件MotionEvent的。

5,InputDispatcher分发与客户端的接收:

待分析。

android6.0按键处理浅析相关推荐

  1. Android6.0 按键流程(七)无线鼠标右键无效 -- Framework层

    之前我们分析了无线鼠标右键无效,hal层的分析,我们可以把修改成返回键. uint32_t CursorButtonAccumulator::getButtonState() const { uint ...

  2. android6.0源码分析之Camera API2.0下的Preview(预览)流程分析

    1.Camera2 preview的应用层流程分析 preview流程都是从startPreview开始的,所以来看startPreview方法的代码: <code class="hl ...

  3. Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮...

    Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮 前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP) ...

  4. android6.0 framwork修改

    基于android6.0.7.01.20 默认使用Launcher2,修改Launcher2 packages/apps/Launcher3/src/com/android/launcher3/Lau ...

  5. Android6.0动态权限申请及RxPermissions权限库使用

    一.AndroidManifest.xml 所有权限列表: 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据 ...

  6. Android6.0电池图标外显示电量百分比

    众所周知Android6.0进入界面后电池电量百分比被隐藏进了调谐者模式里面,即使打开调谐者模式显示电量数字也在电池图标里,对于某些习惯于5.1电量显示的人来说这是一个很难受的事情,那么这里我来提供一 ...

  7. msm8909 Android6.0杂记

    高通msm8909 Android6.0 笔记(未完) 一 : 添加新板 二 :DDR配置 三 : EMMC && SD card 配置 四: GPIO/I2C/SPI/SDIO/UA ...

  8. android6.0 Activity(一) Activity创建 初始化

     之前在http://blog.csdn.net/kc58236582/article/details/50069785这篇博客中,讲述了一个Activity如何通过AMS启动的.还有http:/ ...

  9. Android6.0的phone应用源码分析(3)——phone 拨号UI分析

    1.1   原生界面 Phone应用的UI设计直接关系到后面的去来电流程,因此有必要对Phone的UI做一定的介绍.下面是Android6.0的原生拨号界面: 1.2   应用界面 Phone的UI入 ...

最新文章

  1. R语言ggplot2可视化将两个dataframe可视化的结果组合在一起实战:combining two plots from different data.frames
  2. [解题报告]Triangle Wave
  3. 微信支付商业版 结算周期_了解商业周期
  4. python调用adb shell命令_Python之使用adb shell命令启动应用的方法详解
  5. Gitee搭建自己的图床
  6. linux查看程序的快捷键,linux操作系统的快捷键及命令讲解
  7. 扩展AD 用户上传头像
  8. 东方通TongWeb启动springboot报错
  9. 十行以内,你写过哪些比较酷的 Matlab 代码?
  10. 在线评判系统java代码_sojV1.0 Online Judge System 在线评判系统是一个 联合开发网 - pudn.com...
  11. CCNP-OSPF中SPF(最短路径树)算法剖析,建树过程示例
  12. .net reflector反编译破解软件
  13. Linux基础-Swap分区
  14. MySQL008:数据库引擎,如何设置引擎独立空间
  15. 咋阻止别人用计算机监控我家,我想用我家里的电脑控制办公室电脑的打印机怎么处理?...
  16. 【平头哥RVB2601开发板试用体验】I/O扩展
  17. python挖矿木马_centos7系统被入侵,挂载挖矿木马-pamdicks-(1)临时处理
  18. 如何将项目代码放到github上
  19. FastDFS分布式文件系统实践详解
  20. linux cacti监控tomcat,Cacti监控Tomcat服务器实现过程

热门文章

  1. 【黑马程序员西安中心】我和传智有个梦!
  2. 以AI为支点NEC欲撬动未来物联网世界
  3. sws_scale图像缩放函数介绍
  4. Power Supply---驱动框架
  5. 显示器3d测试软件,全球首款120Hz 优派3D液晶显示器首测
  6. [附源码]java毕业设计学生互评的在线作业管理系统
  7. 5个简历模板下载及制作网站
  8. Linux:打包压缩
  9. Java反射获取构造方法
  10. 计算机网络(自顶向下)笔记