android wms,Android解析WindowManagerService(一)WMS的诞生
原標(biāo)題:Android解析WindowManagerService(一)WMS的誕生
前言
此前我用多篇文章介紹了WindowManager,這個系列我們來介紹WindowManager的管理者WMS,首先我們先來學(xué)習(xí)WMS是如何產(chǎn)生的。本文源碼基于Android 8.0,與Android 7.1.2相比有一個比較直觀的變化就是Java FrameWork采用了Lambda表達(dá)式。
1.WMS概述
WMS是系統(tǒng)的其他服務(wù),無論對于應(yīng)用開發(fā)還是Framework開發(fā)都是重點的知識,它的職責(zé)有很多,主要有以下幾點:
窗口管理
WMS是窗口的管理者,它負(fù)責(zé)窗口的啟動、添加和刪除,另外窗口的大小和層級也是由WMS進行管理的。窗口管理的核心成員有DisplayContent、WindowToken和WindowState。
窗口動畫
窗口間進行切換時,使用窗口動畫可以顯得更炫一些,窗口動畫由WMS的動畫子系統(tǒng)來負(fù)責(zé),動畫子系統(tǒng)的管理者為WindowAnimator。
輸入系統(tǒng)的中轉(zhuǎn)站
通過對窗口的觸摸從而產(chǎn)生觸摸事件,InputManagerService(IMS)會對觸摸事件進行處理,它會尋找一個最合適的窗口來處理觸摸反饋信息,WMS是窗口的管理者,因此,WMS“理所應(yīng)當(dāng)”的成為了輸入系統(tǒng)的中轉(zhuǎn)站。
Surface管理
窗口并不具備有繪制的功能,因此每個窗口都需要有一塊Surface來供自己繪制。為每個窗口分配Surface是由WMS來完成的。
WMS的職責(zé)可以簡單總結(jié)為下圖。
2.WMS的誕生
WMS的知識點非常多,在了解這些知識點前,我們十分有必要知道WMS是如何產(chǎn)生的。WMS是在SyetemServer進程中啟動的,不了解SyetemServer進程的可以查看在Android系統(tǒng)啟動流程(三)解析SyetemServer進程啟動過程這篇文章。
先來查看SyetemServer的main方法:
frameworks/base/services/java/com/android/server/SystemServer.java
main方法中只調(diào)用了SystemServer的run方法,如下所示。
frameworks/base/services/java/com/android/server/SystemServer.java
run方法代碼很多,這里截取了關(guān)鍵的部分,在注釋1處加載了libandroid_servers.so。在注釋2處創(chuàng)建SystemServiceManager,它會對系統(tǒng)的服務(wù)進行創(chuàng)建、啟動和生命周期管理。接下來的代碼會啟動系統(tǒng)的各種服務(wù),在注釋3中的startBootstrapServices方法中用SystemServiceManager啟動了ActivityManagerService、PowerManagerService、PackageManagerService等服務(wù)。在注釋4處的方法中則啟動了BatteryService、UsageStatsService和WebViewUpdateService。注釋5處的startOtherServices方法中則啟動了CameraService、AlarmManagerService、VrManagerService等服務(wù),這些服務(wù)的父類為SystemService。從注釋3、4、5的方法名稱可以看出,官方把大概80多個系統(tǒng)服務(wù)分為了三種類型,分別是引導(dǎo)服務(wù)、核心服務(wù)和其他服務(wù),其中其他服務(wù)為一些非緊要和一些不需要立即啟動的服務(wù),WMS就是其他服務(wù)的一種。
我們來查看startOtherServices方法是如何啟動WMS的:
frameworks/base/services/java/com/android/server/SystemServer.java
startOtherServices方法用于啟動其他服務(wù),其他服務(wù)大概有70多個,上面的代碼只列出了WMS以及和它相關(guān)的IMS的啟動邏輯,剩余的其他服務(wù)的啟動邏輯也都大同小異。在注釋1、2處分別得到Watchdog實例并對它進行初始化,Watchdog用來監(jiān)控系統(tǒng)的一些關(guān)鍵服務(wù)的運行狀況,后文會再次提到它。在注釋3處創(chuàng)建了IMS,并賦值給IMS類型的inputManager對象。注釋4處執(zhí)行了WMS的main方法,其內(nèi)部會創(chuàng)建WMS,需要注意的是main方法其中一個傳入的參數(shù)就是注釋1處創(chuàng)建的IMS,WMS是輸入事件的中轉(zhuǎn)站,其內(nèi)部包含了IMS引用并不意外。結(jié)合上文,我們可以得知WMS的main方法是運行在SystemServer的run方法中,換句話說就是運行在”system_server”線程”中,后面會再次提到”system_server”線程。
注釋5和注釋6處分別將WMS和IMS注冊到ServiceManager中,這樣如果某個客戶端想要使用WMS,就需要先去ServiceManager中查詢信息,然后根據(jù)信息與WMS所在的進程建立通信通路,客戶端就可以使用WMS了。注釋7處用來初始化顯示信息,注釋8處則用來通知WMS,系統(tǒng)的初始化工作已經(jīng)完成,其內(nèi)部調(diào)用了WindowManagerPolicy的systemReady方法。
我們來查看注釋4處WMS的main方法,如下所示。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java
在注釋1處調(diào)用了DisplayThread的getHandler方法,用來得到DisplayThread的Handler實例。DisplayThread是一個單例的前臺線程,這個線程用來處理需要低延時顯示的相關(guān)操作,并只能由WindowManager、DisplayManager和InputManager實時執(zhí)行快速操作。注釋1處的runWithScissors方法中使用了Java8中的Lambda表達(dá)式,它等價于如下代碼:
在注釋2處創(chuàng)建了WMS的實例,這個過程運行在Runnable的run方法中,而Runnable則傳入到了DisplayThread對應(yīng)Handler的runWithScissors方法中,說明WMS的創(chuàng)建是運行在“android.display”線程中。需要注意的是,runWithScissors方法的第二個參數(shù)傳入的是0,后面會提到。來查看Handler的runWithScissors方法里做了什么:
frameworks/base/core/java/android/os/Handler.java
開頭對傳入的Runnable和timeout進行了判斷,如果Runnable為null或者timeout小于0則拋出異常。注釋1處根據(jù)每個線程只有一個Looper的原理來判斷當(dāng)前的線程(”system_server”線程)是否是Handler所指向的線程(”android.display”線程),如果是則直接執(zhí)行Runnable的run方法,如果不是則調(diào)用BlockingRunnable的postAndWait方法,并將當(dāng)前線程的Runnable作為參數(shù)傳進去 ,BlockingRunnable是Handler的內(nèi)部類,代碼如下所示。
frameworks/base/core/java/android/os/Handler.java
注釋2處將當(dāng)前的BlockingRunnable添加到Handler的任務(wù)隊列中。前面runWithScissors方法的第二個參數(shù)為0,因此timeout等于0,這樣如果mDone為false的話會一直調(diào)用注釋3處的wait方法使得當(dāng)前線程(”system_server”線程)進入等待狀態(tài),那么等待的是哪個線程呢?我們往上看,注釋1處,執(zhí)行了傳入的Runnable的run方法(運行在”android.display”線程),執(zhí)行完畢后在finally代碼塊中將mDone設(shè)置為true,并調(diào)用notifyAll方法喚醒處于等待狀態(tài)的線程,這樣就不會繼續(xù)調(diào)用注釋3處的wait方法。因此得出結(jié)論,”system_server”線程線程等待的就是”android.display”線程,一直到”android.display”線程執(zhí)行完畢再執(zhí)行”system_server”線程,這是因為”android.display”線程內(nèi)部執(zhí)行了WMS的創(chuàng)建,顯然WMS的創(chuàng)建優(yōu)先級更高些。
WMS的創(chuàng)建就講到這,最后我們來查看WMS的構(gòu)造方法:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService .java
注釋1處用來保存?zhèn)鬟M來的IMS,這樣WMS就持有了IMS的引用。注釋2處通過DisplayManager的getDisplays方法得到Display數(shù)組(每個顯示設(shè)備都有一個Display實例),接著遍歷Display數(shù)組,在注釋3處的createDisplayContentLocked方法會將Display封裝成DisplayContent,DisplayContent用來描述一快屏幕。
注釋4處得到AMS實例,并賦值給mActivityManager ,這樣WMS就持有了AMS的引用。注釋5處創(chuàng)建了WindowAnimator,它用于管理所有的窗口動畫。注釋6處初始化了窗口管理策略的接口類WindowManagerPolicy(WMP),它用來定義一個窗口策略所要遵循的通用規(guī)范。注釋7處將自身也就是WMS通過addMonitor方法添加到Watchdog中,Watchdog用來監(jiān)控系統(tǒng)的一些關(guān)鍵服務(wù)的運行狀況(比如傳入的WMS的運行狀況),這些被監(jiān)控的服務(wù)都會實現(xiàn)Watchdog.Monitor接口。Watchdog每分鐘都會對被監(jiān)控的系統(tǒng)服務(wù)進行檢查,如果被監(jiān)控的系統(tǒng)服務(wù)出現(xiàn)了死鎖,則會殺死Watchdog所在的進程,也就是SystemServer進程。
查看注釋6處的initPolicy方法,如下所示。
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
initPolicy方法和此前講的WMS的main方法的實現(xiàn)類似,注釋1處執(zhí)行了WMP的init方法,WMP是一個接口,init方法的具體實現(xiàn)在PhoneWindowManager(PWM)中。PWM的init方法運行在”android.ui”線程中,它的優(yōu)先級要高于initPolicy方法所在的”android.display”線程,因此”android.display”線程要等PWM的init方法執(zhí)行完畢后,處于等待狀態(tài)的”android.display”線程才會被喚醒從而繼續(xù)執(zhí)行下面的代碼。在本文中共提到了3個線程,分別是”system_server”、”android.display”和”android.ui”,為了便于理解,下面給出這三個線程之間的關(guān)系。
“system_server”線程中會調(diào)用WMS的main方法,main方法中會創(chuàng)建WMS,創(chuàng)建WMS的過程運行在”android.display”線程中,它的優(yōu)先級更高一些,因此要等創(chuàng)建WMS完畢后才會喚醒處于等待狀態(tài)的”system_server”線程。
WMS初始化時會執(zhí)行initPolicy方法,initPolicy方法會調(diào)用PWM的init方法,這個init方法運行在”android.ui”線程,并且優(yōu)先級更高,因此要先執(zhí)行完P(guān)WM的init方法后,才會喚醒處于等待狀態(tài)的”android.display”線程。
PWM的init方法執(zhí)行完畢后會接著執(zhí)行運行在”system_server”線程的代碼,比如本文前部分提到WMS的
systemReady方法。返回搜狐,查看更多
責(zé)任編輯:
總結(jié)
以上是生活随笔為你收集整理的android wms,Android解析WindowManagerService(一)WMS的诞生的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android.process.medi
- 下一篇: android手机连接无线路由器上网设置