1. 程式人生 > >Android原始碼編譯之Nexus5真機編譯

Android原始碼編譯之Nexus5真機編譯

轉載:https://blog.csdn.net/liu1075538266/article/details/51272398

1.   前言

在Android安全的研究工作中,我們時常要對Android進行改進並對其進行原始碼編譯,由於目前幾乎所有的手機廠商均對其底層驅動實行封閉政策,導致我們在完成Android編譯後無法將我們編譯好的系統刷到普通的Android手機上,因此在一般的科學實驗中我們更多的是將修改好的android原始碼編譯成模擬器,以模擬器的形式證明實驗的成功與否。

事實上,Android作為一款開放原始碼的移動裝置作業系統,Google最初就考慮到了真機編譯的問題,而關於這個問題的解決方案體現在每次Google I/O大會發布的官方手機,即Nexus系列手機上。Nexus系列手機作為Google釋出的Android標杆機,不僅在一定程度上代表和引領了該年度的Android手機發展方向,更解決的開發者真機編譯原始碼的問題。此係列裝置採用了完全開放裝置的層驅動的形式使得開發者可以實現將自己的原始碼燒錄到真機的功能,從而使得原始碼編譯真機除錯不再是難題。下面,我就來介紹一下這項工作是如何完成的。

2.   實驗環境與裝置

實驗裝置:Nexus5(日版 D821)。

實驗環境:Ubuntu14.04 (x64) + JDK 1.7 + python 2.7.6 + make 3.81

3.   準備工作

首先要宣告的一點是,這是一部零基礎教程,上述實驗環境是作者電腦最初的狀態,它不一定符合我們此次試驗的要求,因此會在後面逐步完善實驗環境,這樣寫的目的也是為了將我在實驗中所遇到的問題以及解決方案原原本本展示給大家,讓大家少走一些彎路。

3.1.  對編譯環境的一些準備

