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


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

    [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?" ":":"));  
    13.     return j;  
    14. }  
    15.   
    16.   
    17. static struct kobj_attribute cust_virtual_keys_attr = {  
    18.     .attr = {  
    19.         .name = "virtualkeys.cust-tpd",  
    20.         .mode = S_IRUGO,  
    21.     },  
    22.     .show = &cust_virtual_keys_show,  
    23. };  
    24.   
    25.   
    26. static struct attribute *cust_properties_attrs[] = {  
    27.     &cust_virtual_keys_attr.attr,  
    28.     NULL  
    29. };  
    30.   
    31.   
    32. static struct attribute_group cust_properties_attr_group = {  
    33.     .attrs = cust_properties_attrs,  
    34. };  
    35.   
    36.   
    37. struct kobject *properties_kobj;  
    38.   
    39.   
    40. void tpd_button_init(void) {  
    41.     int ret = 0, i = 0, j=0;  
    42.   
    43.   
    44.     tpd->kpd=input_allocate_device();  
    45.     /* struct input_dev kpd initialization and registration */  
    46.     tpd->kpd->name = TPD_DEVICE "-kpd";  
    47.     set_bit(EV_KEY, tpd->kpd->evbit);  
    48.     for(i=0;i<tpd_keycnt;i++)  
    49.         __set_bit(tpd_keys[i], tpd->kpd->keybit);  
    50.     tpd->kpd->id.bustype = BUS_HOST;  
    51.     tpd->kpd->id.vendor  = 0x0001;  
    52.     tpd->kpd->id.product = 0x0001;  
    53.     tpd->kpd->id.version = 0x0100;  
    54.     if(input_register_device(tpd->kpd))  
    55.         TPD_DMESG("input_register_device failed.(kpd) ");  
    56.     set_bit(EV_KEY, tpd->dev->evbit);  
    57.     for(i=0;i<tpd_keycnt;i++)  
    58.         __set_bit(tpd_keys[i], tpd->dev->keybit);  
    59.     properties_kobj = kobject_create_and_add("board_properties", NULL);  
    60.     if(properties_kobj)  
    61.         ret = sysfs_create_group(properties_kobj,&cust_properties_attr_group);  
    62.     if(!properties_kobj || ret)  
    63.     printk("failed to create board_properties ");  
    64. }  
    65.   
    66.   
    67. void tpd_button_setting(int keycnt, void *keys, void *keys_dim)  
    68. {  
    69.         tpd_keycnt = keycnt;  
    70.         memcpy(tpd_keys, keys, keycnt*4);  
    71.         memcpy(tpd_keys_dim, keys_dim, keycnt*4*4);  
    72. }  


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



    其实找这个函数的调用的话,其实是发现通过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

  • 相关阅读:
    【纯水题】POJ 1852 Ants
    【树形DP】BZOJ 1131 Sta
    【不知道怎么分类】HDU
    【树形DP】CF 1293E Xenon's Attack on the Gangs
    【贪心算法】CF Emergency Evacuation
    【思维】UVA 11300 Spreading the Wealth
    【树形DP】NOI2003 逃学的小孩
    【树形DP】BZOJ 3829 Farmcraft
    【树形DP】JSOI BZOJ4472 salesman
    【迷宫问题】CodeForces 1292A A NEKO's Maze Game
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3212012.html
Copyright © 2011-2022 走看看