一起來學嵌入式Android系統 (第七章心得一)

在O’REILLY"嵌入式Android系統"這本書的第七章Android Framework,這也是本書的最後一章;在這章中主要是描述Framework這個議題,但因內容很多,一樣也是分次進行心得分享,本次分享議題是:框架入門。書中在本章一開始時就提到,Android Framework當中大部份都必須原樣使用,但若要進行修改框架的動作通常需要瞭解原始碼並添加自己的程式碼;書中的內容也是以描述方式帶過重點,實際要深入瞭解程式就需要參考一些大陸作者寫的原始碼分析書籍,這些資訊可以參考第二章的心得分享內容以獲得書籍的資訊。框架入門在書上內容本身已經很多,而且也延續上一章的Init內容;所以討論會拆成以下子議題分別說明:

※ 中心建置區塊

※ 系統服務

※ 開機動畫

※ Dex最佳優化

※ App啟動

在中心建置區塊部份,Framework的運作依賴少數幾個關鍵建置區塊:Service Manager、Android Runtime、Zygote與Dalvik;init最早啟動的服務之一就是servicemanager,這是所有系統中的系統服務之名錄,它必須很早就啟動,好讓後續啟動的系統服務得以向它注冊;所以servicemanager並不是一個選用元件,而且它在init.rc檔案的順序是不夠隨便客制化的。下一個要啟動的元件是Zygote,從init.rc看到實際上執行的是app_process命令;而app_process仰賴Android Runtime;而其被打包成共用程式庫libandroid_runtime.so,Android Runtime能夠啟動與管理Dalvik VM,以便執行Android類型的程式碼;Runtime也包含促進「通常由執行在Dalvik上所有Android類型之App所完成的功能」;另外要注意的是,Runtime不預載類別(class),那是Zygote在設定系統執行Android App時所做的。利用app_process開啟的Java類別既可使用一般的Android API,並且與既有的系統服務溝通,如果是被建置成AOSP的一部份(如Launcher2),它在建置期間便可以使用很多供它使用的android.*套件。此外,Android App僅能夠由Activity Manager利用intent來起動,一旦Zygote自己被啟動,Activity Manager本身即被當作其餘系統服務的一部份來啟動;為了讓Zygote正確啟動,並且讓它開啟System Server,必須讓init.rc裡頭對應的app_process那行保持原封不動,就在它預設的位置上,也就是說這部份沒有什麼可組態的方式。一旦Zygote的VM被啟動,com.android.internal.os.ZygoteInit類別的main函式被呼叫,它會預先載入整組Android套件,著手啟動System Server,然後繞行迴圈並監聽來自Activity Manager的連接;就如書中所述,這部份也沒什麼好客制化的。要詳細瞭解這些程式碼如何運作,建議研讀先前所介紹的源碼分析書籍,較新版本(Android 4.1)的分析可參考"深入剖析Android系統"(簡體書,楊長剛 著)。

在系統服務部份,System Server作為Zygote的一部份而啟動,還有其它系統服務從Ssystem Server以外的行程被啟動;從Android 4.0開始,第一個被啟動的系統服就是Surface Flinger,在Android 4.2中該服務原始碼所在的位置是frameworks/native/services/surfaceflinger,其內容如下:

7-1-1

Surface Flinger是Android最根本構建區塊之一。而為了啟動System Server,Zygote分叉出並且執行com.android.server.SystemServer類别的main()函式,後者加載了libandroid_servers.so程式庫,然後呼叫frameworks/base/cmds/system_server/system_init.cpp中的原生程式碼,在Android 4.2中由system_server啟動的以C程式撰寫的系統服務就只有Sensor Service。接著System Server回到Java,並且開始初始化關鍵性的系統服務,然後繼續初始化它所管理的系統服務,並向Service Manager註冊,全都由frameworks/base/services/java/com/android/server/SystemServer.java中的程式碼來完成的,這些都是不能組態的,全部都寫死在SystemServer.java中;隨意修改可能會造成CTS驗證失敗。除了Suface Flinger以及由System Server啟動的系統服務之外,另一組系統服務根源自mediaserver的啟動,其在Android 4.2中原始碼存放於frameworks/av/media目錄下:

7-1-2

啟動下列系統服務:Audio Flinger、Media Player Service、Camera Service與Audio Policy Service;同樣的,這也是不可組態的,但在全志方案有將Player的地方代換成自己的播放器CedarX而非使用Android原生的Stagefright,這算是比較深度的修改。最後在Phone App的議題上面,則跟開發板搭配上面較無關係,就請自行參閱書上的描述。

在開機動畫的部份,開發板使用的全志方案一樣有提供對應的說明文件如下所示(參考連結https://mega.co.nz/#F!mtxywC7B!034Ovh0nhI-XQmfD70x3LQ,本公司不保證其內容):

7-1-3

其它詳細的說明就請參考書中的內容;另外,在網路上也可以找到很多"bootanimation.zip"的製作方式與檔案。

在Dex最佳優化部份;Package Manager用於管理系統當中所有的APK,除此之外,它還會處理APK的安裝與移除,並且幫忙Activity Manager處理intent;而其職責還包括DEX byte-code的JIT版本在對應的Java程式碼執行之前已經備妥,為達到此目的,Package Manager建構子遍歷系統中所有的.apk檔案及.jar檔案,並請求installd針對它們執行dexopt命令;這個行程應該只會發生在第一次開機時,之後,/data/dalvik-cache目錄會包含所有.dex檔案的JIT版本,而且啟動過程基本上會快很多;書上也有提供最佳化的執行順序。當然,最佳化的時間也可以在建置時期完成,就是在建置時加入"WATH_DEXPREOPT=true"。

在App啟動部份;隨著系統服務起動接近尾聲,App開始被啟動,Activity Manager透過傳送Intent.CATEGORY_HOME類型的intent結束其初始化,從而促使Launcher App啟動及家螢幕出現;但系統服務啟動實際上將導致不少App啟動。最早起動的App類型之一為輸入法(input method),Input Method Manager Service的建構子檢視與啟動具有針對android.view.InputMethod而準備之intent過濾器的所有App服務。在永續性App部份,於其定義描述檔的<application>元素裡具有android:persistent="true"之屬性的App於啟動期間由Activity Manager自動產生,如果APP不正常結束也會自動被Activity Manager重啟;標記為永續性的的App並不會被Activity Manager做生命週期管理,它們存活在系統的整個生命週期,這允許我們利用這樣的App來實作某些特殊功能。在家螢幕的部份,一般情況下只有一個家螢幕App,它回應Intent.CATEGORY_HOME的intent,那是在系統服務啟動尾聲由Activity Manager所發送的;另外,若有一個以上App回應該intent,使用者會看到一個對話框,詢問我們想要使用那個家螢幕;而系統也會依據情況當需要家螢幕到前景時由Activity Manager發送該intent。在BOOT_COMPLETED intent部份,Activity Manager會在啟動時發送intent.BOOT_COMPLETED的intent,這是一個通常用來告知App系統已經完成開機的intent;為了要接收這個intent,App必須要明確地要求能夠這樣做的權限(android.intent.action.BOOT_COMPLETED)。在APPWIDGET_UPDATE intent中,App Widget Service將自己註冊為接收intent.BOOT_COMPLETED,它利用該intent的接收,透過傳送Intent. APPWIDGET_UPDATE,做為啟動系統當中所有App Widget的觸發機制。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s