我們參照android opensource project官網(http://source.android.com/source/requirements.html)上的guide來進行實驗,在AOSP的guide中對編譯的硬體要求和軟體要求做出了詳細的規定。此次我們要編譯的原始碼是Android 4.4.x版本,根據官網中的資訊,我們要使用64位Ubuntu進行編譯,並且至少有100G的磁碟空間;在軟體方面,由於我們編譯的是4.4.x (Kitkat) 版本的原始碼,因此需要JDK 1.6,除此之外,official guide中還有一些其他要求:Python2.6 -- 2.7,GNU Make 3.81 -- 3.82,Git1.7 or newer(這裡我們不需要配置git,因為在officialguide中原始碼的獲取是通過git + repo線上下載完成的,而我們採取另一種方式獲取原始碼)。

在我的編譯環境中,作業系統為64位Ubuntu 14.04,磁碟空間預留100G,JDK版本為1.7,make 版本3.81,python 版本2.7.6。

現在我們可以發現,java環境的版本比要求的jdk 1.6要高,因此下面,我們需要進行jdk的降級工作。

首先我們要找到jdk 1.6的包,目前在oracle的官方網站上已經無法下載了,只能自己百度。在此我提供一個jdk 1.6 for Linux x64的安裝包供大家使用:http://pan.baidu.com/s/1c2e8x6S

Jdk 1.6的安裝包是一個bin檔案,我們需要先安裝它。

把這個檔案放到你自己定義的地方,這裡我放到了Home下的java檔案裡,當然也可以放在別的地方。首先要修改這個檔案的許可權,否則直接安裝會報錯,系統會告訴你許可權不夠。

chmod 777 jdk-6u45-linux-x64.bin

修改完許可權後就可以執行安裝了。

./jdk-6u45-linux-x64.bin

這個過程其實就是生成了jdk的目錄。

Jdk1.6的目錄生成後,我們需要修其改環境變數,原有的java變數是在/etc/profile中配置的,在此只需要修改此檔案中的環境變數就可以了。

修改之後只需使/etc/profile生效即可。

source /etc/profile

執行這個命令之後,重啟。

然後我們可以檢視一下是否生效:java –version

修改成功!

有的環境中可能會出現make版本不符合要求的情況,針對這種情況可以參考這篇部落格:http://blog.csdn.net/lr2131/article/details/45673603(內附make下載地址和安裝指南)。

另外,在編譯環境的配置上,我們還需要安裝一些依賴包,Google在AOSP official guide 中已經給出了不同版本的Ubuntu需要安裝哪些依賴(http://source.android.com/source/initializing.html),摘錄如下:

3.2.  對原始碼和驅動版本的一些準備

在準備好了編譯環境後,我們就該準備要編譯的原始碼了。此次實驗的目標是將Android4.4.x編譯後燒錄到Nexus 5上,由於Google的官方裝置目前已經更新至第七代,而且種類繁多,不僅有智慧手機,還有平板電腦,智慧手錶,膝上型電腦等其他智慧裝置,而且不同代次的裝置所相容的原始碼版本也是處在一定範圍內的。因此,Google對Android原始碼構建了種類繁多而又詳細的分支,使其分別適配不同的裝置,例如:分支android-5.1.1_r3( build: LMY48B )只支援Nexus 5,而android-5.1.1_r1(build: LMY47V )支援的是Nexus 7 (flo/grouper), Nexus 10, Nexus Player;由於存在不同的運營商定製版裝置,不同的運營商定製的裝置甚至都不能共用一個分支的原始碼,例如:android-5.1.1_r4( build: LMY47Z )支援除T-Mobile美國之外的所有Nexus6裝置,而T-Mobile定製版本的Nexus 6裝置則需要android-5.1.1_r5( build: LYZ28E )分支來支援。綜上所述,我們可以得出結論,在真機編譯中,選擇正確的原始碼分支至關重要,否則一旦沒有選擇對,耗費了大量的時間進行編譯,即便燒錄到真機中也會出現開不了機的情況(最常見的就是手機開機後卡在Google的開機介面中)。

首先,我們需要確定我們的裝置所對應的原始碼分支是哪一個,我的裝置是日版Nexus 5 (即D821)Nexus 5手機只分兩個大的版本:D820和D821,D820是面向美國本土發售的機型,俗稱美版,D821是除美版之外的所有版本,即所謂亞太版。當然,在不同國家和地區也會有不同的運營商定製版本,針對這種情況也要注意,看看有沒有對應專有的原始碼分支。我們可以通過http://source.android.com/source/build-numbers.html來查詢自己的裝置屬於對應的原始碼分支,由於我們要編譯的是Android 4.4.x版本的原始碼,因此只列出此版本的分支與裝置的對應關係:

先來解釋一下表格中每一列代表什麼:

第一列是build程式碼,我們根據build碼查詢對應裝置的驅動程式,並下載之。

第二列是分支(branch)程式碼,不同的分支會對應不同的裝置。

第三列是Android版本代號,這裡我們關注的是4.4系列的版本,因此是KitKat。

第四列是對應的裝置名稱,值得注意的是,同一裝置即便是不同運營商釋出的也可能使用不同分支的原始碼,例如android-4.4.4_r2就是隻針對上述運營商的定製版本的分支,而r1就支援其餘的Nexus 5裝置。

這裡,我們選擇android-4.4.4_r1進行編譯,因為它支援我的裝置。注意要記住這個分支的build號:KTU84P,後面我們要用這個碼查詢對應的裝置驅動並下載。

Official guide中獲取原始碼的方式是通過git+ repo的方式線上獲取,而由於Android原始碼的網站https://android.googlesource.com/在正常情況下無法訪問,因此我們不採取官方提供的方式獲取原始碼。事實上,我們在百度上查詢一下就會發現有很多已經下載並打包好的安卓原始碼,比如百度網盤中就有很多,我也是從百度網盤上找到的,在此分享一下我所需原始碼的連結,供大家下載使用:http://pan.baidu.com/s/1skJjkfj。注意,在解壓時最好是在Linux下直接解壓,切勿在Windows環境中使用圖形化工具,如2345好壓。親測證明,使用圖形化介面解壓會導致原始碼中缺失檔案和資料夾。我提供的原始碼是一個7z格式的壓縮包,在Linux下解壓此種格式的檔案的方法可參見:http://www.educity.cn/linux/1241489.html

在編譯工作開始之前,我們可以使用編譯器快取記憶體工具complier cache(ccache)來加快編譯速度。首先,我們在環境變數中加入:

export USE_CCACHE=1

並使環境變數檔案生效。然後,我們在命令列執行

prebuilts/misc/linux-x86/ccache/ccache -M 50G

即可。

下載好原始碼之後,我們要將驅動檔案加入原始碼中。我們可以在https://developers.google.com/android/nexus/drivers#hikey中找到對應裝置與原始碼分支的硬體驅動。此時,上一步中的build碼就該派上用場了,我們根據build碼來找到對應的驅動程式,我們剛才選擇的原始碼分支所對應的build碼是KTU84P,因此,就下載此代號的驅動程式即可。

下載得到的是三個tgz檔案,我們只需依次解壓三個檔案,得到的是三個shell指令碼檔案,我們先將其置於原始碼根目錄中。

依次執行這三個指令碼檔案,這裡要注意,三個指令碼檔案的作用是生成驅動檔案,但是在執行操作前,它會讓你閱讀相關協議,你必須一直按enter鍵一行一行往下讀,更不能一鍵摁到底,因為程式在最後會讓你輸入“I ACCEPT”,如果你一鍵摁到底,也就是說最後一步也摁enter鍵的話它就會執行預設操作,即不接受此協議,那生成驅動檔案的操作就不會執行。這裡有個小竅門,一直摁住enter,注意命令列中閃過的協議項,當讀到第八項時可以放慢速度,一下一下的摁enter鍵了,最後慢慢的到最後一步,輸入I ACCEPT即可。這三個檔案都是這樣的操作流程。上圖展示了在執行完指令碼檔案後生成的驅動檔案目錄。

4.   編譯

在完成了以上任務之後,我們就可以進行原始碼的編譯工作了。首先,我們在terminal中進入Android原始碼所在目錄,我就把我的原始碼放在了Home下。

初始化編譯環境,輸入

. build/envsetup.sh

會出現這樣的效果。

載入機型,輸入lunch命令,會列出不同裝置可能編譯出的結果。

在這一步中,我們選擇6號:aosp_hammerhead_userdebug,因為我們的Nexus 5裝置代號就是hammerhead。

aosp則代表著編譯出的系統是純淨的、沒有Google服務框架的。而buildtype也分為user、userdebug和eng,具體區別見下圖。

在選擇好裝置之後,系統會生成詳細的編譯資訊,這裡我們可以再確認一下原始碼的分支,build號是否正確。

然後我們就可以進行編譯了,輸入make –j16 或make –j8,j後面的引數取決於你電腦處理器的核心數,j=核心數*2,由於我的電腦是8核的,因此我選擇

make –j16

在經過將近三個小時的編譯後,我們的原始碼終於編譯完成,而此時,在原始碼根目錄中多出了一個out目錄,編譯的結果就存放在裡面。

5.   刷機

原始碼編譯完成後,我們開始將編譯好的系統燒錄進手機中。首先,先將我們的Nexus 5連線到電腦上,注意一定要開啟USB除錯,連線後手機可能會提示電腦要除錯這臺手機,允許即可。然後,我們令手機進入recovery模式,還是剛才的terminal(在原始碼根目錄下),輸入以下命令:

sudo adb reboot bootloader

隨後手機就會進入recovery模式。

然後,我們開始刷機:

fastboot flashall –w  或者 fastboot -w flashall

刷機的過程大概在一至兩分鐘左右,刷機結束後會自動開機。

 刷機成功,我們看到了我們編譯好的原生aosp版本的原始碼。