哪家公司建網(wǎng)站好推廣代理平臺(tái)
Android 12 源碼分析 —— 應(yīng)用層一(SystemUI準(zhǔn)備篇)
在接下來的時(shí)間中,將會(huì)使用Pixel 3(blueline)作為研究對象,選用AOSP的android-12.0.0_r34分支作源代碼。
先從android的應(yīng)用層進(jìn)行探析,然后慢慢深入android的framework,接著進(jìn)入android的hal層,最后以android的linux內(nèi)核結(jié)束,期間可能會(huì)穿插一些其他文章如android的art虛擬機(jī)分析等。
本文是整個(gè)系列的第一篇,但是在此之前,請務(wù)必閱讀以下的文章,他們將在以后的源碼分析中時(shí)不時(shí)出場
- android 如何分析應(yīng)用的內(nèi)存(二)——xdd,gdb命令行(http://t.csdn.cn/RENbG)
- android 如何分析應(yīng)用的內(nèi)存(三)——LLDB命令行(http://t.csdn.cn/Vpw8e)
- android 如何分析應(yīng)用的內(nèi)存(四)——Visual studio code的LLDB(http://t.csdn.cn/8ZM8A)
- android 如何分析應(yīng)用的內(nèi)存(十四)——jdb命令行(http://t.csdn.cn/99r2G)
- android 如何分析應(yīng)用的內(nèi)存(十五)——Visual Studio Code 調(diào)試Android應(yīng)用(http://t.csdn.cn/dWeF5)
上面列出的文章,是關(guān)于如何使用gdb,lldb,jdb進(jìn)行android源碼級(jí)別的調(diào)試。它在沒有IDE的情況下非常有用。
本文作為應(yīng)用層的開篇之作,選取SystemUI作為研究對象。
為什么選取SystemUI?
在Android的應(yīng)用層有很多應(yīng)用可以進(jìn)行源碼分析,如Launcher,Camera,Gallery,Bluetooth,SIM,telephony,Settings等等應(yīng)用,綜合考慮到SystemUI可能是定制比較多的一個(gè)模塊,因此,對其進(jìn)行仔細(xì)的分析。
本文的首要目標(biāo)是——搭建分析SystemUI的環(huán)境——如何使用Android Studio進(jìn)行AOSP的開發(fā)和調(diào)試
注意:在使用Android studio時(shí),對pc的性能有一定的要求,如果pc性能確實(shí)不夠,可以參考前面列出的5篇文章,使用VS code進(jìn)行替代。在前面5篇文章中,未提及如何搭建java工程,只提及了如何調(diào)試。讀者可參考其他關(guān)于:Extension Pack for Java插件的使用。搭配前面的5篇調(diào)試文章,也可以進(jìn)行AOSP的開發(fā)。
如何使用Android Studio進(jìn)行AOSP的開發(fā)和調(diào)試
要使用Android Studio進(jìn)行SystemUI的編輯工作,需要進(jìn)行如下的配置:
- 使用AOSP源碼中aidegen工具,構(gòu)建依賴模塊
- 使用AOSP源碼中的JDK
- 使用AOSP源碼中的SDK
- 如何讓AndroidManifest.xml和各種資源xml能相互引用
- 如何修改靜態(tài)代碼分析工具lint,以解決IDE中各種標(biāo)紅的錯(cuò)誤(實(shí)際非錯(cuò)誤)
- 如何使用Android studio單步調(diào)試SystemUI
接下來我們依次解決上面的步驟。
使用aidegen工具,構(gòu)建依賴模塊
在aosp源碼中,加載完編譯環(huán)境之后,即運(yùn)行下面的命令之后:
. build/envsetup.sh
lunch
aidegen即可使用。
接下來使用aidegen工具,產(chǎn)生能在as中打開SystemUI的工程配置文件。如下:
aidegen SystemUI -i s -p /media/wanbiao/disk1t/root/IDE/android-studio/bin
# SystemUI:表示要生成工程文件的模塊
# -i s:表示生成的工程文件對應(yīng)的IDE為Android studio。
# j=IntelliJ s=Android Studio e=Eclipse c=CLion v=VS Code
# -p <路徑>:表示對應(yīng)的IDE的安裝路徑,在生成工程文件完成之后,會(huì)自動(dòng)打開IDE
# 其他常見選項(xiàng)如下:
# -n:表示不用打開IDE
# -s:表示跳過編譯各種依賴,如果以前運(yùn)行過make等命令,可以添加-s
# -e:表示排除一些目錄,這個(gè)非常有用,尤其是大型模塊
# -d:源碼引用的模塊的深度
# -r:重置所有的aidegen保存的配置
# -v:顯示debug級(jí)別的log
# -a:生成整個(gè)Android 源碼樹的工程文件
# -l:用指定的語言打開IDE,j=java,c=c/c++,r=Rust
# -h:打開幫助
成功運(yùn)行之后,會(huì)得到如下的圖片
在frameworks/base/package/SystemUI目錄下,會(huì)出現(xiàn)一下幾個(gè)文件:
- .idea文件夾,Android studio使用的工程文件夾,里面可以配置有多少個(gè)模塊,從上圖可以看到,有三個(gè)模塊分別為:R,SystemUI,dependencies
- SystemUI.iml:配置SystemUI模塊的配置文件
- dependencies.iml:配置dependencies模塊的配置文件
接下來我們將要對上面的模塊進(jìn)行JDK和SDK的配置。這樣as才能正確地在java類之間跳轉(zhuǎn)。
使用AOSP源碼中的JDK
可以使用which javac命令,查看具體的jdk路徑如下:
然后打開Android studio,將這個(gè)jdk加入配置中,
- File->Project Structure
- 按照下圖進(jìn)行配置
如上圖,我們選擇了aosp目錄中的jdk,并將這個(gè)jdk配置命名為:aosp-jdk11
接下來配置sdk
使用AOSP源碼中的SDK
在android-12.0.0_r34分支中,默認(rèn)并不會(huì)編譯SDK,因此,運(yùn)行下面的命令進(jìn)行源碼的編譯。
. build/envsetup.sh
lunch
make sdk -j8
在Android的編譯過程中,可能會(huì)報(bào)錯(cuò),例如:module can not be located。又或者xxx文件不存在。
解決辦法:只需要找到對應(yīng)的報(bào)錯(cuò)文件,然后打開查看對應(yīng)的module是否存在,如果不存在,就修改成正確的路徑。當(dāng)然也可簡單粗暴的注釋掉報(bào)錯(cuò)行,前提是:能夠確定該行不會(huì)影響SDK的功能。
編譯成功之后,將會(huì)在如下路徑中出現(xiàn):
./out/host/本機(jī)平臺(tái)/sdk/aosp_blueline/android-sdk_eng.wanbiao_linux-x86
然后按照如下所示,添加SDK。
注意:在上圖中,要保證SDK內(nèi)部使用的JDK為我們前面配置的JDK即,aosp-jdk11.同時(shí)build target請確保為Android API 31.
將SDK和JDK與SystemUI項(xiàng)目相關(guān)聯(lián)
上面兩個(gè)步驟只是添加了對應(yīng)的SDK配置和JDK配置,但是還未與SystemUI相關(guān)聯(lián)起來,參照如下步驟,進(jìn)行關(guān)聯(lián)
接下來將項(xiàng)目下的各個(gè)模塊,也配置好SDK,如下圖
在點(diǎn)擊完,apply之后,會(huì)出現(xiàn)一段時(shí)間的indexing…請等待片刻。
至此,as已經(jīng)具備,編輯和跳轉(zhuǎn)java代碼的功能。在進(jìn)行xml資源配置之前,我們需要先解決幾個(gè)問題
如下:
- 如何正確跳轉(zhuǎn)到源碼中,而不是跳轉(zhuǎn)到SDK中
- 源碼中的重復(fù)文件該怎么操作
如何正確跳轉(zhuǎn)到源碼中
在上面的配置中,如果我們跳轉(zhuǎn)源碼,將會(huì)首先跳轉(zhuǎn)到SDK中。為了能夠成功跳轉(zhuǎn)到我們的源碼中而不是SDK中
可以有如下兩種辦法:
- 修改依賴的優(yōu)先級(jí)
- 去掉sdk中的android.jar
兩種辦法都需要修改,project structure.我們用如下的圖片來講解兩種辦法
第一種辦法:
第一種辦法通常需要經(jīng)常修改,因?yàn)閍s經(jīng)常會(huì)將sdk移動(dòng)到高優(yōu)先級(jí)
第二種辦法:
經(jīng)過上面的配置,就可以正確的跳轉(zhuǎn)到源碼中的位置了
如何處理重復(fù)文件
我們處理重復(fù)文件,通過將其文件夾標(biāo)記為exclude 目錄即可,如下圖
上圖將Stub模塊下的重復(fù)的SystemProperties.java排除在了source file之外。
注意:添加exclude 文件夾,除了上面的右鍵以外,還可通過對應(yīng)的.iml文件添加如下的格式:
<content url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub"><sourceFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub" isTestSource="false" /><excludeFolder url="file://$MODULE_DIR$/../../../../system/tools/sysprop/stub/android/os" />
</content>
再次注意:除了上面兩種方法,還可以通過打開project structure進(jìn)行修改,如下圖
配置Android
上面的處理,只能進(jìn)行java代碼之間的跳轉(zhuǎn)和配置,我們還需要進(jìn)行AndroidManifest.xml和資源文件的處理。進(jìn)行如下配置。
-
添加Android
-
選擇清單文件和資源文件夾。其中清單文件和資源文件夾是必須
注意:在Android中,一次只能添加一個(gè)資源文件夾,如果有多個(gè)資源文件夾需要編輯,可以修改此處的配置。例如,我想在res-product中編輯資源的時(shí)候,IDE能給我正確的提示,那么可以將此處的Resource directory改為對應(yīng)的文件夾。
至此,IDE中已經(jīng)基本可以使用Android的資源了。但是在使用之前,依然還需要處理兩個(gè)問題:
- 引用系統(tǒng)資源時(shí),跳轉(zhuǎn)到源碼而不是sdk
- 處理IDE中報(bào)錯(cuò),但是是正確的使用
如何調(diào)整到系統(tǒng)資源
在我的例子中,為了能夠正確的關(guān)聯(lián)到系統(tǒng)資源,我將編譯出來的sdk中的資源文件夾,刪掉,然后通過鏈接文件夾指向framworks/base/core/res/res目錄。使用ln命令即可,不再贅述
處理xml中的非法使用
在AndroidManifest.xml中,如果使用了系統(tǒng)權(quán)限如:
<uses-permission android:name="android.permission.BIND_CONTROLS" />
再如,使用了不屬于應(yīng)用的useid
android:sharedUserId="android.uid.systemui"
這些會(huì)在IDE中,用紅線標(biāo)識(shí)其錯(cuò)誤,
再如資源文件夾中使用
@*android:integer/config_mediumAnimTime
訪問非public的資源,也會(huì)報(bào)錯(cuò)
這些都屬于靜態(tài)代碼檢查工具的功能,我們將對其進(jìn)行一些修改。
針對上述錯(cuò)誤,可做如下修改:
方法一:
- 打開AndroidManifest.xml文件之后,右鍵單擊
- 選中Analyze->Configure Current File Analysis
- 最后選擇Syntax
上面的步驟,是告訴IDE,對于當(dāng)前這個(gè)文件,只做語法檢查,不做其他檢查
方法二:
上面僅僅是非常粗暴的關(guān)掉了提示。同樣還可以通過File->Settings->Editor->Inspections 在打開的面板中,進(jìn)行精細(xì)的條件。這個(gè)涉及到inspect功能的詳細(xì)解讀,不在此贅述。
方法三:
除了通過圖形界面操作以外,還可以在當(dāng)前目錄下的lint.xml文件中進(jìn)行配置。
lint.xml支持的選項(xiàng),可以通過如下命令得到:
./prebuilts/devtools/tools/lint --list
至此,你可以暢快的在Android Studio中進(jìn)行,java代碼以及xml代碼中的編輯工作了。
當(dāng)然,你也可以對IDE編輯器上面的報(bào)錯(cuò),視而不見,這對于我們的編輯工作并沒有什么實(shí)質(zhì)性影響。
在Android studio中調(diào)試
關(guān)于Android studio怎么調(diào)試Android 應(yīng)用,此處不再介紹,請參考:
android 如何分析應(yīng)用的內(nèi)存(五)——Android studio的LLDB:http://t.csdn.cn/jSurw和android 如何分析應(yīng)用的內(nèi)存(十五)——Visual Studio Code 調(diào)試Android應(yīng)用:http://t.csdn.cn/wHOgd
本文只介紹,如何能讓SystemUI能夠正確的調(diào)試起來。
事實(shí)上,在進(jìn)行SystemUI的調(diào)試中,你將會(huì)發(fā)現(xiàn)local變量無法debug的場景。為了解決這個(gè)問題。需要處理如下幾個(gè)步驟:
- 確定編譯的時(shí)候,添加了javac -g選項(xiàng)
- 關(guān)掉AOSP中的優(yōu)化配置
確定編譯出來的class文件包含調(diào)試信息
在android 如何分析應(yīng)用的內(nèi)存(十四)——jdb命令行http://t.csdn.cn/GtbBH文章中,講解了使用javap進(jìn)行查看的命令。
接下來我們直接查看SystemUIApplication.class是否含有調(diào)試信息。
如果沒有上面的輸出,則嘗試如下修改:
1. Android.mk中增加:LOCAL_JAVACFLAGS += -g
2. Android.bp中增加:javacflags:["-g"]
然后重新編譯。并再次確定,如果依然沒有調(diào)試信息??梢試L試切換成userdebug版本
關(guān)掉AOSP中的模塊優(yōu)化
在AOSP生成apk的環(huán)節(jié)中,有一個(gè)優(yōu)化環(huán)節(jié),這個(gè)優(yōu)化環(huán)節(jié)包括資源的壓縮,無用代碼的剝離,混淆代碼等。為了不破壞調(diào)試信息,我們需要關(guān)閉優(yōu)化。如下:
1. Android.mk中添加:LOCAL_PROGUARD_ENABLED := false
2. Android.bp中添加:optimize:[enabled:false]
完成上述步驟之后,可關(guān)閉優(yōu)化功能,且能夠在單步調(diào)試中進(jìn)行本地變量的查看
開始調(diào)試代碼
為了能讓SystemUI啟動(dòng)的時(shí)候就等待調(diào)試器的加入,我們運(yùn)行下面的命令:
adb shell am set-debug-app -w com.android.systemui
上面代碼的詳細(xì)解釋,可參考:android 如何分析應(yīng)用的內(nèi)存(十五)——Visual Studio Code 調(diào)試Android應(yīng)用http://t.csdn.cn/JPBjC一文中的開始測試小節(jié)
調(diào)試結(jié)果
單步調(diào)試結(jié)果如下圖
在上面的圖中,可以一步一步單步下去,完成整個(gè)執(zhí)行流程的熟悉。
本篇是我們分析SystemUI的基礎(chǔ)環(huán)節(jié),必不可少的環(huán)節(jié),因?yàn)槟軌騿尾竭\(yùn)行,減輕了許多分析源碼的工作。說句人話就是少加班了。
至此,Android studio如何進(jìn)行SystemUI的源碼編輯和調(diào)試,介紹完畢。
從下一篇文章開始,我們將正式進(jìn)入SystemUI的源碼中,查看讓人魂?duì)繅衾@的SystemUI是怎樣被寫出來的。
另外,題外話,如果自己的PC性能還可以,可以使用一些AI工具,進(jìn)行輔助編程,比如筆者正在使用tabnine插件,再比如使用variable extractor將對象翻譯成json格式,然后使用工具,進(jìn)行圖形化查看,如前面文章中提及的Debug Visualizer工具