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 plaincopy
  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 plaincopy
  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 plaincopy
  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. android按键焦点事件分析(应用开发篇)
  2. Android 解决自定义 CheckBox 样式时的背景显示异常问题
  3. android 自定义组件 :对VelocityTracker的研究
  4. Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
  5. 自定义tabhost实现
  6. Android高手进阶教程(三)之----Android 中自定义View的应用
  7. Android按键添加和处理的方案
  8. Android Actionbar自定义标题栏
  9. 自定义ListView中的分割线

随机推荐

  1. Android Bitmap.setDensity(int density)
  2. Android的px、dip、sp的区别
  3. APK文件粗略介绍
  4. android 判断文件是否存在
  5. Android客户端自动更新代码
  6. Android Intent中的FLAG,很全
  7. Android之MediaPlayer(两种)基本使用方式
  8. android 客户端 smtp 协议发送数据
  9. [Android] 动态语言切换
  10. spotlight android app which likes spot