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. staticunsignedinttpd_keycnt=0;
  2. staticinttpd_keys[TPD_VIRTUAL_KEY_MAX]={0};
  3. staticinttpd_keys_dim[TPD_VIRTUAL_KEY_MAX][4];//={0};
  4. staticssize_tcust_virtual_keys_show(structkobject*kobj,
  5. structkobj_attribute*attr,char*buf){
  6. inti,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. returnj;
  14. }
  15. staticstructkobj_attributecust_virtual_keys_attr={
  16. .attr={
  17. .name="virtualkeys.cust-tpd",
  18. .mode=S_IRUGO,
  19. },
  20. .show=&cust_virtual_keys_show,
  21. };
  22. staticstructattribute*cust_properties_attrs[]={
  23. &cust_virtual_keys_attr.attr,
  24. NULL
  25. };
  26. staticstructattribute_groupcust_properties_attr_group={
  27. .attrs=cust_properties_attrs,
  28. };
  29. structkobject*properties_kobj;
  30. voidtpd_button_init(void){
  31. intret=0,i=0,j=0;
  32. tpd->kpd=input_allocate_device();
  33. /*structinput_devkpdinitializationandregistration*/
  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_devicefailed.(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("failedtocreateboard_properties\n");
  52. }
  53. voidtpd_button_setting(intkeycnt,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:Aversioncode.Mustalwaysbe0x01.
  2. <Linuxkeycode>:TheLinuxkeycodeofthevirtualkey.
  3. <centerX>:TheXpixelcoordinateofthecenterofthevirtualkey.
  4. <centerY>:TheYpixelcoordinateofthecenterofthevirtualkey.
  5. <width>:Thewidthofthevirtualkeyinpixels.
  6. <height>:Theheightofthevirtualkeyinpixels.
  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. publicVirtualKeyDefinition[]getVirtualKeyDefinitions(StringdeviceName){
  2. ArrayList<VirtualKeyDefinition>keys=newArrayList<VirtualKeyDefinition>();
  3. try{
  4. FileInputStreamfis=newFileInputStream(
  5. "/sys/board_properties/virtualkeys."+deviceName);
  6. InputStreamReaderisr=newInputStreamReader(fis);
  7. BufferedReaderbr=newBufferedReader(isr,2048);
  8. Stringstr=br.readLine();
  9. if(str!=null){
  10. String[]it=str.split(":");
  11. if(DEBUG_VIRTUAL_KEYS)Slog.v(TAG,"*****VIRTUALKEYS:"+it);
  12. finalintN=it.length-6;
  13. for(inti=0;i<=N;i+=6){
  14. if(!"0x01".equals(it[i])){
  15. Slog.w(TAG,"Unknownvirtualkeytypeatelem#"
  16. +i+":"+it[i]+"fordevice"+deviceName);
  17. continue;
  18. }
  19. try{
  20. VirtualKeyDefinitionkey=newVirtualKeyDefinition();
  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,"Virtualkey"
  27. +key.scanCode+":center="+key.centerX+","
  28. +key.centerY+"size="+key.width+"x"
  29. +key.height);
  30. keys.add(key);
  31. }catch(NumberFormatExceptione){
  32. Slog.w(TAG,"Badnumberinvirtualkeydefinitionatregion"
  33. +i+"in:"+str+"fordevice"+deviceName,e);
  34. }
  35. }
  36. }
  37. br.close();
  38. }catch(FileNotFoundExceptione){
  39. Slog.i(TAG,"Novirtualkeysfoundfordevice"+deviceName+".");
  40. }catch(IOExceptione){
  41. Slog.w(TAG,"Errorreadingvirtualkeysfordevice"+deviceName+".",e);
  42. }
  43. returnkeys.toArray(newVirtualKeyDefinition[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

更多相关文章

  1. J2ME to android之学习笔记
  2. Android(安卓)JNI编程提高篇之一
  3. 从JVM到Dalivk再到ART(class,dex,odex,ELF)
  4. emulator: could not find virtual device named 'my_avd'
  5. 在Android上实现WLAN的一点理解
  6. Android(安卓)TV开发中所有的遥控器按键监听
  7. android隐藏底部虚拟键Navigation Bar实现全屏
  8. (Android) Eclipse "launching delegate" 停在 27%的解决方法
  9. android 沉浸式状态栏不会和虚拟重叠

随机推荐

  1. Android系统自带的camera默认使用后置摄
  2. Ubuntu 13.04 编译环境配置及android 2.3
  3. SafetyNet & 漏洞rootutils 利用
  4. OpenGL,Android注意事项初始化顺序 NullP
  5. Android Studio 第五十三期 - 自定义Edit
  6. [android]编译时出现/usr/bin/ld: skippi
  7. 2013.01.03 (2)——— android开发实例之仿
  8. 关于标准android中视频播放器中的快进和
  9. 仿照Android的池化技术
  10. Android Bluetooth Code