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


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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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要准确的填充才可以的。具体的填充的规则如下:
  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来获得定义的虚拟按键。
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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://www.2cto.com/kf/201307/230972.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值