Android tp的虚拟按键(virtual key)处理

    xiaoxiao2021-03-25  93

    http://blog.csdn.net/skywalkzf/article/details/7354560

    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 static unsigned int tpd_keycnt = 0;   static int tpd_keys[TPD_VIRTUAL_KEY_MAX]={0};   static int tpd_keys_dim[TPD_VIRTUAL_KEY_MAX][4];// = {0};   static ssize_t cust_virtual_keys_show(struct kobject *kobj,                      struct kobj_attribute *attr, char *buf) {       int i, j;       for(i=0, j=0;i<tpd_keycnt;i++)           j+=sprintf(buf, "%s%s:%d:%d:%d:%d:%d%s",buf,              __stringify(EV_KEY),tpd_keys[i],              tpd_keys_dim[i][0],tpd_keys_dim[i][1],              tpd_keys_dim[i][2],tpd_keys_dim[i][3],              (i==tpd_keycnt-1?"\n":":"));       return j;   }         static struct kobj_attribute cust_virtual_keys_attr = {       .attr = {           .name = "virtualkeys.cust-tpd",           .mode = S_IRUGO,       },       .show = &cust_virtual_keys_show,   };         static struct attribute *cust_properties_attrs[] = {       &cust_virtual_keys_attr.attr,       NULL   };         static struct attribute_group cust_properties_attr_group = {       .attrs = cust_properties_attrs,   };         struct kobject *properties_kobj;         void tpd_button_init(void) {       int ret = 0, i = 0, j=0;             tpd->kpd=input_allocate_device();       /* struct input_dev kpd initialization and registration */       tpd->kpd->name = TPD_DEVICE "-kpd";       set_bit(EV_KEY, tpd->kpd->evbit);       for(i=0;i<tpd_keycnt;i++)           __set_bit(tpd_keys[i], tpd->kpd->keybit);       tpd->kpd->id.bustype = BUS_HOST;       tpd->kpd->id.vendor  = 0x0001;       tpd->kpd->id.product = 0x0001;       tpd->kpd->id.version = 0x0100;       if(input_register_device(tpd->kpd))           TPD_DMESG("input_register_device failed.(kpd)\n");       set_bit(EV_KEY, tpd->dev->evbit);       for(i=0;i<tpd_keycnt;i++)           __set_bit(tpd_keys[i], tpd->dev->keybit);       properties_kobj = kobject_create_and_add("board_properties", NULL);       if(properties_kobj)           ret = sysfs_create_group(properties_kobj,&cust_properties_attr_group);       if(!properties_kobj || ret)       printk("failed to create board_properties\n");   }         void tpd_button_setting(int keycnt, void *keys, void *keys_dim)   {           tpd_keycnt = keycnt;           memcpy(tpd_keys, keys, keycnt*4);           memcpy(tpd_keys_dim, keys_dim, keycnt*4*4);   }   有了上面的代码,我们的virtual key才可以使用,这里主要是需要注册/sys/board_properties/virtualkeys.cust-tpd。这个是framework需要的文件节点。他的出现可以使我们的虚拟按键畅通无阻了。 当然,在这里tpd_keys这个定义key的数组和定义区域的tpd_keys_dim要准确的填充才可以的。具体的填充的规则如下: 每一个虚拟按键有六个参数: [cpp]  view plain  copy 0x01: A version code. Must always be 0x01.   <Linux key code>: The Linux key code of the virtual key.   <centerX>: The X pixel coordinate of the center of the virtual key.   <centerY>: The Y pixel coordinate of the center of the virtual key.   <width>: The width of the virtual key in pixels.   <height>: The height of the virtual key in pixels.   对比我的milestone来看看:   0x01:158:32:906:63:57:   0x01:139:162:906:89:57:   0x01:102:292:906:89:57:   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 public VirtualKeyDefinition[] getVirtualKeyDefinitions(String deviceName) {               ArrayList<VirtualKeyDefinition> keys = new ArrayList<VirtualKeyDefinition>();                              try {                   FileInputStream fis = new FileInputStream(                           "/sys/board_properties/virtualkeys." + deviceName);                   InputStreamReader isr = new InputStreamReader(fis);                   BufferedReader br = new BufferedReader(isr, 2048);                   String str = br.readLine();                   if (str != null) {                       String[] it = str.split(":");                       if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "***** VIRTUAL KEYS: " + it);                       final int N = it.length-6;                       for (int i=0; i<=N; i+=6) {                           if (!"0x01".equals(it[i])) {                               Slog.w(TAG, "Unknown virtual key type at elem #"                                       + i + ": " + it[i] + " for device " + deviceName);                               continue;                           }                           try {                               VirtualKeyDefinition key = new VirtualKeyDefinition();                               key.scanCode = Integer.parseInt(it[i+1]);                               key.centerX = Integer.parseInt(it[i+2]);                               key.centerY = Integer.parseInt(it[i+3]);                               key.width = Integer.parseInt(it[i+4]);                               key.height = Integer.parseInt(it[i+5]);                               if (DEBUG_VIRTUAL_KEYS) Slog.v(TAG, "Virtual key "                                       + key.scanCode + ": center=" + key.centerX + ","                                       + key.centerY + " size=" + key.width + "x"                                       + key.height);                               keys.add(key);                           } catch (NumberFormatException e) {                               Slog.w(TAG, "Bad number in virtual key definition at region "                                       + i + " in: " + str + " for device " + deviceName, e);                           }                       }                   }                   br.close();               } catch (FileNotFoundException e) {                   Slog.i(TAG, "No virtual keys found for device " + deviceName + ".");               } catch (IOException e) {                   Slog.w(TAG, "Error reading virtual keys for device " + deviceName + ".", e);               }                              return keys.toArray(new VirtualKeyDefinition[keys.size()]);           }   其实找这个函数的调用的话,其实是发现通过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
    转载请注明原文地址: https://ju.6miu.com/read-14563.html

    最新回复(0)