2010 Android 平台社群開發大會 – 論文集 主題:Using High Level View on Android Porting

2010 Android 平台社群開發大會 – 論文集 主題:Using High Level View on Android Porting

摘要:
本文針對移植Android至實際硬體平台,提出High level view的方法;為什麼要使用High level view來看Android Porting?因為High level view是移植Android的捷徑;畢竟人類的生命有限,我們不太可能在全盤瞭解Android之後,才進行移植工作;再者因為市場變化的太快,也許等到我們全盤瞭解Android之後,智慧型手機市場已與現在大不相同。
本文使用破題法直接點出如何使用High level view on Android Porting,就是將未知的部份當成一個黑箱,假設它是對的,接著試圖解決移植過程中所遭遇的問題,換句話說假設Android的原始碼沒有問題,可以正常執行,在此條件下試圖去執行Android,如果無法順利地執行Android,再根據所遇到的問題,想辦法解決,解決問題的方法不外乎就是ctags + 暴力法。

內文:
因為現在的SoC越來越強大,開發方式已經漸漸由傳統的customized轉變為general + customized,部份開發人員甚至將SoC當成general purpose processor來開發。因為SoC越來越powerful,CPU甚至已經超越1GHz,所以手機的開發方式會越來越趨近傳統PC的開發方式,雖然兩者之間還是有很大差距,但是這個趨勢正在成形。不過因為產業生態的不同,所以手機市場不像傳統PC市場,PC市場是由intel及Microsoft主導,而手機則是大廠林立,各自獨霸一方,像3G晶片,Qualcomm擁有高度市佔率,2G晶片則以MTK、Broadcom等多家廠商為主,而DSP則以TI等大廠較為知名。智慧型手機軟體則由以往的Symbian及Windows系列轉變為由iPhone及Android主導的趨勢;當然黑莓機也是有相當高的市佔率。

手機市場商機龐大,每年9-12億支的出貨量,遠是PC出貨量的三倍大,試問如何能夠在短時間內進入手機市場,並且佔有一席之地?可能只有一個方法,就是站在巨人的肩膀上。倘若從頭打造一套全新、完整的手機系統,必定耗時費工,時間與人力成本更是無法估量,若是能夠採用當下現有的軟體,加以修改及結合,並將研發重心放在該產品的應用面上,才能夠縮短產品上市的時間(Time to Market)。以手機為例,試問一支怎樣的手機,消費者會願意掏錢購買,消費者第一眼看到的是手機的外觀,也就是ID(工業設計),再來就是UI(User Interface),或稱作使用者介面,所以手機軟體的發展重點在上層,也就是應用軟體的部分,iPhone就是因為人性化的操作介面而大賣,所以一個友善且直覺式的操作方式,成為現下智慧型手機的發展重點之一。

Android的架構圖如下:
http://developer.android.com/guide/basics/what-is-android.html

從Android的架構圖得知,Android的組成與傳統Embedded Linux的概念相同:僅取所需的軟體套件,兩者皆為component based的架構;只是Android在軟體授權方面,做了更多的考量。簡單地說,Android與以往Embedded Linux的產品相同:各取所需,組合而成;不同的是:Dalvik VM及Application Framework為Android自行開發,正因上層應用軟體是Android的發展重點,所以Android將重心放在Dalvik VM、Application Framework及Applications。
從software stack的角度來看,Android是一套完整的OS,從下到上,從kernel,library到application,Android具備一套作業系統所應有的軟體元件;而從Framework的角度來看,Android是一個不完整的系統,因為它只是一個架構,如果要控制實際的硬體,我們可能需要加入相關的程式碼,而所需加入程式碼的多寡,視情況不同而定。
若從Framework的角度來看Android,Android利用了Open Source的好處,因為Android可能只是提供一個啟發性的概念,而在開放源碼的條件下,Android可能得到全世界developer的回饋與發想,這些都對Android的發展是有利且正向的。
從High level view來看Android的架構圖:

