Android tp的虚拟按键(virtual key)处理
Android tp的虚拟按键处理
现在在越来越多的Android的手机都是虚拟按键来操作,但是对于开发者来说可能会关心Android对虚拟按键如何处理的。对Linux熟悉的人可能会说,it's easy, 调用input_report_key()。OK,你说的没有错误,但是在android中,google让你对策略和驱动有了更加深入的了解。
APP------->
Framework------->
Kernel------->
Hardware
上面就是整个Android的Virtual key的整个的框图。
由于是搞驱动的,所以这里先从驱动开始说起。
其实说起对virtual key的处理对于驱动来说没有任何的难处,实现了Touch panel驱动,你也就将virtual key的底层驱动实现了。这里你试验了吗?你可能会说,“不行,这里实现不了”。是的,这个时候还不行,还有关键的步骤得操作。
在这里,你需要如下代码加入才可以。
- static unsigned int tpd_keycnt = 0;
- static int tpd_keys[TPD_VIRTUAL_KEY_MAX]={0};
- static int tpd_keys_dim[TPD_VIRTUAL_KEY_MAX][4];// = {0};
- static ssize_t cust_virtual_keys_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf) {
- int i, j;
- for(i=0, j=0;i<tpd_keycnt;i++)
- j+=sprintf(buf, "%s%s:%d:%d:%d:%d:%d%s",buf,
- __stringify(EV_KEY),tpd_keys[i],
- tpd_keys_dim[i][0],tpd_keys_dim[i][1],
- tpd_keys_dim[i][2],tpd_keys_dim[i][3],
- (i==tpd_keycnt-1?"\n":":"));
- return j;
- }
- static struct kobj_attribute cust_virtual_keys_attr = {
- .attr = {
- .name = "virtualkeys.cust-tpd",
- .mode = S_IRUGO,
- },
- .show = &cust_virtual_keys_show,
- };
- static struct attribute *cust_properties_attrs[] = {
- &cust_virtual_keys_attr.attr,
- NULL
- };
- static struct attribute_group cust_properties_attr_group = {
- .attrs = cust_properties_attrs,
- };
- struct kobject *properties_kobj;
- void tpd_button_init(void) {
- int ret = 0, i = 0, j=0;
- tpd->kpd=input_allocate_device();
- /* struct input_dev kpd initialization and registration */
- tpd->kpd->name = TPD_DEVICE "-kpd";
- set_bit(EV_KEY, tpd->kpd->evbit);
- for(i=0;i<tpd_keycnt;i++)
- __set_bit(tpd_keys[i], tpd->kpd->keybit);
- tpd->kpd->id.bustype = BUS_HOST;
- tpd->kpd->id.vendor = 0x0001;
- tpd->kpd->id.product = 0x0001;
- tpd->kpd->id.version = 0x0100;
- if(input_register_device(tpd->kpd))
- TPD_DMESG("input_register_device failed.(kpd)\n");
- set_bit(EV_KEY, tpd->dev->evbit);
- for(i=0;i<tpd_keycnt;i++)
- __set_bit(tpd_keys[i], tpd->dev->keybit);
- properties_kobj = kobject_create_and_add("board_properties", NULL);
- if(properties_kobj)
- ret = sysfs_create_group(properties_kobj,&cust_properties_attr_group);
- if(!properties_kobj || ret)
- printk("failed to create board_properties\n");
- }
- void tpd_button_setting(int keycnt, void *keys, void *keys_dim)
- {
- tpd_keycnt = keycnt;
- memcpy(tpd_keys, keys, keycnt*4);
- memcpy(tpd_keys_dim, keys_dim, keycnt*4*4);
- }
有了上面的代码,我们的virtual key才可以使用,这里主要是需要注册/sys/board_properties/virtualkeys.cust-tpd。这个是framework需要的文件节点。他的出现可以使我们的虚拟按键畅通无阻了。
当然,在这里tpd_keys这个定义key的数组和定义区域的tpd_keys_dim要准确的填充才可以的。具体的填充的规则如下:
每一个虚拟按键有六个参数:
- 0x01: A version code. Must always be 0x01.
- <Linux key code>: The Linux key code of the virtual key.
- <centerX>: The X pixel coordinate of the center of the virtual key.
- <centerY>: The Y pixel coordinate of the center of the virtual key.
- <width>: The width of the virtual key in pixels.
- <height>: The height of the virtual key in pixels.
- 对比我的milestone来看看:
- 0x01:158:32:906:63:57:
- 0x01:139:162:906:89:57:
- 0x01:102:292:906:89:57:
- 0x01:217:439:906:63:57
则可以看出定义了有back,menu,home,search,具体的区域也一清二楚了。
下面就是framework中的处理了,文件在framework/base/services/java/com/android/server/InputManager.java。
在其中通过调用getVirtualKeyDefinitions来获得定义的虚拟按键。
- public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {
- ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();
- try {
- FileInputStream fis = new FileInputStream(
- "/sys/board_properties/virtualkeys." + deviceName);
- InputStreamReader isr = new InputStreamReader(fis);
- BufferedReader br = new BufferedReader(isr, 2048);
- String str = br.readLine();
- if (str != null) {
- String[] it = str.split(":");
- if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);
- final int N = it.length-6;
- for (int i=0; i<=N; i+=6) {
- if (!"0x01".equals(it[i])) {
- Slog.w(TAG, "Unknown virtual key type at elem #"
- + i + ": " + it[i] + " for device " + deviceName);
- continue;
- }
- try {
- VirtualKeyDefinition key = new VirtualKeyDefinition();
- key.scanCode = Integer.parseInt(it[i+1]);
- key.centerX = Integer.parseInt(it[i+2]);
- key.centerY = Integer.parseInt(it[i+3]);
- key.width = Integer.parseInt(it[i+4]);
- key.height = Integer.parseInt(it[i+5]);
- if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "
- + key.scanCode + ": center=" + key.centerX + ","
- + key.centerY + " size=" + key.width + "x"
- + key.height);
- keys.add(key);
- } catch (NumberFormatException e) {
- Slog.w(TAG, "Bad number in virtual key definition at region "
- + i + " in: " + str + " for device " + deviceName, e);
- }
- }
- }
- br.close();
- } catch (FileNotFoundException e) {
- Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
- } catch (IOException e) {
- Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
- }
- return keys.toArray(new VirtualKeyDefinition[keys.size()]);
- }
其实找这个函数的调用的话,其实是发现通过JNI com_android_server_InputManager.cpp,InputReader.cpp来调用的。
最终通过notifyKey()来将key事件上报给app来处理。
在这其中还需要配置:
Key layout file: /system/usr/keylayout/touchyfeely.kl.
key 158 BACK
key 139 MENU
key 102 HOME
key 217 SEARCH
Key character map file: /system/usr/keychars/touchyfeely.kcm.
type SPECIAL_FUNCTION
其实这个例子给我的最大的感受是让我更加的了解了什么是策略,什么是机制,一定要区分清楚。读源码可以让自己的想法也会有些转变的。
Have Fun!
补充资料:
http://source.android.com/tech/input/touch-devices.html#virtual-key-map-files
http://source.android.com/tech/input/validate-keymaps.html
Android tp的虚拟按键(virtual key)处理的更多相关文章
- 隐藏Android下的虚拟按键
要隐藏Android下的虚拟按键,可通过如下办法操作 adb root adb remount adb shell ls -al /system/build.prop (查看文件权限) -rw-r ...
- android监听虚拟按键的显示与隐藏【转】
本文转载自:http://blog.csdn.net/u014583590/article/details/55263141 虚拟按键在华为手机中大量存在,而虚拟按键的存在无疑增加了屏幕适配的难度,往 ...
- Android适配底部虚拟按键的方法
---恢复内容开始--- 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近项目进行适配的时候发现部分(如华为手机)存在底部虚拟按键的手机会因为虚拟按键的存在导致挡住部分界面,因为需要全屏显示 ...
- Android隐藏虚拟按键,关闭开机动画、开机声音
/*********************************************************************** * Android隐藏虚拟按键,关闭开机动画.开机声音 ...
- Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高
一.屏幕中各种栏目以及屏幕的尺寸 当我们需要计算屏幕中一些元素的高度时,或许需要先获取到屏幕或者各种栏目的高度,下面这个类包含了Status bar状态栏,Navigation bar虚拟按键栏,Ac ...
- android 虚拟按键是通过哪种机制上报的?
1.在normal mode下,tp button也是和其他触摸事件一样,以坐标形式的input_event进行上报.在初始化时会通过tpd_button_setting()函数依据定义在tpd_cu ...
- 关于Android适配华为等带有底部虚拟按键的解决方案
http://blog.csdn.NET/a91694451/article/details/50469857 最近公司的项目里遇到了一个问题,就是最后适配的时候时候同事的华为手机时,由于底部带有虚拟 ...
- 【Android】隐藏底部虚拟按键
Google的官方文档是: https://developer.android.com/training/system-ui/navigation.html#behind 示例代码 1 View de ...
- android适配pad和部分手机底部虚拟按键+沉浸式状态栏
在使用沉浸式状态栏设置界面全屏时发现pad和部分手机(华为和魅族系统自带)屏幕底部会带有虚拟按键,遮挡住界面本身的一部分. 为了设置隐藏,在网上找了一些方法,设置Activity主题再在布局加fits ...
随机推荐
- Windows 下 Django/python 开发环境配置
1.安装 Aptana/Eclipse Aptana是在eclipse上二次开发的一个开源的集成开发环境,内置python编译器 http://www.aptana.com/ 2. 安装python ...
- SQL Server创建LinkServer
USE [master] GO /****** Object: LinkedServer [xxx_LNK] Script Date: 2014/7/7 17:04:13 ******/ EXEC m ...
- wxpython 中的所有控件及高级应用
转自http://xoomer.virgilio.it/infinity77/Phoenix/lib.agw.html,,,哈哈终于找到了这块的内容,书上基本没有讲解 This is the Adva ...
- 任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0。
题目:任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0. 解法一:暴力求解.从1开始查找M,然后判断M*N=X这个数字是否只含有0,1. 解法二:由 ...
- ProductHunt:创业公司产品猎场和秀场
Product模式介绍 ProductHunt(站点www.producthunt.com)是一个国外新出现的创业公司产品展示和交流平台, 顾名思义.对于创业者而言这里是一个秀场,而对于投资人而言这里 ...
- .net通用权限框架B/S (四)--DAL数据层以及数据接口
数据层以及数据接口设计如下图(以g_orga组织机构和g_role角色)为例,这几个类可以通过.tt模版生成 设计参考学习http://www.cnblogs.com/hanyinglong/arch ...
- spring加载jar包中多个配置文件
转自:http://www.cnblogs.com/GarfieldTom/p/3723915.html <import resource="classpath*:applicatio ...
- Oracle的用户管理,授权及备份
一.用户进行授权的操作 创建用户:刚刚创建的用户并没有任何权限 CREATE USER 用户名 indentife BY 密码 授权: GRANT 权限1,权限2... TO 用户权限有:CREAT ...
- Hadoop Eclipse远程连接出现:Error:Call to /10.10.10.10:9000 failed on local exception: java.io.EOFException
异常截图:
- EC读书笔记系列之11:条款20、21
条款20 宁以pass-by-reference-to-const替换pass-by-value 记住: ★尽量以pass-by-reference-to-const替换pass-by-value.前 ...