日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android6.0按键处理浅析

發布時間:2023/12/14 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android6.0按键处理浅析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

處理流程及示意圖:





1,硬件配置:

kernel-3.18\arch\arm\boot\dts\projectxxx.dts

&keypad {

???????? mediatek,kpd-key-debounce= <1024>;

???????? mediatek,kpd-sw-pwrkey= <116>;

???????? mediatek,kpd-hw-pwrkey= <8>;

???????? mediatek,kpd-use-extend-type= <0>;

???????? /*HWKeycode [0~71] -> Linux Keycode*/

???????? mediatek,kpd-hw-map-num= <72>;

// kpd-hw-init-map為硬件掃描的矩陣列表。跟具體硬件接法相關。即為linux_code

???????? mediatek,kpd-hw-init-map= <115 114 0 0 0 0 0 0 0 158 0 0 0 0 0 0 0 0 0 0 0 0 0 0

???????????????????????????????????? 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

???????????????????????????????????? 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >;

???????? mediatek,kpd-pwrkey-eint-gpio= <0>;

???????? mediatek,kpd-pwkey-gpio-din? = <0>;

???????? mediatek,kpd-hw-dl-key0= <0>;

???????? mediatek,kpd-hw-dl-key1= <1>;

???????? mediatek,kpd-hw-dl-key2= <8>;

???????? mediatek,kpd-hw-recovery-key= <0>;

???????? mediatek,kpd-hw-factory-key? = <1>;

???????? status= "okay";

};

?

硬件接法,軟件注意各個IO的功能配置,以確保按鍵掃描時獲取到正確的值。

2,kernel驅動:

按下按鍵后,會出發中斷,然后進去中斷處理程序中進行按鍵的掃描:

?

static void kpd_keymap_handler(unsignedlong data)

{

???????? inti, j;

???????? boolpressed;

???????? u16new_state[KPD_NUM_MEMS], change, mask;

???????? u16hw_keycode, linux_keycode;

?

???????? kpd_get_keymap_state(new_state);

?

???????? wake_lock_timeout(&kpd_suspend_lock,HZ / 2);

?

???????? for(i = 0; i < KPD_NUM_MEMS; i++) {

?????????????????? change= new_state[i] ^ kpd_keymap_state[i];

?????????????????? if(!change)

??????????????????????????? continue;

?

?????????????????? for(j = 0; j < 16; j++) {

??????????????????????????? mask= 1U << j;

??????????????????????????? if(!(change & mask))

???????????????????????????????????? continue;

?

??????????????????????????? hw_keycode = (i << 4) + j;//獲取到硬件掃描的HW_code值,這個與硬件接法相關。

??????????????????????????? /*bit is 1: not pressed, 0: pressed */

??????????????????????????? pressed= !(new_state[i] & mask);

??????????????????????????? if(kpd_show_hw_keycode)

???????????????????????????????????? kpd_print("(%s)HW keycode = %u\n", pressed ? "pressed" : "released",hw_keycode);

??????????????????????????? BUG_ON(hw_keycode>= KPD_NUM_KEYS);

??????????????????????????? linux_keycode = kpd_keymap[hw_keycode];//根據對應的hw_coed,按照dts中的對應,映射獲取到linux_code.

??????????????????????????? if(unlikely(linux_keycode == 0)) {

???????????????????????????????????? kpd_print("Linuxkeycode = 0\n");

???????????????????????????????????? continue;

??????????????????????????? }

??????????????????????????? kpd_aee_handler(linux_keycode,pressed);

?

??????????????????????????? input_report_key(kpd_input_dev, linux_keycode, pressed);//通過INPUT發送linux_codeinput subsystem

??????????????????????????? input_sync(kpd_input_dev);

??????????????????????????? kpd_print("reportLinux keycode = %u\n", linux_keycode);

?????????????????? }

???????? }

?

???????? memcpy(kpd_keymap_state,new_state, sizeof(new_state));

???????? kpd_print("savenew keymap state\n");

???????? enable_irq(kp_irqnr);

}

3,input 子系統對按鍵的處理:

具體請參照:input子系統按鍵處理

?adb可以參看proc/bus/input下面的devices和handler。

?

Devices的key:

I: Bus=0019 Vendor=2454 Product=6500Version=0010

N: Name="mtk-kpd"

P: Phys=

S:Sysfs=/devices/soc/10011000.keypad/input/input1

U: Uniq=

H: Handlers=event1

B: PROP=0

B: EV=3

B: KEY=40000000 1c0000 0 0 0

?

Hander:

N: Number=0 Name=sysrq (filter)

