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的底层驱动实现了。这里你试验了吗?你可能会说,“不行,这里实现不了”。是的,这个时候还不行,还有关键的步骤得操作。

在这里,你需要如下代码加入才可以。

[cpp] 
view plain
copy

 

  1. static unsigned int tpd_keycnt = 0;
  2. static int tpd_keys[TPD_VIRTUAL_KEY_MAX]={0};
  3. static int tpd_keys_dim[TPD_VIRTUAL_KEY_MAX][4];// = {0};
  4. static ssize_t cust_virtual_keys_show(struct kobject *kobj,
  5. struct kobj_attribute *attr, char *buf) {
  6. int i, j;
  7. for(i=0, j=0;i<tpd_keycnt;i++)
  8. j+=sprintf(buf, "%s%s:%d:%d:%d:%d:%d%s",buf,
  9. __stringify(EV_KEY),tpd_keys[i],
  10. tpd_keys_dim[i][0],tpd_keys_dim[i][1],
  11. tpd_keys_dim[i][2],tpd_keys_dim[i][3],
  12. (i==tpd_keycnt-1?"\n":":"));
  13. return j;
  14. }
  15. static struct kobj_attribute cust_virtual_keys_attr = {
  16. .attr = {
  17. .name = "virtualkeys.cust-tpd",
  18. .mode = S_IRUGO,
  19. },
  20. .show = &cust_virtual_keys_show,
  21. };
  22. static struct attribute *cust_properties_attrs[] = {
  23. &cust_virtual_keys_attr.attr,
  24. NULL
  25. };
  26. static struct attribute_group cust_properties_attr_group = {
  27. .attrs = cust_properties_attrs,
  28. };
  29. struct kobject *properties_kobj;
  30. void tpd_button_init(void) {
  31. int ret = 0, i = 0, j=0;
  32. tpd->kpd=input_allocate_device();
  33. /* struct input_dev kpd initialization and registration */
  34. tpd->kpd->name = TPD_DEVICE "-kpd";
  35. set_bit(EV_KEY, tpd->kpd->evbit);
  36. for(i=0;i<tpd_keycnt;i++)
  37. __set_bit(tpd_keys[i], tpd->kpd->keybit);
  38. tpd->kpd->id.bustype = BUS_HOST;
  39. tpd->kpd->id.vendor  = 0x0001;
  40. tpd->kpd->id.product = 0x0001;
  41. tpd->kpd->id.version = 0x0100;
  42. if(input_register_device(tpd->kpd))
  43. TPD_DMESG("input_register_device failed.(kpd)\n");
  44. set_bit(EV_KEY, tpd->dev->evbit);
  45. for(i=0;i<tpd_keycnt;i++)
  46. __set_bit(tpd_keys[i], tpd->dev->keybit);
  47. properties_kobj = kobject_create_and_add("board_properties", NULL);
  48. if(properties_kobj)
  49. ret = sysfs_create_group(properties_kobj,&cust_properties_attr_group);
  50. if(!properties_kobj || ret)
  51. printk("failed to create board_properties\n");
  52. }
  53. void tpd_button_setting(int keycnt, void *keys, void *keys_dim)
  54. {
  55. tpd_keycnt = keycnt;
  56. memcpy(tpd_keys, keys, keycnt*4);
  57. memcpy(tpd_keys_dim, keys_dim, keycnt*4*4);
  58. }

有了上面的代码,我们的virtual key才可以使用,这里主要是需要注册/sys/board_properties/virtualkeys.cust-tpd。这个是framework需要的文件节点。他的出现可以使我们的虚拟按键畅通无阻了。


当然,在这里tpd_keys这个定义key的数组和定义区域的tpd_keys_dim要准确的填充才可以的。具体的填充的规则如下:


每一个虚拟按键有六个参数:

