android6.0按键处理浅析
处理流程及示意图:
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按键处理浅析相关推荐
- Android6.0 按键流程(七)无线鼠标右键无效 -- Framework层
之前我们分析了无线鼠标右键无效,hal层的分析,我们可以把修改成返回键. uint32_t CursorButtonAccumulator::getButtonState() const { uint ...
- android6.0源码分析之Camera API2.0下的Preview(预览)流程分析
1.Camera2 preview的应用层流程分析 preview流程都是从startPreview开始的,所以来看startPreview方法的代码: <code class="hl ...
- Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮...
Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮 前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP) ...
- android6.0 framwork修改
基于android6.0.7.01.20 默认使用Launcher2,修改Launcher2 packages/apps/Launcher3/src/com/android/launcher3/Lau ...
- Android6.0动态权限申请及RxPermissions权限库使用
一.AndroidManifest.xml 所有权限列表: 访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据 ...
- Android6.0电池图标外显示电量百分比
众所周知Android6.0进入界面后电池电量百分比被隐藏进了调谐者模式里面,即使打开调谐者模式显示电量数字也在电池图标里,对于某些习惯于5.1电量显示的人来说这是一个很难受的事情,那么这里我来提供一 ...
- msm8909 Android6.0杂记
高通msm8909 Android6.0 笔记(未完) 一 : 添加新板 二 :DDR配置 三 : EMMC && SD card 配置 四: GPIO/I2C/SPI/SDIO/UA ...
- android6.0 Activity(一) Activity创建 初始化
之前在http://blog.csdn.net/kc58236582/article/details/50069785这篇博客中,讲述了一个Activity如何通过AMS启动的.还有http:/ ...
- Android6.0的phone应用源码分析(3)——phone 拨号UI分析
1.1 原生界面 Phone应用的UI设计直接关系到后面的去来电流程,因此有必要对Phone的UI做一定的介绍.下面是Android6.0的原生拨号界面: 1.2 应用界面 Phone的UI入 ...
最新文章
- R语言ggplot2可视化将两个dataframe可视化的结果组合在一起实战:combining two plots from different data.frames
- [解题报告]Triangle Wave
- 微信支付商业版 结算周期_了解商业周期
- python调用adb shell命令_Python之使用adb shell命令启动应用的方法详解
- Gitee搭建自己的图床
- linux查看程序的快捷键,linux操作系统的快捷键及命令讲解
- 扩展AD 用户上传头像
- 东方通TongWeb启动springboot报错
- 十行以内,你写过哪些比较酷的 Matlab 代码?
- 在线评判系统java代码_sojV1.0 Online Judge System
在线评判系统是一个 联合开发网 - pudn.com...
- CCNP-OSPF中SPF(最短路径树)算法剖析,建树过程示例
- .net reflector反编译破解软件
- Linux基础-Swap分区
- MySQL008:数据库引擎,如何设置引擎独立空间
- 咋阻止别人用计算机监控我家,我想用我家里的电脑控制办公室电脑的打印机怎么处理?...
- 【平头哥RVB2601开发板试用体验】I/O扩展
- python挖矿木马_centos7系统被入侵,挂载挖矿木马-pamdicks-(1)临时处理
- 如何将项目代码放到github上
- FastDFS分布式文件系统实践详解
- linux cacti监控tomcat,Cacti监控Tomcat服务器实现过程