Android tp的虛擬按鍵(virtual key)處理

來源:互聯網
上載者:User

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的底層驅動實現了。這裡你實驗了嗎?你可能會說,“不行,這裡實現不了”。是的,這個時候還不行,還有關鍵的步驟得操作。


在這裡,你需要如下代碼加入才可以。

 

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來獲得定義的虛擬按鍵。
 

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!


 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.