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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Input 子系统初探

發(fā)布時(shí)間:2023/12/20 Android 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Input 子系统初探 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android系統(tǒng)基于Linux內(nèi)核實(shí)現(xiàn),內(nèi)核作為整個(gè)操作系統(tǒng)的核心,對下,它負(fù)責(zé)整個(gè)硬件的驅(qū)動、實(shí)現(xiàn)對硬件器件的控制管理;對上,它提供各種系統(tǒng)所需的核心功能。Android系統(tǒng)支持的輸入設(shè)備較多,如按鍵、觸摸屏、手柄等,面對種類繁雜的輸入設(shè)備,內(nèi)核通過抽象化的方式來使得各輸入設(shè)備的的核心處理流程統(tǒng)一化,細(xì)節(jié)處理流程差異化(通過不同類型的回調(diào)實(shí)現(xiàn)),這就是Input子系統(tǒng)所要完成的內(nèi)容,總結(jié)來說,它在內(nèi)核中主要作用為:

  • 規(guī)范化Input Device的定義方式及其數(shù)據(jù)的上報(bào)格式;

  • 規(guī)范化Input Handler的定義方式及其需要實(shí)現(xiàn)的回調(diào);

  • 為Input Device和Input Handler提供核心服務(wù);

  • 提供標(biāo)準(zhǔn)化用戶空間接口;

圖1 Input事件處理整體框圖

整體的Input事件處理框圖如圖1所示,本文主要圍繞這張圖來詳述Input子系統(tǒng)的各個(gè)方面,如定義、初始化、注冊匹配、事件傳遞、與用戶空間的交互等。介于本人理解有限,如有敘述不當(dāng)?shù)牡胤?#xff0c;還請諒解指出。

一.Input子系統(tǒng)相關(guān)定義

在前序內(nèi)容中,我們提前用到了Input Device、Input Handler等名詞,但還沒有進(jìn)行相關(guān)的解釋說明。本節(jié)的內(nèi)容旨在了解Input子系統(tǒng)中幾個(gè)重要的結(jié)構(gòu)體定義,以便于Input子系統(tǒng)的后續(xù)介紹。

1.?Input_dev

struct input_dev用來抽象所有的輸入設(shè)備,由于不同的輸入設(shè)備上報(bào)的事件或形式存在差異,抽象的input_dev必然需要包含差異的內(nèi)容,形成一種x+(y1、y2、y3..)的方式(其中,x為所有輸入設(shè)備共有的成員,y1/y2/y3為輸入設(shè)備差異化成員),所以在實(shí)際的特定輸入設(shè)備驅(qū)動開發(fā)工作中,只需要填充部分成員即可完成input_dev的定義。詳細(xì)的成員定義說明如下:

2.?Input_handler

struct input_handler用于抽象事件處理,不同的輸入設(shè)備對應(yīng)的事件處理方式會存在差異,linux內(nèi)核抽象該結(jié)構(gòu)體保證input事件的處理流程一致,具體的實(shí)現(xiàn)部分通過input_handler的函數(shù)指針回調(diào)完成,主要包括匹配、建立連接、事件傳遞/過濾等,具體的成員說明如下:

3.?Input_handle

在抽象input_dev和input_handler之后,我們知道一個(gè)input_dev上報(bào)的事件可以被多個(gè)input_handler接收處理,一個(gè)input_handler也可以處理多個(gè)input_dev上報(bào)的事件,這樣多個(gè)input_dev和多個(gè)input_handler之間可能會形成交織的網(wǎng)狀(如下圖2)。在這種情況下,需要一個(gè)橋梁來搭建兩者之間的聯(lián)系,兩邊的函數(shù)調(diào)用都可以通過這個(gè)“中介”進(jìn)行,input_handle就是這個(gè)橋梁。

圖2 device與handler示意圖

Input_handle的定義比較簡單,各成員說明如下:

二.Input子系統(tǒng)相關(guān)流程

主要流程包括input core初始化、input設(shè)備注冊、input_handler注冊、input設(shè)備與input_handler匹配、input事件傳遞。

1.?input core初始化

Input core通過sybsys_initcall注冊設(shè)定啟動等級,保證其初始化會早于input設(shè)備和input_handler的注冊(module_init方式注冊),在初始化過程中主要完成:

1)input類注冊;

2)Proc文件創(chuàng)建,主要用于input_handler和devices信息查看;

3)注冊字符設(shè)備,主設(shè)備號為13;

2.?input_dev注冊

一般而言,Input設(shè)備驅(qū)動需要完成設(shè)備的控制和響應(yīng)上報(bào),其中響應(yīng)上報(bào)是通過注冊的input_dev來完成,所以input_dev的注冊需要在input設(shè)備驅(qū)動的初始化過程中調(diào)用input_register_device完成,input_register_device執(zhí)行的過程說明如下:

3.?input_handler注冊

Input handler的注冊相對于input設(shè)備的注冊更為簡單,在填充struct input_handler后,直接調(diào)用input_register_handler完成handler的注冊,input_register_handler的處理流程如下:

4.?input_handler與input_dev匹配

Input_handler與input_dev的注冊最終都會調(diào)用input_attach_handler完成自己與“相親對象”的配對,配對完成后input_dev、input_handler、input_handle之間的關(guān)系如圖3所示,設(shè)備驅(qū)動和事件處理層驅(qū)動都可以通過自身訪問到input_handle,然后通過input_handle訪問到自己的“對象”,具體的匹配代碼說明如下:

