- Android Telephony原理解析與開發指南
- 楊青平
- 2777字
- 2019-10-23 17:46:39
2.4 在Google手機上調試Android源碼
2.4.1 Google手機對應編譯選項
Google手機至今已經發布了很多款,目前最新發布的是Google Pixel 2。本書選擇Nexus 6P作為實例,讀者也可以選擇其他Google手機調試Android源碼。
Google手機對應的代碼名稱、編譯選項詳情見表2-2。
表2-2 Google手機編譯選項表代碼名稱

2.4.2 Google手機刷入工廠鏡像
首先下載Google Nexus和Pixel系列手機的工廠鏡像文件。Nexus 6P手機對應的工廠鏡像是angler 8.1.0 (OPM1.171019.011, Dec 2017),即Nexus 6P手機Android 8.1.0工廠刷機鏡像。
$ unzip angler-opm1.171019.011-factory-39448337.zip $ tree angler-opm1.171019.011 angler-opm1.171019.011 ├── bootloader-angler-angler-03.78.img ├── flash-all.bat ├── flash-all.sh ├── flash-base.sh ├── image-angler-opm1.171019.011.zip └── radio-angler-angler-03.85.img 0 directories, 6 files
image-angler-opm1.171019.011.zip壓縮包中包含了android-info.txt、boot.img、recovery.img、system.img、vendor.img等鏡像文件。
先將Nexus 6P手機關機,然后同時按下電源鍵和音量鍵兩個按鍵,持續幾秒不要松開,就可以進入fastboot刷機模式。
$ sudo –s //一定要使用root賬號刷機,否則沒有權限,fastboot刷機將失敗 # fastboot flashing unlock//或者fastboot flashing unlock_critical對Pixel 2 XL有效 # ./flash-all.sh ...... sending sparse 'system' 5/5 (51472 KB)... OKAY [ 1.704s] writing 'system' 5/5... OKAY [ 0.743s] sending 'vendor' (192545 KB)... OKAY [ 6.143s] finished. total time: 104.914s
等待Nexus 6P手機重啟完成,我們便可以體驗和使用原汁原味的Android 8.1.0系統了,詳情如圖2-6所示。

圖2-6 Nexus 6P開機向導和Android 8.1.0版本信息
2.4.3 編譯本地鏡像并刷入Google手機
Google手機刷入工廠鏡像文件是如此得簡單方便,但我們需要調試Android源碼,僅刷入工廠鏡像是無法辦到的,因為它是用戶版本的,無法調試系統級源碼;因此還需要刷入本地編譯出來的userdebug版本鏡像文件,主要的步驟如下:
1. 下載Google手機對應的驅動文件(Driver Binaries)
到官網下載Google手機對應的驅動文件,選擇Nexus 6P ("angler") binaries for Android 8.1.0 (OPM1.171019.011)的兩個Driver文件:Vendor image和Qualcomm,對應的文件名分別是huawei-angler-opm1.171019.011-41db8ed5.tgz和qcom-angler-opm1.171019.011-f7e511bb.tgz,解壓后是兩個Shell腳本:extract-huawei-angler.sh和extract-qcom-angler.sh,將這兩個文件復制到Android O源碼的主目錄下。
2. 將驅動文件導入到Android 8.1.0源碼工程中
$ cd $oreo $ ./extract-huawei-angler.sh //運行自解壓腳本,并接受License $ ./extract-qcom-angler.sh //運行自解壓腳本,并接受License //將在當前目錄下生成vendor目錄,其中包括了華為和高通的二進制文件和對應的編譯腳本 $ tree vendor -L 3 vendor ├── huawei │ └── angler │ ├── android-info.txt │ ├── BoardConfigPartial.mk │ ├── BoardConfigVendor.mk │ ├── device-partial.mk │ ├── device-vendor.mk │ └── proprietary └── qcom └── angler ├── BoardConfigPartial.mk ├── device-partial.mk └── proprietary
3. 使用angler編譯選項重新編譯
前面編譯Android源碼時,lunch選項選擇的是aosp_arm64-eng。而現在導入Nexus 6P的驅動文件后,編譯Nexus 6P手機對應的鏡像文件時,lunch需要選擇aosp_angler-userdebug,并以全新的方式編譯整個代碼,最簡單的方式就是刪除保存編譯結果的out目錄。
$ rm –rf out $ source build/envsetup.sh //或者. build/envsetup.sh, //使用第二種方法需要注意build前有一個空格 including device/asus/fugu/vendorsetup.sh including device/generic/car/vendorsetup.sh including device/generic/mini-emulator-arm64/vendorsetup.sh ...... including device/huawei/angler/vendorsetup.sh including device/lge/bullhead/vendorsetup.sh including sdk/bash_completion/adb.bash $ lunch You're building on Linux Lunch menu... pick a combo: ...... 28. aosp_angler-userdebug 29. aosp_bullhead-userdebug 30. aosp_bullhead_svelte-userdebug 31. hikey-userdebug 32. hikey960-userdebug Which would you like? [aosp_arm-eng] aosp_angler-userdebug//選擇Nexus 6P對應的編譯選項 ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=8.1.0 //Android O版本 TARGET_PRODUCT=aosp_angler //lunch選擇aosp_angler-userdebug TARGET_BUILD_VARIANT=eng ...... BUILD_ID=OPM1.171019.011 //編譯號 OUT_DIR=out AUX_OS_VARIANT_LIST= ============================================ $ make –j8
4. fastboot刷入本地編譯出的鏡像文件
首先進入fastboot刷機模式,然后使用Android SDK中的fastboot工具刷入鏡像文件,詳情操作如下:
$ sudo –s //一定要使用root賬號刷機,否則沒有權限,fastboot刷機將失敗 # fastboot flash boot boot.img # fastboot flash system system.img # fastboot flash vendor vendor.img # fastboot flash userdata userdata.img # fastboot reboot
等待手機完成重啟后,驗證本地編譯的Android O系統:
Android Version:8.1.0 Builder Number:aosp_angler-userdebug 8.1.0 OPM1.171019.011 eng.androi20171210. 102134test-keys
? aosp_angler_userdebug——即Nexus 6P手機的userdebug版本。
? eng.androi engineer——工程模式,編譯環境的用戶名android(因長度限制少了字母d)。
? 20171210.102134——2017年12月10日10點21分34秒開始編譯。
? test-keys——系統鏡像的簽名使用test-keys密鑰。
詳情如圖2-7所示。