從上圖得知,若是以嵌入式軟體的架構來看,Android與傳統Embedded Linux並無不同,大架構分為kernel space及user space;而這也正是我們移植Android的步驟;也與目前Android原始碼下載的方式相互呼應。
從High level view的角度來看,移植Android只需要掌握大方向,而由上圖得知,移植Android的流程為:先移植kernel的部份,接著移植user space。
移植Android並不困難,但是卻很複雜,簡單地說,就是一個字“雜”,因此要整理出一個移植的流程並不容易,遠比實際移植要來的困難。移植Android需要Embedded Linux的背景知識,包含Linux kernel的開機流程,Android並沒有修改Linux kernel的開機流程、控制權的轉移、如何追蹤Linux kernel的原始碼以及過去相關的經驗等等。

正因為移植Android需要的背景知識過於複雜,所以我們更應該從High level view的角度來看Android Porting,唯有使用High level view的方式來移植Android,才能夠降低移植的複雜度。我們的作法是避免讓Android過於龐大且複雜的程式碼模糊我們移植的焦點,從基本的Linux開機流程切入,切開kernel space及user space,簡化問題,將複雜的軟體架構分層,先從大方向來看,再一步步的深入了解。

我們在移植Android的過程中,有時候因為Android的原始碼過於龐大及複雜,而忘記要從High level view的角度來看Android Porting,甚至被Android的原始碼牽著鼻子走,因此在移植Android的過程中,不要忘記要不時跳脫當下的思維,回到High level view的角度來看Android Porting。

我們的目的是移植Android、拆解Android,想盡辦法在短時間內讓Android可以在我們的硬體平台上執行,因此我們除了必須具備上述的背景知識外,還要熟悉可以幫助我們縮短移植時間的工具軟體,畢竟工欲善其事,必先利其器;既然我們正在開發Android,身處在Open Source的世界裡,就應該站在巨人的肩膀上,利用現有且好用的工具軟體來輔助我們移植Android,縮短移植Android的時間。我們在這裡介紹三個好用的Open Source工具,善用工具可以幫助我們縮短移植所需的時間:

WinMerge
http://winmerge.org/about/screenshots/
Meld
http://meld.sourceforge.net/screenshots.html
Kdiff3
http://kdiff3.sourceforge.net/doc/screenshots.html

在移植初期,細心是移植Android的一大關鍵,因為一定要夠細心,才能夠完整移植必須或是相關的程式碼;而經驗則為移植後期的關鍵。

我們在移植Android的過程中,解決問題的方法不外乎就是ctags + 暴力法。ctags可以幫助我們建立程式碼的symbol,用於靜態追蹤程式碼,方便我們馬上找到程式碼的位置,進而分析問題產生的原因,嘗試除錯及解決問題。暴力法則是利用關鍵字來縮小搜尋的範圍,逼近相關程式碼或是產生錯誤的位置。暴力法之好用是因為非常直覺,使用find搭配grep來縮小及逼近相關程式碼的範圍。善用ctags + 暴力法來幫助我們盡可能在短時間內完成初步移植的工作。

在移植初期,我們不太可能在完全或是全盤瞭解Android的樣貌下,才進行移植工作,畢竟Android一開始是由Google + Qualcomm + HTC三方人馬大力催生的,過程中勢必耗費大量的人力資源,如果我們要在全盤瞭解的條件下,才進行移植工作,這條路似乎不是可行的方式,所以我們建議將未知或是不了解的部份,當成一個黑箱,換句話說在我們未能全盤了解Android的條件下,假設從Google官方網站上所下載的Android原始碼可以正常運作,然後試圖讓Android可以在實際硬體平台上執行,從執行過程中的訊息,一步步修改原始碼,使之符合該硬體平台的執行環境,讓Android可以順利地在該硬體平台上執行;過程中如果遇到問題,但是不知道如何解決時,或是不想知道問題發生的原因,那麼可以想辦法試著找到該問題的源頭,disable該功能,嘗試在部份功能不啟動或是不執行的情況下,先想辦法看到Android的畫面,移植初期的目的只有一個,就是想盡辦法讓Android可以在我們的硬體平台上執行,當然用的都是合法,正當的手段。

