Android Q新特性:APEX 模塊化升級

最近在修改Android源碼(廠商定制的源碼,非AOSP)時,遇到了一些問題:

  1. 新增的lib庫模塊,需要依賴libart等so包,而這些so包在Android Q中被編譯到了apex中(apex文件位于/system/apex目錄),導致無法找到共享庫(需要修改/system/core/roodir/etc/ld.config.txt, 修改里面的策略比較麻煩,并且可能導致安全問題)。
  2. 在將java層代碼移動到了core-libart中,可以順利的引用到com.android.runtime.release中的庫文件,也算解決了問題1。
  3. 在某個最新的Android版本中,system分區(qū)為erofs文件系統(tǒng)(只讀),無法通過adb remount來重新掛載為可讀寫。而為了替換apex,需要替換/system/apex/下的相應(yīng)文件。該系統(tǒng)版本通過引入了overlay文件系統(tǒng)來解決該問題。overlay文件系統(tǒng)在system掛載點上覆蓋了一層upper目錄。當用戶通過adb remount指令重新掛載后,所有對/system的操作實際是對cache下的upper目錄的操作。由于cache分區(qū)太小,導致將文件直接放入。
  4. 在廠商定制的Android源碼中,由于存在很多二進制交付的部件,這使得單純通過編譯源碼得到的System.img是不完整的鏡像,無法直接刷入設(shè)備。

解決方案

為了將修改后的APEX文件放入設(shè)備中,考慮到APEX特性主要用于模塊化升級操作,肯定預留了升級模塊的功能。故而,可以利用APEX的升級功能來達到替換APEX的效果。
接下來,我們將對APEX進行簡要的學習。相應(yīng)的源碼位置如下

  1. APEX的實現(xiàn)源碼位于:/system/apex/模塊
  2. 與運行時庫相關(guān)的APEX編譯模塊(com.android.runtime)位于art/build/apex模塊,編譯指令為:make com.android.runtime.release, 編譯后替換/system/apex/相應(yīng)文件,重啟后將在/apex中掛載。

參考資料

APEX簡要介紹

APEX是Google繼Project Treble后的又一重大舉措,它是Android Q的系統(tǒng)組件更新機制。APEX的想法在GNU/Linux發(fā)行版中非常普遍:針對Linux庫集合中的特定部分的包更新。但這是Google從未嘗試過的事情,因為Android中使用了一個ro(只讀)分區(qū),在其中存儲了所有系統(tǒng)庫和框架,而不是大多數(shù)Linux發(fā)行版中通常使用的rw(讀寫)分區(qū),從而使得其難以實現(xiàn)標準升級過程。
庫是預編譯的代碼,可以在其它程序中使用。常用的方法是可以制作成Android應(yīng)用程序調(diào)用的庫,減少Android應(yīng)用程序的大小,因為不需要在多個應(yīng)用程序中實現(xiàn)相同的代碼。我們可以在/system/lib/system/lib64目錄中找到許多預裝系統(tǒng)庫。Android系統(tǒng)庫通常不會單獨更新-相反,它們會通過OTA更新作為Android平臺升級的一部分進行更新(備注:意思就是要整個系統(tǒng)升級才能把系統(tǒng)庫部分也一并升級了,而不能像Linux那樣子,可以針對特定的系統(tǒng)庫進行升級)。另一方面,Linux發(fā)行版的庫可以單獨升級。
隨著APEX的推出,Android中的系統(tǒng)庫可以像Android應(yīng)用程序一樣單獨更新。這樣做的好處是,應(yīng)用程序開發(fā)人員將能夠利用更新后的庫,而無需等待OEM推出完整的系統(tǒng)升級。
APEX是一個生態(tài)系統(tǒng),迫使Google重新考慮Android從不同于/system的非標準分區(qū)加載所有庫和文件的方式。
首先,我們必須區(qū)分共享庫和靜態(tài)庫。共享庫是一個庫(如libkind.so的文件),它不包含自身運行所需的所有代碼,而是與實際提供代碼的其它庫進行鏈接;靜態(tài)庫則是,可以認為它不依賴于其它任何庫,并在文件中靜態(tài)包含了所有內(nèi)容。
Android歷史上使用了名為ld.config.txt[0]的單個配置庫路徑文件(即Linux中的LD_LIBRARY_PATH),以配置二進制或其它庫中所需的共享庫的允許搜索路徑。這些路徑在配置中是硬編碼的,不可擴展。除非用戶安裝OTA Android更新,否則此布局(包括只讀系統(tǒng)分區(qū))會導致不可更新的庫。Google解決了該問題,允許擴展搜索路徑,讓單個APEX包提供自己的ld.config.txt,其中包含額外(和更新)庫路徑。
但這樣子仍存在問題:首先是ABI(應(yīng)用程序二進制接口)穩(wěn)定性,庫應(yīng)該始終導出一組穩(wěn)定的接口,以允許其它應(yīng)用程序和庫繼續(xù)使用相同的協(xié)議,即使升級后的庫也是如此。Google正嘗試在APEXed庫之間創(chuàng)建穩(wěn)定的C接口來積極開展該工作。
APEX并不僅與庫和二進制文件。實際上,它還包括配置文件、timezone更新以及一些java框架。
當前AOSP提供的APEX包名的示例有:

  • com.andrid.runtime: ART和bionic runtime(二進制和庫)
  • com.android.tzdata: TimeZone和ICU數(shù)據(jù)(庫和配置數(shù)據(jù))
  • com.android.resolv: Android中用于解決網(wǎng)絡(luò)相關(guān)請求的庫(庫)
  • com.android.conscrypt(Java安全提供程序)(Java框架)