圖2-7 Nexus 6P刷入本地編譯的Android 8.1.0 userdebug系統
2.4.4 Google手機上調試Android源碼
1. Android Studio導入Android O源碼
首先,編譯出idegen.sh腳本依賴的jar包:idegen.jar,操作詳情如下。
$ mmm development/tools/idegen/ //編譯idegen.jar [100% 3/3] Install: out/host/linux-x86/framework/idegen.jar $ development/tools/idegen/idegen.sh //當前代碼主目錄下將生成android.iml和android.ipr兩 //個Android Studio的工程配置文件 Read excludes: 15ms Traversed tree: 70465ms
接著,打開Android Studio,進入Open an existing Android Studio project,選擇android.ipr文件,開始導入Android O源碼。
注意
不同的計算機處理能力不同,導入的時間也不同,需要耐心等待一段時間,由Android Studio準備Android等相關插件工具,以及建立工程的代碼文件索引,以提升后續的操作性能。
2. 修改代碼模塊編譯
本例選擇com.android.phone進程加載的代碼入口文件PhoneApp.java作為修改實例,其相對路徑為:packages/services/Telephony/src/com/android/phone/PhoneApp.java。
在Android Studio連續快速地兩次按下右Shift鍵,輸入PhoneApp.java將快速匹配出該文件。在代碼的onCreate方法中增加一行打印日志的代碼,來驗證代碼修改后是否能成功運行在Google手機上,代碼修改和編譯詳情如下。
@Override public void onCreate() { android.util.Log.d("Android", "My Code run on the Nexus 6P"); ...... } $ cd $oreo $ mmm packages/services/Telephony/ [100% 10/10] Install: out/target/product/angler/system/priv-app/TeleService/TeleService.apk
3. 掛載手機
前面成功編譯了TeleService.apk文件,需要將此文件push到Nexus 6P手機上運行,在此之前還需要掛載手機,只有掛載成功以后才能push apk系統應用、系統jar包、so動態鏈接庫等文件到手機/system掛載點。具體操作如下:
$ adb root restarting adbd as root $ adb remount dm_verity is enabled on the system partition. Use "adb disable-verity" to disable verity. If you do not, remount may succeed, however, you will still not be able to write to these volumes. remount succeeded $ adb disable-verity Verity disabled on /system Now reboot your device for settings to take effect//需要重啟手機 $ adb reboot $ adb root restarting adbd as root $ adb remount $ remount succeeded
注意
掛載成功的手機系統重啟以后,掛載的狀態會失效,需要再做一次掛載操作。
4. push模塊并重啟應用
手機掛載成功以后,接著就要開始push應用到手機上;TeleService模塊編譯成功后的日志,只提示我們安裝out目錄下的TeleService.apk文件,其實還要安裝dex相關的文件,修改才能在手機上生效。
進入out/target/product/angler/system/priv-app/TeleService/目錄查證編譯后文件更新的情況,除TeleService.apk文件更新了,oat目錄也同時更新了,該目錄下的TeleService.odex和TeleService.vdex這兩個文件同樣需要安裝到Nexus 6P手機上對應的目錄,否則我們的修改不會生效。具體操作如下:
$ tree out/target/product/angler/system/priv-app/TeleService/oat out/target/product/angler/system/priv-app/TeleService/oat └── arm64 ├── TeleService.odex └── TeleService.vdex $ adb push out/target/product/angler/system/priv-app/TeleService/TeleService.apk /system/priv-app/TeleService/ out/target/product/angler/system/priv-app/TeleService/TeleService.apk: 1 file pushed. 21.0 MB/s (7691558 bytes in 0.350s) $ adb push out/target/product/angler/system/priv-app/TeleService/oat /system/priv-app/TeleService/ //重點關注push的目錄沒有oat out/target/product/angler/system/priv-app/TeleService/oat/: 2 files pushed. 10.9 MB/ s (2032058 bytes in 0.178s) $ adb reboot //重啟手機或是“殺死” com.android.phone進程重啟應用
注意
請讀者使用adb shell命令進入手機中對應的目錄,通過修改時間和文件大小來查看push的文件是否已經成功更新,同時關注push的oat目錄是否在/system/priv-app/TeleService/oat目錄下再次生成了oat目錄。
5. 日志驗證代碼修改內容
$ mlog |grep -i "nexus 6p"http://mlog -s Android 02-26 00:01:28.077 4671 4671 D Android : My Code run on the Nexus 6P
“02-26 00:01:28.077”:以手機上時間為準的時間戳。
“Android”:打印日志的TAG。
“My Code run on the Nexus 6P”:日志打印內容。
至此,我們已經成功搭建了Android源代碼調試環境,從Android官網下載Android 8.1.0源碼、Android Studio、Android SDK以及Nexus 6P手機對應的工廠鏡像和驅動文件,然后成功編譯本地鏡像文件,刷入Android 8.1.0 userdebug版本的angler手機鏡像文件,最后修改TeleService模塊代碼,編譯后push到Nexus 6P手機上驗證我們的代碼修改是否生效。
2.4.5 關鍵問題總結
搭建Android源代碼調試環境的環節眾多,時間開銷大,任何小細節出現問題都將無法滿足要求,因此,作者總結出編譯Android源碼過程中自己碰到的兩個非常關鍵的問題:Jack內存溢出和模塊編譯失敗。
1. Jack編譯器內存溢出
[ 0% 38/54562] Building with Jack: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/with-local/classes.dex FAILED: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/with-local/classes.dex /bin/bash out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/with-local/classes.dex.rsp Out of memory error (version 1.3-rc6 'Douarn' (441800 22a11d4b264ae70e366aed3025ef47362d1522bb by android-jack-team@google.com)).
Jack編澤器內存不足,需要修改配置文件以增加編譯器內存大小。修改源碼目錄下的prebuilts/sdk/tools/jack-admin文件,其中有兩個參數:JACK_SERVER_VM_ARGUMENT和JACK_SERVER_COMMAND,本例中添加-Xmx4096M(配置的內存大小可根據自己計算機實際內存大小進行調整),最后執行make clean、make -j8命令重新編譯。
JACK_SERVER_VM_ARGUMENTS="${JACK_SERVER_VM_ARGUMENTS:=-Dfile.encoding=UTF-8 -Xmx4096M}" JACK_SERVER_COMMAND="java -XX:MaxJavaStackTraceDepth=-1 -Xmx4096M -Djava.io.tmpdir= $TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME" $ ps -ef|grep jack android 25499 2315 99 17:11 pts/0 00:01:59 java -XX:MaxJavaStackTraceDepth= -1 -Djava.io.tmpdir=/tmp -Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096M -cp /home/android/.jack-server/launcher.jar com.android.jack.launcher.ServerLauncher //修改了配置仍然沒有生效,可以通過ps命令查看jack進程信息,手工“殺死”對應的進程,再重新執行編譯命令
2. 模塊編譯失敗
Android 8.1.0源碼在使用mmm方式編譯TeleService單個模塊時,packages/services/Telephony/目錄下包含了與測試相關的應用,但因為android-support-test Libraries依賴關系的缺失,將導致編譯失敗,錯誤信息如下:
ninja: error: 'out/target/common/obj/JAVA_LIBRARIES/android-support-test_intermediates/classes.dex. toc', needed by 'out/target/common/obj/APPS/TeleServiceTests_intermediates/with-local/ classes.dex', missing and no known rule to make it
因此,我們只需要做簡單的修改,比如在packages/services/Telephony/目錄下將tests/和testapps/兩個目錄移除或是將這兩個目錄下的Android.mk文件改名為Android.mk.bak,總之與測試相關的應用或jar包不進行編譯。
或者不做任何改動,直接使用make TeleService的方式編譯單個模塊。
- BPEL and Java Cookbook
- SOA實踐者說
- 高性能Linux服務器構建實戰:運維監控、性能調優與集群應用
- 開源安全運維平臺OSSIM疑難解析:入門篇
- 嵌入式Linux驅動程序和系統開發實例精講
- 奔跑吧 Linux內核(入門篇)
- 零基礎學鴻蒙PC:新一代國產操作系統
- 直播系統開發:基于Nginx與Nginx-rtmp-module
- Application Development in iOS 7
- Vim 8文本處理實戰
- 分布式系統設計實踐
- Linux系統最佳實踐工具:命令行技術
- Learn CUDA Programming
- Drupal 7 Cookbook
- OpenHarmony開發與實踐:基于紅莓RK2206開發板