N: Number=1 Name=evdev Minor=64//這個是我們所用到的

?

?主要是對下面三個結構體進行配置:

Device: input的核心層,主要文件input.c,建立設備節點,對驅動層提供統一的接口。如主要的input_report_key() 就是他提供的。作用我覺得主要是對下形成對硬件,驅動進行接口的統一,對上次配合事件層提供相應的匹配接口。

Handler:event事件層,主要文件evdev.c。主要作用是用戶核心層的device相匹配,匹配成功后,然后新建handle。產生事件的節點。并且對上提供讀寫相關的接口。供上層獲取或者寫入相應的鍵值。evdev_read,evdev_write;到這里應該是kernel層的任務就完成了。

Handle:通過handler->connect(),將device與handler匹配連接起來。主要是匹配id。個人覺得只是形成一個簡單的綜合體,方便對匹配成功的device和handler的訪問。

?

static ssize_t evdev_read(struct file*file, char __user *buffer,

??????????????????????????? ? size_t count, loff_t *ppos)

{

???????? structevdev_client *client = file->private_data;

???????? structevdev *evdev = client->evdev;

???????? structinput_event event;

???????? size_tread = 0;

???????? interror;

?

???????? if(count != 0 && count < input_event_size())

?????????????????? return-EINVAL;

?

???????? for(;;) {

?????????????????? if(!evdev->exist || client->revoked)

??????????????????????????? return-ENODEV;

?

?????????????????? if(client->packet_head == client->tail &&

?????????????????? ??? (file->f_flags & O_NONBLOCK))

??????????????????????????? return-EAGAIN;

?

?????????????????? /*

?????????????????? ?* count == 0 is special - no IO is done but wecheck

?????????????????? ?* for error conditions (see above).

?????????????????? ?*/

?????????????????? if(count == 0)

??????????????????????????? break;

?

?????????????????? while(read + input_event_size() <= count &&

?????????????????? ?????? evdev_fetch_next_event(client,&event)) {

?

??????????????????????????? if(input_event_to_user(buffer + read, &event))//將獲取到的event信息反饋到用戶層

???????????????????????????????????? return-EFAULT;

?

??????????????????????????? read+= input_event_size();

?????????????????? }

?

?????????????????? if(read)

??????????????????????????? break;

?

?????????????????? if(!(file->f_flags & O_NONBLOCK)) {

??????????????????????????? error= wait_event_interruptible(evdev->wait,

?????????????????????????????????????????????? client->packet_head!= client->tail ||

?????????????????????????????????????????????? !evdev->exist|| client->revoked);

??????????????????????????? if(error)

???????????????????????????????????? returnerror;

?????????????????? }

???????? }

?

???????? returnread;

}

4,inputmanager對按鍵事件的獲取和向上派發:

參照文檔:inputmanager對按鍵事件的獲取和向上派發

說明:

調試的時候,可以用adb來進行調試。Input keyevent? 26//power key


先大致介紹一下整個流程,再做重點分析。輸入事件流程一共涉及到下面這幾個文件:

/frameworks/base/services/Java/com/Android/server/WindowManagerService.java

/frameworks/base/services/java/com/android/server/InputManager.java

/frameworks/base/services/jni/com_android_server_InputManager.cpp

/frameworks/base/libs/ui/InputReader.cpp

/frameworks/base/libs/ui/InputDispatcher.cpp

/frameworks/base/libs/ui/EventHub.cpp

其中,WindowManagerService.javaInputManager.java主要向Android為窗口系統提供服務,EventHub.cpp主要用來讀取設備文件中的RawEvent,而InputReader.cppInputDispatcher.cpp算是它們之間的對接層。

?

它們的關系是:WindowManagerService通過InputManager提供的接口開啟一個線程驅動InputReader不斷地從/dev/input/目錄下面的設備文件讀取事件,然后通過InputDispatcher分發給連接到WindowManagerService服務的客戶端。

InputReader從設備文件中讀取的是RawEvent,在交給InputDispatcher進行分發之前,它需要先把RawEvent進行轉化分類,拆分成KeyEventMotionEventTrackEvent各種類型等。這篇文章主要關注的就是這個RawEvent的拆分過程,所以我們的重點在EventHub.cpp中。并且,為了簡單化分析過程,在這里我的分析只關注觸摸屏事件。看它是如何從RawEvent被拆分成應用層用戶事件MotionEvent的。

?

?

5,InputDispatcher分發與客戶端的接收

待分析。

總結

以上是生活随笔為你收集整理的android6.0按键处理浅析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。