Android窗口管理服務WindowManagerService的簡要介紹和學習計劃

       在前一個系列文章中,我們從個體的角度來分析了Android應用程序窗口的實現框架。事實上,如果我們從整體的角度來看,Android應用程序窗口的實現要更復雜,因爲它們的類型和作用不同,且會相互影響。在Android系統中,對系統中的所有窗口進行管理是窗口管理服務WindowManagerService的職責。在本文中,我們就將簡要介紹WindowManagerService的職能以及制定學習計劃。

       我們知道,在Android系統中,同一時刻,只有一個Activity窗口是激活的,但是,對於WindowManagerService服務來說,這並不意味着它每次只需要管理一個Activity窗口,例如,在兩個Activity窗口的切換過程中,前後兩個Activity窗口實際上都是可見的。即使在只有一個Activity窗口是可見的時候,WindowManagerService服務仍然需要同時管理着多個窗口,這是因爲可見的Activity窗口可能還會被設置了壁紙窗口(Wallpaper Winodw)或者彈出了子窗口(Sub Window),以及可能會出現狀態欄(Status Bar)以及輸入法窗口(Input Method Window),如圖1所示。


圖1 Activity窗口及其子窗口、壁紙窗口、輸入法窗口和狀態欄的位置結構

       因此,WindowManagerService服務是不可以假設同一時刻它只需要管理一個窗口的,它需要通過各個窗口在屏幕上的位置以及大小來決定哪些窗口需要顯示的以及要顯在哪裏,這實際上就是要計算出各個窗口的可見區域。

       從前面Android系統Surface機制的SurfaceFlinger服務渲染應用程序UI的過程分析一文可以知道,SurfaceFlinger服務在渲染整個屏幕的UI的時候,會對各個窗品的可見性進行計算,因此,WindowManagerService服務只要將它所管理的各個窗品的位置以及大小告訴SurfaceFlinger服務,後者可以幫幫它計算出各個窗口的可見區域了。注意,這裏,這裏所說的窗口位置包括窗口在X、Y和Z軸的位置。

      WindowManagerService服務大致按照以下方式來控制哪些窗口需要顯示的以及要顯在哪裏:

      1. 每一個Activity窗口的大小都等於屏幕的大小,因此,只要對每一個Activity窗口設置一個不同的Z軸位置,然後就可以使得位於最上面的,即當前被激活的Activity窗口,纔是可見的。

      2. 每一個子窗口的Z軸位置都比它的父窗口大,但是大小要比父窗口小,這時候Activity窗口及其所彈出的子窗口都可以同時顯示出來。

      3. 對於非全屏Activity窗口來說,它會在屏幕的上方留出一塊區域,用來顯示狀態欄。這塊留出來的區域稱對於屏幕來說,稱爲裝飾區(decoration),而對於Activity窗口來說,稱爲內容邊襯區(Content Inset)。

      4. 輸入法窗口只有在需要的時候纔會出現,它同樣是出現在屏幕的裝飾區或者說Activity窗口的內容邊襯區的。

      5. 對於壁紙窗口,它出現需要壁紙的Activity窗口的下方,這時候要求Activity窗口是半透明的,這樣就可以將它後面的壁紙窗口一同顯示出來。

      6. 兩個Activity窗口在切換過程,實際上就是前一個窗口顯示退出動畫而後一個窗口顯示開始動畫的過程,而在動畫的顯示過程,窗口的大小會有一個變化的過程,這樣就導致前後兩個Activity窗口的大小不再都等於屏幕的大小,因而它們就有可能同時都處於可見的狀態。事實上,Activity窗口的切換過程是相當複雜的,因爲即將要顯示的Activity窗口可能還會被設置一個啓動窗口(Starting Window)。一個被設置了啓動窗口的Activity窗口要等到它的啓動窗口顯示了之後纔可以顯示出來。

      從以上六點就可以看出,窗口在X、Y和Z軸的位置及其大小的計算非常重要,它們共同決定了一個窗口是否是整體可見的,還是部分可見的,或者整體不可見的。在Android系統中,WindowManagerService服務是通過一個實現了WindowManagerPolicy接口的策略類來計算一個窗口的位置和大小的。例如,在Phone平臺上,這個策略類就是PhoneWindowManager。這樣做的好處就是對於不同的平臺實現不同的策略類來達到不同的窗口控制模式。

     從上面的描述就可以看出,WindowManagerService服務除了要與Activity窗口所運行在的應用程序進程打交道之外,還需要與SurfaceFlinger服務以及窗口管理策略類PhoneWindowManager交互,如圖2所示。


圖2 WindowManagerService服務與Activity窗口、SurfaceFlinger服務、PhoneWindowManager策略的關係圖

       在前面Android應用程序窗口(Activity)實現框架簡要介紹和學習計劃的一系列文章中,我們已經分析過應用程序進程與WindowManagerService服務之間的交互過程了,因此,在這一系列文章中,我們就將主要分析WindowManagerService服務的實現,以及它與SurfaceFlinger服務、PhoneWindowManager策略類的交互過程。

       從總體上來看,WindowManagerService服務的實現是相當複雜的,例如,WindowManagerService類的核心成員函數performLayoutAndPlaceSurfacesLockedInner的代碼有1200+行,比600-行代碼的ViewRoot類的核心成員函數performTraversals還要恐怖。不過,WindowManagerService服務實現的複雜性是在預料之中的,畢竟它要管理的整個系統所有窗口的UI,而在任何一個系統中,窗口管理子系統都是極其複雜的。基於上述理由,採用硬碰硬的方式來分析WindowManagerService服務的實現是以卵擊石,因此,這個系列的文章將對WindowManagerService服務進行分拆,然後再逐個擊破,這是算法中的分而治之思想是一致的。

       具體來說,我們將按照以下幾個情景來分析WindowManagerService服務的實現:

       1. 窗口大小和位置(X軸和Y軸)的計算過程

       2. 窗口的組織方式

       3. 輸入法窗口的調整過程

       4. 壁紙窗口的調整過程

       5. 窗口Z軸位置的計算和調整過程

       6. Activity窗口的啓動窗口的顯示過程

       7. Activity窗口的切換過程

       8. Activity窗口的動畫顯示過程

       再次地,由於WindowManagerService服務的實現實在是太複雜,因此上述八個情景可能還不足於說明WindowManagerService服務的實現。如果出現這種情況,我們在分析的過程中會進行相應的調整。相信對WindowManagerService服務的實現進行分而治之的分析後,我們就可以對Android系統的UI架構有一個深刻的理解!敬請關注接下來的文章!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章