本頁介紹了 Android 裝置 OEM 可以用來跨產品線擁有自己的共享系統映像 (SSI) 的幾種機制。它還提出了一種將 OEM 擁有的 SSI 基於 AOSP 構建的通用系統映像 (GSI) 的程式。
背景
在Project Treble中,整體 Android 被分為兩部分:特定於硬體的部分(供應商實作)和通用作業系統部分(Android 作業系統框架)。每個軟體都安裝在單獨的分區中:供應商分區用於特定於硬體的軟體,系統分區用於通用作業系統軟體。稱為供應商介面 ( VINTF ) 的版本化介面是在兩個分區之間定義和強制執行的。透過使用此分區系統,您可以修改系統分區而不修改供應商分區,反之亦然。
動機
AOSP 中發布的框架程式碼符合 Treble 架構,並保持了與舊供應商實現的向後相容性。例如,從 Android 10 AOSP 來源建置的通用系統映像可以在運行 Android 8 或更高版本的任何相容 Treble 的裝置上運行。消費性裝置上搭載的 Android 版本由 SoC 供應商和 OEM 進行修改。 (請參閱Android 版本的生命週期。)對框架所做的這些更改和擴展並不是為了保持向後相容性,這意味著作業系統升級的複雜性和成本更高。特定於裝置的變更和修改增加了升級 Android 作業系統版本的成本和複雜性。
在 Android 11 之前,沒有明確的架構可以讓合作夥伴建構 Android 作業系統框架的模組化擴充。本文檔介紹了 SoC 供應商和 OEM 可以採取的建立 SSI 的步驟。這意味著從 Android 作業系統框架來源建立的映像可以在多個裝置上重複使用,保持與供應商實現的向後相容性,並顯著降低 Android 作業系統升級的複雜性和成本。有關建立 SSI 所需的具體步驟,請參閱基於 GSI 的 SSI 的建議步驟部分,並注意您不必使用所有四個步驟。您選擇哪些步驟(例如,僅步驟 1)取決於您的實作。
SSI概述
透過 SSI,特定於產品的軟體元件和 OEM 擴充被放置在新的/product
分區中。 /product
分區中的元件使用定義良好、穩定的介面與/system
分區中的元件互動。 OEM 可以選擇建立一個 SSI,也可以選擇擁有少量 SSI 以在多個裝置 SKU 中使用。當新版本的 Android 作業系統發佈時,OEM只需投資一次即可將其 SSI 更新到最新的 Android 版本。他們可以重複使用 SSI 來更新多個設備,而無需更新/product
分區。
請注意,OEM 和 SoC 供應商建置的 SSI 包含 OEM 所需的所有自訂功能和修改。本頁提供的機制和最佳實務旨在供 OEM 用來實現以下關鍵目標:
- 跨多個裝置 SKU 重複使用 SSI。
- 透過模組化擴充更新Android系統,讓作業系統升級更加容易。
將特定於產品的組件分離到產品分區中的核心思想類似於將特定於 SoC 的組件分離到供應商分區中的 Treble 思想。產品介面(類似於VINTF )允許 SSI 和產品分區之間進行通訊。請注意,對於 SSI,術語「元件」描述了安裝到映像的所有資源、二進位檔案、文字、庫等,這些資源本質上成為分區。
圍繞 SSI 進行分區
圖 1 顯示了 SSI 周圍的分區、跨分區的版本化介面以及介面上的策略。本節詳細解釋每個分區和介面。
圖 1. SSI 周圍的分區和介面
鏡像和分區
本節中的資訊區分術語「映像」和「分區」 。
- 影像是一個可以獨立更新的概念性軟體。
- 分區是可以獨立更新的實體儲存位置。
圖 1 中的各部分定義如下:
SSI: SSI是 OEM 通用的映像,可以跨多個裝置存在。它沒有任何特定於硬體或特定於產品的組件。根據定義,給定 SSI 中的所有內容都在使用該 SSI 的所有裝置之間共用。 SSI 由單一
/system
映像或/system
和/system_ext
分區組成,如圖 1 所示。/system
分區包含基於 AOSP 的元件,而/system_ext
在實作時包含 OEM 和 SoC 供應商擴充以及與 AOSP 元件緊密耦合的元件。例如,為 OEM 自己的應用程式提供自訂 API 的 OEM Java 框架庫更適合放在/system_ext
中,而不是放在/system
分區中。/system
和/system_ext
分區的內容都是根據 OEM 修改的 Android 來源建構的。/system_ext
分區是可選的,但將其用於與基於 AOSP 的組件緊密耦合的任何自訂功能和擴展是有益的。這種差異可以幫助您確定需要進行的更改,以便在一段時間內將此類元件從/system_ext
分區移至/product
分區。
產品:特定於產品或裝置的元件的集合,代表 OEM 對 Android 作業系統的客製化和擴充。將 SoC 特定組件放在
/vendor
分區。 SoC 供應商也可以將/product
分區用於適當的組件,例如獨立於 SoC 的組件。例如,如果 SoC 供應商向其 OEM 客戶提供獨立於 SoC 的組件(可以選擇隨產品一起提供),則 SoC 供應商可以將該組件放置在產品映像中。組件的位置不是由其所有權決定的,而是由其用途決定的。供應商:SoC 特定組件的集合。
ODM: SoC 未提供的特定於板的組件的集合。通常,SoC 供應商擁有供應商映像,而設備製造商擁有 ODM 映像。當沒有單獨的
/odm
分割區時,SoC 供應商和 ODM 映像都會合併到/vendor
分割區中。
影像之間的介面
SSI 周圍存在兩個用於供應商和產品映像的主要介面:
供應商介面 (VINTF) :VINTF 是駐留在供應商和 ODM 映像中的元件的介面。產品和系統映像中的元件只能透過此介面與供應商和 ODM 映像進行互動。例如,供應商映像不能依賴系統映像的私有部分,反之亦然。這最初是在 Project Treble 中定義的,它將映像分為系統分區和供應商分區。此介面使用以下機制進行說明:
- HIDL (直通 HAL 僅適用於
system
和system_ext
模組) - 穩定的AIDL
- 配置
- 系統屬性API
- 設定檔架構 API
- 越南國家發展局
- Android SDK API
- Java SDK 函式庫
- HIDL (直通 HAL 僅適用於
產品介面:產品介面是SSI 和產品影像之間的介面。定義穩定的介面可以將 SSI 中的產品元件與系統元件解耦。產品介面需要與VINTF相同的穩定介面。但是,對於使用 Android 11(及更高版本)啟動的設備,僅強制使用 VNDK 和 Android SDK API。
在 Android 11 中啟用 SSI
本部分介紹如何使用 Android 11 中的新功能來支援 SSI。
/system_ext 分區
/system_ext
分區是在 Android 11 中作為可選分區引入的。 (這是與/system
分區中 AOSP 定義的組件緊密耦合的非 AOSP 組件所在的位置。) /system_ext
分區被假定為/system
分區的 OEM 特定擴展,沒有跨系統定義的介面。兩個分區。 /system_ext
分區中的元件可以對/system
分區進行私有 API 呼叫,而/system
分區中的元件可以對/system_ext
分區進行私有 API 呼叫。
由於這兩個分區緊密耦合,因此當新的 Android 版本發佈時,兩個分區都會一起升級。為先前版本的 Android 建立的/system_ext
分區不需要與下一個 Android 版本中的/system
分區相容。
若要將模組安裝到/system_ext
分區,請將system_ext_specific: true
加入Android.bp
檔案。對於沒有/system_ext
分區的設備,請將此類模組安裝到/system
分區中的./system_ext
子目錄。
歷史
以下是有關/system_ext
分區的一些歷史記錄。設計目標是將所有 OEM 特定元件(無論它們是否通用)放置在/product
分區中。然而,一次性移動它們是不可行的,特別是當某些組件與/system
分區緊密耦合時。若要將緊密耦合的元件移至/product
分區,必須擴充產品介面。這往往需要對組件本身進行廣泛的重構,這會消耗大量的時間和精力。 /system_ext
分區最初是作為臨時託管那些尚未準備好移至/product
分區的組件的位置。 SSI 的目標是最終消除/system_ext
分區。
但是, /system_ext
分區對於使/system
分區盡可能靠近 AOSP 非常有用。對於 SSI,大部分升級工作都花在/system
和/system_ext
分區中的元件上。當系統映像是盡可能從與 AOSP 相似的來源建置時,您可以將升級工作重點放在system_ext
映像上。
將元件從/system
和/system_ext
分區解綁到/product
分區
Android 9 引進了與/system
分區結合的/product
分區。 /product
分區中的模組不受任何限制地使用系統資源,反之亦然。為了讓 SSI 在 Android 10 中成為可能,產品元件被分成/system_ext
和/product
分區。 /system_ext
分區不必遵守 Android 9 中/product
分區對使用系統組件的限制。從 Android 10 開始, /product
分區必須從/system
分區解綁,並且必須使用來自/system
10 的穩定介面。/system和/system_ext
分區。
/system_ext
分區的主要目的是擴展系統功能,而不是安裝捆綁的產品模組,如/system_ext partition
部分所述。為此,請解綁特定於產品的模組並將它們移至/product
分區。分拆特定於產品的模組使得/system_ext
對於設備來說是通用的。 (有關更多詳細信息,請參閱使 /system_ext 分區公用。)
若要從系統元件中取消捆綁/product
分區, /product
分區必須與已與 Project Treble 取消捆綁的/vendor
分區具有相同的強制策略。
從 Android 11 開始, /product
分區的本機和 Java 介面將如下所述強制實施。有關更多信息,請參閱強制執行產品分區接口。
- 本機介面:
/product
分區中的本機模組必須與其他分區分開。產品模組唯一允許的依賴項是/system
分區中的一些 VNDK 庫(包括 LLNDK)。產品應用依賴的JNI函式庫必須是NDK函式庫。 - Java 介面:
/product
分區中的 Java(應用程式)模組不能使用隱藏的 API,因為它們不穩定。這些模組只能使用/system
分區中的公用 API 和系統 API,以及/system
或/system_ext
分區中的 Java SDK 函式庫。您可以為自訂 API 定義Java SDK 函式庫。
基於 GSI 的 SSI 的建議步驟
圖 2.基於 GSI 的 SSI 的建議分區
通用系統映像 (GSI) 是直接從 AOSP 建置的系統映像。它用於Treble 合規性測試(例如,CTS-on-GSI),並作為參考平台,應用程式開發人員在沒有運行所需Android 版本的真實設備時可以使用該平台來測試其應用程式的兼容性。
OEM 也可以使用 GSI 來製作他們的 SSI。如映像和分區所述,SSI 由 AOSP 定義的元件的系統映像和 OEM 定義的元件的system_ext
映像組成。當使用GSI作為system
鏡像時,OEM可以專注於system_ext
鏡像進行升級。
本部分為希望在使用 AOSP 或近 AOSP 系統映像時將其自訂模組化至/system_ext
和/product
分區的 OEM 提供指南。如果 OEM 從 AOSP 來源建立系統映像,那麼他們可以用 AOSP 提供的 GSI 替換他們建立的系統映像。然而,OEM 不需要一次完成最後一步(使用 GSI)。
步驟1.繼承OEM的系統映像(OEM GSI)的generic_system.mk
透過繼承generic_system.mk
(在Android 11中命名為mainline_system.mk
,在AOSP中重新命名為generic_system.mk
),系統映像(OEM GSI)包含了AOSP GSI擁有的所有檔案。 OEM 可以修改這些文件,以便 OEM GSI 除了 AOSP GSI 文件之外還可以包含 OEM 專有文件。但是,OEM 不允許修改generic_system.mk
檔案本身。
圖 3.繼承 OEM 系統映像的generic_system.mk
步驟 2. 使 OEM GSI 與 AOSP GSI 具有相同的文件列表
OEM GSI 在此階段不能有其他文件。 OEM 的專有檔案必須移出到system_ext
或product
分區。
圖 4.將新增的檔案移出 OEM GSI
步驟 3. 定義允許清單以限制 OEM GSI 中的修改文件
若要檢查已修改的文件,OEM 可以使用compare_images
工具,並將AOSP GSI 與OEM GSI 進行比較。從 AOSP 午餐目標generic_system_*
取得 AOSP GSI。
透過使用allowlist
參數定期執行compare_images
工具,您可以監控白名單以外的差異。這樣就無需對 OEM GSI 進行額外修改。
圖 5.定義允許列表以減少 OEM GSI 中的修改文件列表
步驟 4. 使 OEM GSI 具有與 AOSP GSI 相同的二進位文件
清理白名單允許 OEM 使用 AOSP GSI 作為自己產品的系統映像。要清理允許列表,OEM 可以放棄 OEM GSI 中的更改,或將其更改上游到 AOSP,以便 AOSP GSI 包含其更改。
圖 6.使 OEM GSI 具有與 AOSP GSI 相同的二進位文件
為 OEM 定義 SSI
在建置時保護 /system 分區
為了避免/system
分區中任何特定於產品的變更並定義 OEM GSI,OEM 可以使用名為require-artifacts-in-path
的 makefile 巨集來防止在呼叫該巨集後聲明任何系統模組。請參閱建立 makefile 並啟用工件路徑檢查範例。
OEM 可以定義一個列表,以允許將特定於產品的模組暫時安裝在/system
分區中。但是,該清單必須為空,以使 OEM GSI 對於所有 OEM 產品都是通用的。此流程用於定義 OEM GSI,並且可以獨立於AOSP GSI 的步驟。
強制執行產品介面
為了確保/product
分區是解綁定的,OEM 可以透過設定PRODUCT_PRODUCT_VNDK_VERSION:= current
(對於本機模組)和PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true
對於 Java 模組)來確保其設備強制執行產品介面。如果設備的PRODUCT_SHIPPING_API_LEVEL
大於或等於30
,則會自動設定這些變數。有關詳細信息,請參閱強制執行產品分區介面。
使/system_ext
分區公用
/system_ext
分區可能因設備而異,因為它可以具有特定於設備的系統捆綁模組。由於 SSI 由/system
和/system_ext
分區組成,因此/system_ext
分區的差異阻礙了 OEM 定義 SSI。 OEM 可以擁有自己的 SSI,並且可以透過消除任何差異並使/system_ext
分區公用來在多個裝置之間共用該 SSI。
本節提供了使/system_ext
分區公用的建議。
暴露系統分割區中隱藏的API
許多產品特定應用程式無法安裝在產品分割區中,因為它們使用隱藏的 API,而這些 API 在產品分割區中是被禁止的。若要將裝置特定的應用程式移至產品分割區,請刪除隱藏 API 的使用。
從應用程式中刪除隱藏 API 的首選方法是找到替代的公共或系統 API 來取代它們。如果沒有 API 來取代隱藏的 API,OEM 可以向 AOSP 做出貢獻,為其設備定義新的系統 API。
或者,OEM 可以透過在/system_ext
分區中建立自己的Java SDK 庫來定義自訂 API。它可以使用系統分割區中的隱藏API,並且可以向產品或供應商分割區中的應用程式提供API。 OEM 必須凍結產品導向的 API以實現向後相容性。
包含所有 APK 的超集並跳過每個設備的一些軟體包安裝
與系統捆綁在一起的某些軟體包在不同設備上並不常見。解綁這些 APK 模組以將其移至產品或供應商分區可能很困難。作為臨時解決方案,OEM 可以讓 SSI 包含所有模組,然後使用 SKU 屬性 ( ro.boot.hardware.sku
) 過濾掉不需要的模組。若要使用篩選器,OEM 會覆寫框架資源config_disableApkUnlessMatchedSku_skus_list
和config_disableApksUnlessMatchedSku_apk_list
。
為了更精確的設置,聲明一個廣播接收器來停用不必要的包。廣播接收器在收到ACTION_BOOT_COMPLETED
訊息時呼叫setApplicationEnabledSetting
來停用該套件。
定義 RRO 而不是使用靜態資源覆蓋
靜態資源覆蓋操作覆蓋的包。但是,它可能會妨礙定義 SSI,因此請確保 RRO 的屬性已開啟並正確設定。透過如下設定屬性,OEM 可以將所有自動產生的覆蓋作為 RRO。
PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty
如果需要詳細配置,請手動定義 RRO,而不是依賴自動產生的 RRO。有關詳細信息,請參閱運行時資源覆蓋 (RRO) 。 OEM 也可以使用android:requiredSystemPropertyName
和android:requiredSystemPropertyValue
屬性定義依賴系統屬性的條件 RRO。
常見問題 (FAQ)
我可以定義多個 SSI 嗎?
這取決於設備(或設備組)的共通性和特性。 OEM 可以嘗試使system_ext
分區公用,如使 system_ext 分區公用中所述。如果設備組有很多差異,那麼最好定義多個 SSI。
我可以修改 OEM GSI 的generic_system.mk
( mainline_system.mk
) 嗎?
不會。但 OEM 可以為繼承generic_system.mk
檔案的 OEM GSI 定義一個新的 makefile,並改用新的 makefile。有關範例,請參閱強制執行產品分區介面。
我可以從generic_system.mk
中刪除與我的實作衝突的模組嗎?
不會。GSI 具有最少的可啟動和可測試模組集。如果您認為某個模組不是必需的,請提交錯誤以更新 AOSP 中的generic_system.mk
檔案。