• 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

  • 相关阅读:
    Centos7 安装rabbitmq详细教程
    Spring Boot中的@Configuration和@Bean
    springboot+redis项目实战完整篇
    rabbitmq、kafka、activemq、rocketmq之间对比,区别
    MySQL基础总结
    MySQL视图
    MySQL左外链接与右外连接
    MySQL自连接
    MySQL关联查询
    MySQLhaving子句
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3212012.html
Copyright © 2020-2023  润新知