1. 程式人生 > >Android視窗管理服務WindowManagerService的簡要介紹和學習計劃

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

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

《Android系統原始碼情景分析》一書正在進擊的程式設計師網(http://0xcc0xcd.com)中連載,點選進入!

        我們知道,在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服務的實現:

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