[cpp] 
view plain
copy

 

  1. 0x01: A version code. Must always be 0x01.
  2. <Linux key code>: The Linux key code of the virtual key.
  3. <centerX>: The X pixel coordinate of the center of the virtual key.
  4. <centerY>: The Y pixel coordinate of the center of the virtual key.
  5. <width>: The width of the virtual key in pixels.
  6. <height>: The height of the virtual key in pixels.
  7. 对比我的milestone来看看:
  8. 0x01:158:32:906:63:57:
  9. 0x01:139:162:906:89:57:
  10. 0x01:102:292:906:89:57:
  11. 0x01:217:439:906:63:57

则可以看出定义了有back,menu,home,search,具体的区域也一清二楚了。

下面就是framework中的处理了,文件在framework/base/services/java/com/android/server/InputManager.java。


在其中通过调用getVirtualKeyDefinitions来获得定义的虚拟按键。

[java] 
view plain
copy

 

  1. public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {
  2. ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();
  3. try {
  4. FileInputStream fis = new FileInputStream(
  5. "/sys/board_properties/virtualkeys." + deviceName);
  6. InputStreamReader isr = new InputStreamReader(fis);
  7. BufferedReader br = new BufferedReader(isr, 2048);
  8. String str = br.readLine();
  9. if (str != null) {
  10. String[] it = str.split(":");
  11. if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);
  12. final int N = it.length-6;
  13. for (int i=0; i<=N; i+=6) {
  14. if (!"0x01".equals(it[i])) {
  15. Slog.w(TAG, "Unknown virtual key type at elem #"
  16. + i + ": " + it[i] + " for device " + deviceName);
  17. continue;
  18. }
  19. try {
  20. VirtualKeyDefinition key = new VirtualKeyDefinition();
  21. key.scanCode = Integer.parseInt(it[i+1]);
  22. key.centerX = Integer.parseInt(it[i+2]);
  23. key.centerY = Integer.parseInt(it[i+3]);
  24. key.width = Integer.parseInt(it[i+4]);
  25. key.height = Integer.parseInt(it[i+5]);
  26. if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "
  27. + key.scanCode + ": center=" + key.centerX + ","
  28. + key.centerY + " size=" + key.width + "x"
  29. + key.height);
  30. keys.add(key);
  31. } catch (NumberFormatException e) {
  32. Slog.w(TAG, "Bad number in virtual key definition at region "
  33. + i + " in: " + str + " for device " + deviceName, e);
  34. }
  35. }
  36. }
  37. br.close();
  38. } catch (FileNotFoundException e) {
  39. Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");
  40. } catch (IOException e) {
  41. Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);
  42. }
  43. return keys.toArray(new VirtualKeyDefinition[keys.size()]);
  44. }

