Android輸入子系統

來源:互聯網
上載者:User

Linux輸入子系統回顧1:為什麼要回顧linux輸入子系統?這個問題後面自然就知道了  1.linux輸入子系統裝置是基於平台裝置機制的,所以先回顧平台裝置機制,主要回顧後面用得到的東西 1.申請主裝置號2.建立cdev->將cdev掛載到系統裝置雜湊鏈表中,同時產生inode節點3.建立device->將device與剛產生的inode節點關聯起來,為上層調用提供介面   2.註冊輸入子系統裝置 1.建立一個裝置類class2.申請主裝置號3.建立cdev->將cdev掛載到系統裝置雜湊鏈表中,同時產生inode節點4.建立input_device->將input_device與剛產生的inode節點關聯起來,為事件驅動層提供介面 1.註冊裝置支援輸入事件類型(type)->【這個後面會用到】2.註冊裝置支援輸入事件編碼3.產生/dev/input_device       5.當input_device與input_hander匹配成功 1.產生/dev/input*2.上層應用通過主裝置號開啟/dev/input,通過次裝置號開啟/dev/input_device   3.輸入子系統部分函數 1.read函數->讀【後面會用到】2.write函數->寫【後面會用到】3.event函數->上報事件【後面會用到】 【提前思考的問題】1.Android事件處理系統是怎麼捕捉到輸入事件的?2.Android上層應用是怎麼捕捉到輸入事件的?3.Android上層應用捕捉到輸入事件是怎麼響應的?  2.從啟動一個Android程式開始  1.Activity啟動流程:onCreate()->onStart()->onResume()->Activity Running 【Q1】:為什麼onStart()後不直接Running,要插入一個onResume(),在onResume()中系統作了什麼事情?<A1>:在onResume()中,系統會為該Activity建立一個ViewRoot!   【Q2】:這個ViewRoot有什麼用?它做了哪些事情?這個後面解答  3.Android事件從輸入到輸出的整個流程  1.Activity運行時,使用者點擊觸控螢幕操作->{事件產生}    1.點擊觸控螢幕,必然會調用觸控螢幕驅動->{事件輸入} 【Q3】:事件傳遞過程?->{事件傳遞}<A3>:以下所有步驟! 1.Android上層應用調用Framework層的JNI本地方法->{事件訊息傳遞到JNI層}  1.實現JNI層方法,填充本地方法映射表,實現提供Android上層應用的介面 2.產生so動態連結程式庫檔案,adb push到/system/lib目錄下  2.JNI本地方法調用HAL層(硬體抽象層:中介軟體)方法->{事件訊息傳遞到HAL層}  1.JNI層通過指定ID得到HAL模組執行個體,然後調用HAL層函數 2.產生so動態連結程式庫檔案,adb push到/system/lib/hw目錄下  3.HAL通過系統調用write進入核心層->{事件訊息傳遞到核心}  1.copy_from_user()取得使用者層資料 2.調用input_device.write->{(1.1.2):事件訊息傳遞到驅動層} ------------------------------------------------------------------------------------------ 4.輸入裝置驅動擷取事件,調用event函數->{(1.1.3)} 5.事件處理層根據事件類型進行上報->{事件訊息傳遞到核心事件處理層}   1.調用input_event(device,type,code,value)->{【type】後面會用到} 6.到事件處理層時,核心會喚醒read函數->{(1.1.1):事件訊息傳遞到核心層}   1.通過copy_to_user()將核心資料傳遞到使用者空間->{事件訊息傳遞到使用者空間}    【Q4】:read函數被誰調用的? 7.事件訊息被Android的事件處理系統捕捉到->{事件訊息傳遞到Android事件處理系統}  1.Android事件處理系統將這個訊息發送到Android應用程式層 【Q5】:事件訊息在Android事件處理系統中是怎麼傳遞的?  8.Android上層擷取事件訊息,根據事件類型(3.1.1.5.1:type)響應上層View相應回呼函數 9.Android介面UI更新->{事件響應}  4.至此為此,項目中用到的架構知識已經介紹完畢  1.Android事件處理系統作為一個黑盒子,暫時略過  2.切入到項目解讀:電視棒遠程遙控器 1.用戶端APK 1.資料擷取->{此資料必須與Linux輸入子系統相容,這樣才能達到欺騙系統的目的}2.資料傳遞 2.服務端APK->{實現二個虛擬設備(虛擬鍵盤裝置與虛擬滑鼠裝置} 1.接收資料2.將資料傳送到虛擬設備3.虛擬設備上報事件,欺騙系統輸入事件發生  5.剖析Android事件處理系統【Q5】:事件訊息在Android事件處理系統中是怎麼傳遞的?<A5>:看看Android的事件處理系統1.緊接著3.1.1.7,事件訊息傳遞到Android事件處理系統2.在Android開機時,系統服務(System Server)會初始化Android視窗管理服務(WindowManagerService)3.WMS服務會初始化InputManager(InputManager是Framework層的一個C++類,負責管理所有的輸入事件的捕獲與轉寄) 1.在InputManager建構函式中,會初始化事件處理系統中最重要的三個類(InputReader/InputDispatcher/EventHub)2.然後初始化InputManager(InputManager.initialize()),產生兩個線程(InputReaderThread/InputDispatcherThread,分別負責事件捕獲與事件轉寄)3.InputReaderThread線程工作->{解決問題1:Android事件處理系統是怎麼捕捉到輸入事件的}     1.調用InputReader::loopOnce(),在InputReader類中,已經實現looper機制,迴圈操作      1.調用EventHub::getEvent()函數        1.調用Epoll_wait()函數          1.在Epoll_wait()函數中,會去迴圈讀取所有的/dev/input裝置,一旦有事件產生,就會被此函數捕捉到 【Q6】:Android事件處理系統與/dev/input裝置是如何關聯起來的【A6】:EventHub::Device <---->/dev/input,一一對應關係  2.當有事件發生時,Android事件處理系統會調用read函數->{系統調用,從核心層拿到事件訊息} 【Q4】:read函數被誰調用的?<A4>:read函數是InputReader調用的       2.將從核心層讀取到的事件訊息(input_event)儲存到RawEvent中 2.根據事件類型(input_event.type)調用相應的訊息轉換器(InputMapper)  1.Android系統目前支援5種事件訊息(翻滑蓋/軌跡球/多點觸摸/單點觸摸/鍵盤)3.InputReader::InputDevice::inputMapper將RawEvent事件轉換成對應的Notifyargs  1.InputMapper將RawEvent事件轉換成對應的Notifyargs類  2.將Notifyargs加入到InputRead::QueueListener::argsQueue隊列中4.調用InputReader::QueueListener::flush()函數,處理隊列中的事件訊息5.調用Notifyargs::notify函數,將事件訊息轉換成對應的EventEntry再轉交給InputDispatcher 1.對事件進行預先處理  1.判斷是否丟棄此事件訊息    1.丟棄,則直接返回    2.不丟棄  2.擷取當前Activity對應的Connection對象->(這個後面再講)2.將對應的EventEntry加入到InputDispatcher::OutBoundQueue隊列中  【Q7】:在Notifyargs是怎麼擷取InputDispatcher執行個體的  <A7>:在初始化InputRead::QueueListener::argsQueue隊列時,將InputDispatcher對象傳遞過來了 6.喚醒InputDispatcher::pollOnce()函數 4.InputDispatcherThread線程工作  1.調用InputDispatcher::loopOnce(),在InputDispatcher類中,同樣實現looper機制,迴圈操作    1.調用pollOnce()函數,輪詢InputDispatcher::OutBoundQueue隊列      1.隊列中的有事件訊息      2.被Notifyargs::notify()函數喚醒  2.調用對應的InputDispatcher::dispach函數    1.從InputDispatcher::OutBoundQueue隊列中取得EventEntry對象    2.將EventEntry對象轉換成DispatchEntry對象    3.將DispatchEntry對象加入到InputChannel::Connection::outboundQueue隊列中      【Q8】:這個InputChannel::Connection對象是從哪裡來的?有什麼用?【Q9】:現在InputDispatcher得到了轉換後的事件訊息,即將要發出去,但是往哪裡發?<A9>:要解決這個問題,需要回到【Q2】  4.【Q2】:ViewRoot有什麼用?它做了哪些事情?->{解決問題2:Android上層應用是怎麼捕捉到輸入事件的?}  <A2>:1.首先,ViewRoot是一個Hander,與當前Activity綁在一起的      2.ViewRoot有一個重要的作用:與WMS通訊,完成整個GUI視窗系統的繪製      3.建立ViewRoot的時候做了哪些事情?現在來解決問題2:Android上層應用是怎麼捕捉到輸入事件的? 1.由前面分析知道,Android的事件輸入來自InputManager,所以ViewRoot需要與InputManager通訊  【Q10】:ViewRoot怎麼與InputManager通訊並取得事件訊息?  <A10>:ViewRoot與InputManager之間有一個共用記憶體(ShareMemory)    1.InputManager::InputDispatcher將最後的事件訊息發送到共用記憶體(ShareMemory)中    2.ViewRoot在知道有事件訊息到來時,就去共用記憶體(ShareMemory)中取此事件訊息  【Q11】1.ViewRoot怎麼知道有事件訊息到來?  <A11>:1.ViewRoot與InputManager是通過管道通訊的機制來傳遞訊息的    1.在建立ViewRoot後,會建立兩個InputChannel類對象      1.其中一個InputChannel對象註冊到NativeInputQueue中,與ViewRoot綁在一起        【Q12】這個NativeInputQueue是用來幹什麼的?        <A12>:這個NativeInputQueue是Android系統用來維護事件接收的,因為同一時刻,會有很多Activity在等待事件輸入      2.另一個InputChannel對象註冊到InputManager類對象中    2.同時會申請上面用到的的共用記憶體    3.InputChannel類主要封裝管道描述符和共用記憶體的描述符等資訊      1.在ViewRoot與InputManager中各註冊了一個InputChannel類對象,其中各有兩個管道描述符        1.兩個InputChannel對象中都包含一個讀和一個寫描述符        2.所以在ViewRoot與InputManager之前完成了全雙工系統的通訊【後面會用到】  【Q13】:在Android中,每建立一個Activity,就會建立一個ViewRoot,所以也會建立一個InputChannel對象,那Android系統怎麼來區分這些Activity?  <A13>:還記得【Q8】嗎,兩個問題一起解決:InputChannel::Connection對象是從哪裡來的?有什麼用?    1.為了區分不同的Activity,NativeInputQueue類中定義了一個子類Connection    2.在註冊InputChannel對象時,每個InputChannel對象中都建立了一個Connection對象      1.所以ViewRoot中的每個InputChannel與InputManager中的InputChannel都包含一個Connection對象      2.這個Connection對象標識了不同的Activity         4.到現在我們就可以回到【Q9】了 5.【Q9】:現在InputDispatcher得到了轉換後的事件訊息,即將要發出去,但是往哪裡發? <A9>:1.由上面的分析,我們知道現在需要將事件訊息發送給ViewRoot    1.調用InputChannel::Connection::inputPublisher.publishMotionEvent函數將事件訊息發送到共用記憶體(ShareMemory)    2.InputChannel對象向寫管道發送一個dispatch資訊 6.現在工作就該轉移到ViewRoot這邊了  【Q14】:在NativeInputQueue中有很多InputChannel對象,究竟哪個InputChannel的管道會收到資訊?  <A14>:還記得【Q13】嗎,InputManager的InputChannel對象是由ViewRoot建立後註冊過去的    1.在每個註冊的InputChannel對象中,都包含了一個Connection對象    2.InputManager的InputChannel對象的Connection對象<--->NativeInputQueue中的InputChannel對象的Connection對象,是一一對應的關係    3.所以與InputDispatcher中Connection對象相對應的那個Connection對象將收到管道資訊  1.相應的InputChannel對象的Connection對象收到管道資訊  2.調用InputChannel::Connection::inputConsumer到共用記憶體(ShareMemory)中取得事件訊息  3.InputChannel再向寫管道中發一個資訊,表示此事件已經取得  4.然後InputManager中的InputChannel將會收到管道訊息,再繼續進行下一輪事件處理 7.到此為止,事件訊息已經傳遞到NativeInputQueue中的InputChannel對象中  1.由前面分析,NativeInputQueue中的每個InputChannel對象都對應一個Activity  2.NativeInputQueue中InputChannel對象是在ViewRoot建立之後建立的,也就是我們的Activity啟動之前    【Q15】:現在Activity關聯的InputChannel對象拿到的這個事件訊息,但是怎麼處理呢?現在我們就來回答問題3:Android上層應用捕捉到輸入事件是怎麼響應的?    <A15>:這個需要回到ViewRoot端InputChannel對象註冊的時候,也就是【Q11】的位置      1.ViewRoot端InputChannel對象在向NativeInputQueue註冊時,需要註冊3個參數        1.其中有一個參數就是ViewRoot的成員變數InputHandler          1.InputHandler就是事件的處理函數,也就是所謂的回呼函數          2.傳遞它的作用主要是明確當前ViewRoot的事件處理函數          3.當InputChannel對象取得事件後,就會去調用ViewRoot的InputHandler函數-{到此為止,事件訊息就傳遞迴了Android應用程式層}            【Q16】:這個回呼函數到底是什嗎?            <A17>:這個回呼函數大多被Android系統實現成抽象函數              1.在我們的電視棒遠程遙控器的用戶端,就重寫了對應的方法,用來擷取我們需要的資料,比如onScroll/onLongPress等  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.