圖3 input_handle與owner關(guān)系圖

當(dāng)handler中match回調(diào)沒有實(shí)現(xiàn)時(shí)只用根據(jù)input_dev中的id與input_handler中id_table包含的id進(jìn)行匹配,如evdev_handler匹配所有Input設(shè)備,故所有的input設(shè)備都可以通過dev/input/event*路徑獲取原始上報(bào)數(shù)據(jù)。

在匹配成功后會調(diào)用connect回調(diào),舉例evdev_handler中的connect內(nèi)容如下:

5.?Input事件傳遞

不同的input設(shè)備上報(bào)的input事件的格式不同,比如觸摸屏上報(bào)input事件時(shí)一般需要上報(bào)手指的id、x坐標(biāo)、y坐標(biāo)等信息(如圖4為B協(xié)議報(bào)點(diǎn)格式, A協(xié)議報(bào)點(diǎn)無需上報(bào)id,會在inputReader中重新分配)。

圖4 觸摸屏報(bào)點(diǎn)事件格式

每一個(gè)事件上報(bào)都是通過input_event接口來完成,在判定事件類型是否支持后,主要是調(diào)用input_handle_event來完成:

該接口中,首先根據(jù)type、code判定該事件的disposition,當(dāng)disposition為INPUT_PASS_TO_DEVICE時(shí),將該事件傳遞給input_dev設(shè)備自身的event函數(shù)處理;當(dāng)disposition為INPUT_PASS_TO_HANDLERS時(shí),即將該事件傳遞給事件處理層處理,此處一般是將所有的事件存儲在dev的vals數(shù)組中(此處,在disposition為INPUT_SLOT時(shí)表明上次處理的點(diǎn)與本次不同,故多添加一個(gè)ABS_MT_SLOT事件);當(dāng)disposition為INPUT_FLUSH時(shí)或者傳遞的事件達(dá)到數(shù)組的極限時(shí)才將事件傳遞給事件處理層處理( input_sync時(shí),disposition才能取得INPUT_FLUSH這個(gè)值)。

input_get_disposition函數(shù)是將根據(jù)type和code判定事件的disposition,此處只關(guān)心EV_SYN、EV_KEY、EV_ABS事件。EV_KEY事件中當(dāng)設(shè)置了按鍵自動重發(fā)時(shí)的value值為2,!!test_bit(code, dev->key) != !!value語句中都進(jìn)行了兩次取反操作是為了避免出現(xiàn)0、1之外的數(shù)據(jù),如果本次上報(bào)的按鍵事件與上次不同才會進(jìn)行上報(bào)給事件處理層(dev->key保存了最近按鍵事件的所有狀態(tài)),否則不予處理。

在收到sync事件或者event buffer size接近最大值時(shí)開始同步事件,此時(shí)傳遞的為一包事件,input_pass_values接口主要是尋找input_dev設(shè)備對應(yīng)的handle處理存儲的數(shù)據(jù),另外設(shè)置的輸入設(shè)備支持EV_REP事件,則會在此處設(shè)置定時(shí)器自動重發(fā)按鍵事件(按鍵值為2)。

所有的input設(shè)備都會和evdev_handler匹配,此處假設(shè)匹配的handler為evdev_handler,則events指向的函數(shù)為evdev_events:

evdev_pass_values只是將傳過來的所有事件存儲在client->buffer中;kill_fasync函數(shù)用于發(fā)送通知事件,告訴上層client->buffer中有數(shù)據(jù)可以讀了。

6.?Input事件傳遞給用戶空間

當(dāng)應(yīng)用層或框架層調(diào)用read函數(shù)讀取/dev/input/event*文件時(shí),會調(diào)用evdev_read返回?cái)?shù)據(jù),其中event_fetch_next_event是判斷client->buffer這個(gè)循環(huán)緩沖區(qū)中的頭尾指針是否相等(相等時(shí)buffer中沒有數(shù)據(jù)),不相等時(shí)取出一個(gè)input_event類型的事件放入到event中;input_event_to_user函數(shù)是將此事件copy到應(yīng)用層,input_event_size函數(shù)是用來獲取一個(gè)input_event事件的大小,循環(huán)復(fù)制client->buffer中的事件到應(yīng)用層的buffer中。

上層誰會來打開文件讀這些事件?一種是getevent工具,另外一種是android框架層的inputflinger服務(wù),其主要會創(chuàng)建InputReader和InputDispatcher兩個(gè)線程。InputReader負(fù)責(zé)與底層的事件打交道,其先通過eventHub讀取所有的事件, 然后通過設(shè)備屬性或事件特征找到對應(yīng)的mapper處理將底層事件轉(zhuǎn)換為android設(shè)計(jì)的事件類型;InputDispatcher負(fù)責(zé)與窗口打交道,將收到的事件派發(fā)給對應(yīng)注冊的窗口。

參考文獻(xiàn)

1.?https://www.cnblogs.com/lifexy/p/7542989.html

2.?https://blog.csdn.net/qq_39937242/article/details/82631165

推薦閱讀:

? ??專輯|Linux文章匯總

? ??專輯|程序人生

? ??專輯|C語言

嵌入式Linux

微信掃描二維碼,關(guān)注我的公眾號?

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Android Input 子系统初探的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。