天天看點

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

視窗層級關系(浮窗是如何“浮”的)?

浮窗有哪些限制,如何越過使用者授權實作浮窗功能?

activity是如何接收到touch事件的?

前兩個問題在前兩篇文章中已經分析,在這篇文章中我們以第三個問題為切入點,簡單分析一下視窗與使用者輸入的關系。

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

正常的思路是直接去尋找activity 的dispatchtouchevent方法,我們看看activity的dispatchtouchevent()方法的調用棧,在方法中加入thread.dumpstack()來檢視調用棧。

輸出:

一條粗略的線索:

viewrootimpl-deliverinputevent ->view.dispatchpointerevent->phonewindow$decorview.dispatchtouchevent->mainactivity.dispatchtouchevent,讀者可以根據這個線索去跟蹤源碼。我們這裡先不深入其中細節,先來看看decorview 到 activity.dispatchtouchevent 是如何調用的?

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:
浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

再來看看decorview的 dispatchtouchevent方法:

decorview 是view的子類重寫了dispatchtouchevent方法,在這個方法中調用 callback,這個callback是window的一個靜态内部接口類,activity實作了這個接口,activity的dispatchtouchevent() 方法正是從callback繼承而來。

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

思路同上:dump出根視圖的dispatchtouchevent()方法調用棧:

添加到windowmanagerservice中管理。是以activity的dispatchtouchevent方法其實是view傳遞過來的。

我們可以猜測粗略線索是:touch事件-》硬體裝置-》某個服務-》 viewrootimpl --》view。

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

我們先來看看viewrootimpl和view到底有啥關系?首先,看看windowmanager的addview方法,windowmanager是個接口,我們看其實作類windowmangerimpl的源碼:

在來看看windowmanagerglobal的源碼:

在這裡建立了viewrootimpl對象,并且把傳單下來的view通過setview方法設定到其中的變量,來看看setview的源碼:

由此得到關系圖:

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

通過windowmanagerimpl.addview,最終把view添加指派到了viewrootimpl的變量mview。viewrootimpl是view(視窗)和windowmanagerservice協定的紐帶

從mvc的角度來看的話:可以認為view是v,viewrootimpl是controller,windowmanagerservice是model。view的繪制、重新整理都需要通過viewrootimpl與windowmanagerservice互動,另外view的輸入事件(鍵盤、觸摸)也是由viewrootimpl傳遞給view的,那麼viewrootimpl是如何監聽到使用者輸入事件的呢?

回憶下上文點到的windowinputeventreceiver,這是viewrootimpl的一個内部類,我們dump出來的dispatchtouchevent最初的地方就是源于這個類,再往下就是messagequeue、looper的資訊。由此可以推斷windowinputeventreceiver是viewrootimpl和底層某個服務進行ipc互動的關鍵,這個服務是什麼服務呢?

這部分涉及到anddroid系統的兩個重要的子產品:圖形視窗和使用者輸入,分别對應的服務是windowmanagerservice和inputmanagerservice。windowmanagerservice負責圖形視窗(view)的繪制、重新整理等事物、inputmanagerservice管理使用者輸入事件處理。

1、inputmanagerservice 管理者兩個角色inputreader和inputdispatcher 。

2、inputreader負責從硬體(eventhub)讀取輸入信号,轉化成為事件,傳遞給inputdispatcher。

3、inputdispatcher将inputreader傳遞過來的事件分發到對應的場景,例如将touch事件分發到viewrootimpl。

那麼inputmanagerservice(inputdispatcher)是如何将touch事件傳遞到viewrootimpl(windowinputeventreceiver)的呢?

使用者輸入事件處理模型是“生産者-消費者“模型,生産者發生在系統程序中,消費者發生在使用者程序中。傳遞過程由ipc互動,這裡的通訊是采用的socket通訊,消費者需要向生産者”注冊“通訊管道,registerinputchannel建立連接配接。在viewrootimpl的setview()方法中建立了windowinputeventreceiver,并通過windowmanagerservice向inputmanagerservice注冊inputchannel監聽輸入事件。

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

touchevent事件傳遞流程 :

浮窗系列之視窗與使用者輸入系統Touch事件是如何分發到Activity上來的?Touch事件是如何分發到浮窗的根視圖的?ViewRootImpl是個啥?使用者輸入與視窗參考資料:

<a href="http://www.cnblogs.com/samchen2009/p/3367496.html">《android 的視窗管理系統》</a>

<a href="http://www.cnblogs.com/samchen2009/p/3368158.html">《android的使用者輸入處理》</a>

<a href="http://blog.csdn.net/singwhatiwanna/article/details/50775201">《android中motionevent的來源和viewrootimpl》</a>

繼續閱讀