其实找这个函数的调用的话,其实是发现通过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)处理的更多相关文章

  1. 隐藏Android下的虚拟按键

    要隐藏Android下的虚拟按键,可通过如下办法操作 adb root adb remount adb shell ls -al /system/build.prop   (查看文件权限) -rw-r ...

  2. android监听虚拟按键的显示与隐藏【转】

    本文转载自:http://blog.csdn.net/u014583590/article/details/55263141 虚拟按键在华为手机中大量存在,而虚拟按键的存在无疑增加了屏幕适配的难度,往 ...

  3. Android适配底部虚拟按键的方法

    ---恢复内容开始--- 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近项目进行适配的时候发现部分(如华为手机)存在底部虚拟按键的手机会因为虚拟按键的存在导致挡住部分界面,因为需要全屏显示 ...

  4. Android隐藏虚拟按键,关闭开机动画、开机声音

    /*********************************************************************** * Android隐藏虚拟按键,关闭开机动画.开机声音 ...

  5. Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高

    一.屏幕中各种栏目以及屏幕的尺寸 当我们需要计算屏幕中一些元素的高度时,或许需要先获取到屏幕或者各种栏目的高度,下面这个类包含了Status bar状态栏,Navigation bar虚拟按键栏,Ac ...

  6. android 虚拟按键是通过哪种机制上报的?

    1.在normal mode下,tp button也是和其他触摸事件一样,以坐标形式的input_event进行上报.在初始化时会通过tpd_button_setting()函数依据定义在tpd_cu ...

  7. 关于Android适配华为等带有底部虚拟按键的解决方案

    http://blog.csdn.NET/a91694451/article/details/50469857 最近公司的项目里遇到了一个问题,就是最后适配的时候时候同事的华为手机时,由于底部带有虚拟 ...

  8. 【Android】隐藏底部虚拟按键

    Google的官方文档是: https://developer.android.com/training/system-ui/navigation.html#behind 示例代码 1 View de ...

  9. android适配pad和部分手机底部虚拟按键+沉浸式状态栏

    在使用沉浸式状态栏设置界面全屏时发现pad和部分手机(华为和魅族系统自带)屏幕底部会带有虚拟按键,遮挡住界面本身的一部分. 为了设置隐藏,在网上找了一些方法,设置Activity主题再在布局加fits ...

随机推荐

  1. 未能加载文件 %CommonDir%\dte90a.olb。未能找到该文件,因此解决此问题的尝试失败

    分类: 日常应用问题 2012-08-04 10:53 914人阅读 评论(0) 收藏 举报 microsoft2010c vs2010 启动时提示 ------------------------- ...

  2. 利用 Windows Azure 实现“云优先”

    根据 IDC 的调查,云计算无疑为我们的合作伙伴提供了巨大的机会,预计到 2016 年,全球企业将在公共云服务上耗资 980 亿美元.在今天的休斯敦全球合作伙伴大会上,我们非常高兴能与合作伙伴共同寻求 ...

  3. egret随笔-publish命令的改进

    缘由 导了几天的ipa,每次publish后都要改zip包名的代码,终于鼓起勇气翻看了一下egret publish的代码,唉,这代码...应该不会是北京的那几个大牛写的吧??? 正题 看了源码才知道 ...

  4. 使用kd-tree加速k-means

    0.目录 前置知识 思路介绍 详述 1 确定h的中心点 2 算法步骤 java实现 1.前置知识 本文内容基于<Accelerating exact k-means algorithms wit ...

  5. 网易云课堂_程序设计入门-C语言_第五周:函数_2完数

    2 完数(5分) 题目内容: 一个正整数的因子是所有可以整除它的正整数.而一个数如果恰好等于除它本身外的因子之和,这个数就称为完数.例如6=1+2+3(6的因子是1,2,3). 现在,你要写一个程序, ...

  6. document.body is null

    document.body is null:做前端的同学们对这个错误应该不陌生吧 出现这个问题的原因是:你太着急了,document还没渲染到body呢,你就想调用了,当然会找不到了 解决办法so e ...

  7. SQLite语法

    一.建立数据库 sqlite3.exe test.db 二.双击sqlite-3_6_16目录下的程序sqlite3.exe,即可运行 三.退出 .exit 或者 .quit 四.SQLite支持如下 ...

  8. BOOST_PP_INC_I(x)实现

    这个比较有意思,# define BOOST_PP_INC_I(x) BOOST_PP_INC_ ## x 连接在一起以后,然后定义为x+1 实现了inc功能,不过最多也就到255 # /* Copy ...

  9. [一道搜狗输入法的面试题]C++转换构造函数和类型转换函数

    今天面试遇到一道有关C++转换构造函数的题目,之前经常见到默认构造函数.拷贝构造函数.析构函数,但是从没听说过转换构造函数,隐式转换函数也是一样,C++的确是够博大精深的,学习之路很长啊! 其实我们已 ...

  10. Windows Server 2008 Enterprise使用12G内存

    开启PAE选项,用以下命令解决这个问题: 1.开始运行cmd2.输入 BCDEdit /set PAE forceenable 后回车3.重起系统显示12GB内存,一切正常