如何安裝和構(gòu)建APEX包

APEX軟件包是一個簡單的Zip包(如APK),可由ADB進行安裝,而后通過包管理器來安裝。

image.png

apex_manifest.json指定了package以及version:
image.png

apex_payload.img是一個micro-filesytem 鏡像(EXT 4格式)

image.png

其它文交所 用于安裝軟件包是的驗證過程的一部分,如:

  • AndroidManfest.xml:
  • META-INF/目錄有著包整數(shù),并使用域APK相同的機制。因此,在運行用戶安裝更新之前,這些包在運行時,將由私鑰/公鑰對進行驗證。Google又增加了2層安全性,它們使用dm-verity檢測鏡像的完整性以及AVB(Android Verified Boot)驗證來確保鏡像來自可信的源。最壞情況下,APEX包將被拒絕。
    如果所有驗證步驟都成功,鏡像文件將被標記為有效,并在下一次重新引導時替換系統(tǒng)實體。

如何在啟動時安裝鏡像

image.png

預安裝的軟件包存儲在/system/apex中,并且所有軟件包當前都是版本1.但當APEX被激活時會發(fā)生什么?我們將再次使用com.android.tzdata做例子。


image.png

讓我們重啟設(shè)備并分析logcat。


image.png

前兩行提供了足夠的信息來了解軟件包的來源與安裝位置:/apex/, Android Q引入而來新的目錄,用來存儲激活的軟件包。
使用AVB成功驗證軟件包后,并且公鑰匹配后,使用loop設(shè)備將APEX安裝到/dev/block/loop0,使系統(tǒng)可以訪問EXT4文件系統(tǒng)。loop設(shè)備是一種偽設(shè)備,它是文件可以作為塊設(shè)備被訪問,使得該文件的內(nèi)容可以作為安裝點被訪問。
此時,由于@1后綴(表示軟件版本),APEX仍未使用。為了最終讓系統(tǒng)知道我們的軟件包已經(jīng)激活,它將被綁定掛載到/apex/com.android.tzdata。其中Android主動期望tzdata生效,綁定裝載覆蓋不同點下的現(xiàn)有目錄或文件。


image.png

APEX的實現(xiàn)整個位于AOSP下的單個倉庫。apexd(APEX daemon)目錄含有Android上運行的代碼。apexer目錄含有構(gòu)建系統(tǒng)使用的用來創(chuàng)建APEX包的代碼。
Google視圖創(chuàng)建一組APEX包的核心集,這些包可被Google更新,從而可以創(chuàng)建一個在供應(yīng)商之間共享的統(tǒng)一的Android基礎(chǔ)核心,使的只有"system"更新稱為可能,但只是單個包的升級。
apexd要求 /data/apex在啟動后立即可用,以更新所有的Android模塊。使用FDE(全潘加密),/data/apex/在用戶解鎖設(shè)備之前都是加密的,使得apex基本上毫無用處,因為只有系統(tǒng)apex的變種會在啟動時加載。除此之外,所有設(shè)備都應(yīng)該支持APEX,但他們需要一些內(nèi)核補丁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容