移植Android至硬體平台,需要的是掌握移植的大方向,了解Embedded Linux的架構、Linux開機流程、如何追蹤Linux kernel及Android的原始碼,掌握住大方向後,再補強工具軟體的使用、GNU Make的語法等等,如此便具備移植Android的能力,最後,如果過去有相關的經驗,勢必對移植Android有一定的助益。

綜合以上說明,我們知道如果要移植Android,初步要瞭解Linux的開機流程,因為Android並未修改Linux的開機流程,要知道Android是由/init把整個系統帶起來,所以如果要瞭解Android的整個啟動流程,就從/init的原始碼下手。Android由/init讀取/init.rc,/init.rc中記載要執行哪些service、掛載檔案系統、設定檔案權限等相關系統初始化及設定的動作,因此一般要將Android移植到實際硬體平台,會需要改動/init.rc。

試圖讓Android在實際硬體平台上執行的過程中,如果遇到問題,無法讓Android順利地執行,可以使用logcat顯示Android的run-time資訊,透過訊息提示,使用find + grep,找到問題的源頭或是產生錯誤的原因,接著嘗試解決問題,因為移植過程中可能面臨到不同的問題,所以移植Android的必備條件是知道追蹤原始碼的方法,在具備追蹤原始碼的能力下,移植Android便與能力無關,而是與心態有關,因為唯有細心及謹慎,才有機會成功移植Android。所以移植Android並不困難,重點是複雜,但若是具備追蹤原始碼的能力,撇開時間及人力成本的考量,相關問題應該皆可迎刃而解。

移植前期可能需要解決的問題大概只有三個:
1. init.rc
2. LCD + Framebuffer
3. Battery

init.rc依照平台需求去做修改。
LCD盡可能設定成16bit,Framebuffer使用double framebuffer。
Battery的部份,將電池資訊修改成正常狀態。

至於Android的Input System,因為Android在設計上採用動態偵測輸入裝置的方式,所以應該不會遇到太大問題。

其它應該不會遇到太大問題,但是移植後期要讓所有功能都能夠正常運作的話,可能非一己之力能夠完成。現在已經不像從前,不是一人搞定一切的年代,就算有這種人,這樣的開發模式也不可能長久,如今都是用團體戰的方式,不需要一個能力很強,但是沒有辦法跟別人co-work的人,需要的是整個team,每個人都強一點點,這樣整個team就會極具競爭力,而和平的開發方式,是讓一個team走的長遠的要件之一。

以Android 1.0為例,
下圖為Android的WindowManager、PowerManager、Input System、電池及電源關係圖:

下圖為Android如何取得電池資訊的流程圖,包含從上層Application Framework,透過JNI至native code,再到Linux device driver,最後存取實體電池的資訊。

結論:
凡事起頭難,移植Android最難的一點,就是不知從何下手,原因不外乎缺少文件、文件錯誤、Android原始碼過於龐大、缺乏經驗等等,而Using high level view on Android Porting是移植Android的一條捷徑,重點在於掌握移植的大方向,先忽略(不管)細節的部份、熟悉Embedded Linux的軟體架構、了解Linux的開機流程、善用工具、知道如何追蹤Linux kernel及Android原始碼,歸納以上重點,我們可以得到一個移植Android的依循方向,不要因為原始碼過於龐大及複雜,而模糊了移植的大方向,不要因為周圍複雜且不重要的事物,而遮蔽了眼前的視線,這樣會讓你在死胡同中繞不出來;如果能夠掌握以上重點,將未知的部份當成黑箱,試圖去解決在移植過程中所面臨的問題,理當可以針對移植Android至實際硬體平台有所助益。

作者簡介:
Mask(鍾文昌)現為Android及Embedded Linux的自由工作者,從事數年Linux及Embedded Linux的相關開發工作,產品包含Set-Top-Box,智慧型手機及快速開機軟體等相關產業. 具有豐富的Android移植實務經驗,致力開設高品質的Android移植實務課程,2009年12月開設台灣第一個上機實作Android移植實務課程,帶領學員實際移植Android至OMAP3530. 2009年7月發表台灣第一篇開放Android移植流程及原始碼的學術性論文,至今已累積上千人次下載。

本文出處: http://www.mask.org.tw/ by 鍾文昌 Mask

引用 mask
較新的 較舊