官术网_书友最值得收藏!

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的方式編譯單個模塊。

主站蜘蛛池模板: 清苑县| 沾益县| 台北县| 历史| 上思县| 石柱| 青铜峡市| 丘北县| 饶河县| 丰县| 余姚市| 佛坪县| 永福县| 永寿县| 十堰市| 莒南县| 交城县| 鸡东县| 柘城县| 南陵县| 罗定市| 崇阳县| 古田县| 巴青县| 庆元县| 云浮市| 贺兰县| 宜丰县| 盐源县| 南部县| 玉树县| 大宁县| 杭州市| 和龙市| 洪雅县| 德江县| 会理县| 汉川市| 南川市| 长垣县| 玉山县|