<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android Input 子系統(tǒng)初探

          共 4154字,需瀏覽 9分鐘

           ·

          2020-09-15 13:06



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


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

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

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

          • 提供標準化用戶空間接口;


          圖1 Input事件處理整體框圖


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



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



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



          1.?Input_dev


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




          2.?Input_handler


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



          3.?Input_handle


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


          圖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)上報,其中響應(yīng)上報是通過注冊的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)系圖


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



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




          5.?Input事件傳遞


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


          圖4 觸摸屏報點事件格式


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



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



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


          在收到sync事件或者event buffer size接近最大值時開始同步事件,此時傳遞的為一包事件,input_pass_values接口主要是尋找input_dev設(shè)備對應(yīng)的handle處理存儲的數(shù)據(jù),另外設(shè)置的輸入設(shè)備支持EV_REP事件,則會在此處設(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事件傳遞給用戶空間


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



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



          參考文獻


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


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




          推薦閱讀:
          ? ??專輯|Linux文章匯總
          ? ??專輯|程序人生
          ? ??專輯|C語言


          嵌入式Linux
          微信掃描二維碼,關(guān)注我的公眾號?
          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色电影免费在线播放 | 久久青草免费电影 | 激情在线无码色综合播放视频 | 日韩日逼 | 中文字幕高清无码视频 |