本頁介紹 Android 裝置 OEM 可使用的幾種機制,在產品線中採用自己的共用系統映像檔 (SSI)。此外,本文也建議程序,讓原始設備製造商 (OEM) 能夠以 AOSP 建構的一般系統映像檔 (GSI) 為基礎,建立自有 SSI。
背景
Project Treble 將單一的 Android 分成兩部分:硬體專屬部分 (供應商實作) 和一般 OS 部分 (Android OS 架構)。每個軟體都安裝在不同的分區:供應商分區用於硬體專屬軟體,系統分區則用於一般 OS 軟體。系統會定義並強制執行兩個分區的介面版本,稱為供應商介面 (VINTF)。使用這個分割系統時,您可以修改系統分割區,而不必修改供應商分割區,反之亦然。
動機
Android 開放原始碼計畫 (AOSP) 發布的架構程式碼一直都符合 Treble 架構,並維持與舊版供應商實作項目的回溯相容性。舉例來說,從 Android 10 AOSP 來源建構的通用系統映像檔,可在任何執行 Android 8 以上版本的 Treble 相容裝置上執行。消費者裝置搭載的 Android 版本是由 SoC 供應商和 OEM 修改。(請參閱「Android 版本生命週期」。)這些對架構進行的變更和擴充功能並非為了維持回溯相容性而編寫,因此 OS 升級的複雜度增加,成本也隨之提高。裝置專屬的變更和修改會增加 Android OS 版本升級的成本和複雜度。
在 Android 11 之前,合作夥伴無法透過明確的架構,為 Android OS 架構建構模組化擴充功能。本文說明 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 需要的所有自訂功能和修改項目。本頁面提供的機制和最佳做法,可協助原始設備製造商達成下列主要目標:
- 在多個裝置 SKU 中重複使用 SSI。
- 使用模組化擴充功能更新 Android 系統,讓作業系統升級更輕鬆。
將產品專屬元件劃分為產品分割區的核心概念,與 Treble 將 SoC 專屬元件劃分為供應商分割區的概念類似。產品介面 (類似於 VINTF) 可讓 SSI 與產品分割區通訊。請注意,就 SSI 而言,「元件」一詞是指安裝到映像檔的所有資源、二進位檔、文字、程式庫等,這些資源基本上會成為分割區。
SSI 周圍的分區
圖 1 顯示 SSI 周圍的分區,以及分區和介面上各個介面和政策的版本。本節將詳細說明每個分割區和介面。
圖 1. SSI 周圍的分區和介面
圖片和分割區
本節資訊會區分「映像檔」和「磁碟分割」這兩個詞彙。
- 映像檔是概念上的軟體,可獨立更新。
- 分割區是可獨立更新的實體儲存位置。
圖 1 中的各節定義如下:
SSI:SSI 是 OEM 裝置通用的映像檔,可存在於多部裝置中。不含任何硬體或產品專屬元件。根據定義,特定 SSI 中的所有內容都會在所有使用該 SSI 的裝置間共用。SSI 由單一
/system
圖片,或/system
和/system_ext
分區組成,如圖 1 所示。/system
分區包含以 Android 開放原始碼計畫為基礎的元件,而/system_ext
(如果已實作) 則包含 OEM 和 SoC 廠商的擴充功能,以及與 Android 開放原始碼計畫元件緊密結合的元件。舉例來說,如果 OEM Java 架構程式庫為 OEM 自己的應用程式提供自訂 API,就比較適合放在/system_ext
分割區,而不是/system
分割區。/system
和/system_ext
分割區的內容都是以 OEM 修改的 Android 來源建構而成。/system_ext
分區為選用項目,但建議用於與 AOSP 型元件緊密結合的任何自訂功能和擴充功能。這項區別有助於您找出需要進行的變更,以便在一段時間內將這類元件從/system_ext
分區移至/product
分區。
產品:一組產品或裝置專屬元件,代表 OEM 對 Android OS 的自訂和擴充功能。將 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 (Passthrough HAL 僅適用於
system
和system_ext
模組) - 穩定 AIDL
- 設定
- 系統屬性 API
- 設定檔結構定義 API
- VNDK
- Android SDK API
- Java SDK 程式庫
- HIDL (Passthrough HAL 僅適用於
產品介面:產品介面是 SSI 與產品圖片之間的介面。定義穩定介面可將產品元件與 SSI 中的系統元件分離。產品介面必須與 VINTF 採用相同的穩定介面。不過,對於搭載 Android 11 以上版本推出的裝置,系統只會強制執行 VNDK 和 Android SDK API。
在 Android 11 中啟用 SSI
本節說明如何使用新功能,在 Android 11 中支援 SSI。
/system_ext 分區
Android 11 推出 /system_ext
分區,做為選用分區。(這是指與 /system
分區中 AOSP 定義的元件緊密耦合的非 AOSP 元件。)/system_ext
分區應是 /system
分區的 OEM 專用擴充功能,且這兩個分區之間沒有定義介面。/system_ext
分割區中的元件可以對 /system
分割區發出私有 API 呼叫,/system
分割區中的元件也可以對 /system_ext
分割區發出私有 API 呼叫。
由於這兩個磁碟分割區緊密結合,因此在發布新版 Android 時,這兩個磁碟分割區會一併升級。為先前 Android 版本建立的 /system_ext
分區,不必與下一個 Android 版本的 /system
分區相容。
如要將模組安裝至 /system_ext
分區,請在 Android.bp
檔案中新增 system_ext_specific:
true
。如果裝置沒有 /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
分割區中的模組可不受限制地使用系統資源,反之亦然。為在 Android 10 中啟用 SSI,產品元件會分割到 /system_ext
和 /product
分區。/system_ext
分區不必遵守 Android 9 中 /product
分區對使用系統元件的限制。從 Android 10 開始,/product
分區必須從 /system
分區取消組合,且必須使用 /system
和 /system_ext
分區的穩定介面。
如「/system_ext partition
」一節所述,/system_ext
分區的主要用途是擴充系統功能,而非安裝隨附的產品模組。如要這麼做,請取消產品專屬模組的組合,並將其移至 /product
分區。將產品專屬模組解除綁定後,/system_ext
就能在裝置間共用。(詳情請參閱「將 /system_ext 分區設為通用」。)
如要從系統元件取消綁定 /product
分區,/product
分區必須與已透過 Project Treble 取消綁定的 /vendor
分區採用相同的強制執行政策。
從 Android 11 開始,系統會強制執行 /product
分區的原生和 Java 介面,詳情如下。詳情請參閱「強制執行產品分割介面」。
- 原生介面:
/product
分區中的原生模組必須與其他分區解除繫結。產品模組中唯一允許的依附元件,是/system
分割區中的部分 VNDK 程式庫 (包括 LLNDK)。產品應用程式所依附的 JNI 程式庫必須是 NDK 程式庫。 - Java 介面:
/product
分區中的 Java (應用程式) 模組無法使用隱藏版 API,因為這些 API 不穩定。這些模組只能使用/system
分區的公開 API 和系統 API,以及/system
或/system_ext
分區的 Java SDK 程式庫。您可以為自訂 API 定義 Java SDK 程式庫。
以 GSI 為基礎的 SSI 建議步驟
圖 2. 以 GSI 為基礎的 SSI 建議分割區
通用系統映像檔 (GSI) 是直接從 Android 開放原始碼計畫建構的系統映像檔。GSI 可用於 Treble 相容性測試 (例如 CTS-on-GSI),以及做為參考平台,供應用程式開發人員在沒有搭載所需 Android 版本的實體裝置時,測試應用程式的相容性。
原始設備製造商也可以使用 GSI 製作 SSI。如「映像檔和分割區」一文所述,SSI 包含 AOSP 定義元件的系統映像檔,以及 OEM 定義元件的 system_ext
映像檔。使用 GSI 做為 system
映像檔時,原始設備製造商可以專注於升級 system_ext
映像檔。
本節提供指南,協助 OEM 廠商在使用 AOSP 或近乎 AOSP 的系統映像檔時,將自訂項目模組化至 /system_ext
和 /product
分割區。如果原始設備製造商從 Android 開放原始碼計畫來源建構系統映像檔,則可將建構的系統映像檔替換為 Android 開放原始碼計畫提供的 GSI。不過,原始設備製造商不需要一次完成最後一個步驟 (直接使用 GSI)。
步驟 1:為 OEM 的系統映像檔 (OEM GSI) 繼承 generic_system.mk
透過繼承 generic_system.mk
(在 Android 11 中名為 mainline_system.mk
,並在 Android 開放原始碼計畫中重新命名為 generic_system.mk
),系統映像檔 (OEM GSI) 會包含 Android 開放原始碼計畫 GSI 的所有檔案。原始設備製造商 (OEM) 可以修改這些檔案,因此除了 AOSP GSI 檔案外,OEM GSI 也可以包含 OEM 專有檔案。不過,OEM 不得修改 generic_system.mk
檔案本身。
圖 3. 為 OEM 的系統映像檔繼承 generic_system.mk
步驟 2:讓 OEM GSI 擁有與 AOSP GSI 相同的檔案清單
現階段 OEM GSI 無法包含其他檔案。原始設備製造商的專有檔案必須移至 system_ext
或 product
分區。
圖 4. 將新增的檔案移出 OEM GSI
步驟 3:定義允許清單,限制 OEM GSI 中修改的檔案
如要檢查修改後的檔案,原始設備製造商 (OEM) 可以使用 compare_images
工具,並比較 AOSP GSI 與 OEM GSI。從 AOSP lunch 目標 generic_system_*
取得 AOSP GSI。
定期使用 allowlist
參數執行 compare_images
工具,即可監控允許清單以外的差異。這樣可避免對 OEM GSI 進行額外修改。
圖 5. 定義允許清單,減少 OEM GSI 中修改的檔案清單
步驟 4:讓 OEM GSI 與 AOSP GSI 具有相同的二進位檔
清理許可清單後,原始設備製造商就能將 AOSP GSI 用於自家產品的系統映像檔。如要清除允許清單,原始設備製造商可以放棄 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
分區未綁定,原始設備製造商可以設定 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
分區的差異會阻礙原始設備製造商定義 SSI。原始設備製造商可以擁有自己的 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 提供給產品或供應商分區中的應用程式。為確保回溯相容性,原始設備製造商必須凍結面向產品的 API。
包含所有 APK 的超集,並略過每個裝置的部分套件安裝作業
系統隨附的某些套件並非所有裝置都有。
將這些 APK 模組解除綁定並移至產品或供應商分割區,可能會有困難。做為暫時解決方案,原始設備製造商可以讓 SSI 包含所有模組,然後使用 SKU 屬性 (ro.boot.hardware.sku
) 篩除不需要的模組。如要使用篩選器,原始設備製造商可以疊加架構資源 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)」。原始設備製造商也可以使用 android:requiredSystemPropertyName
和 android:requiredSystemPropertyValue
屬性,定義取決於系統屬性的條件式 RRO。
常見問題 (FAQ)
我可以定義多個 SSI 嗎?
這取決於裝置 (或裝置群組) 的共通性和特徵。
如要讓 OEM 嘗試將 system_ext
分區設為通用,請參閱「將 system_ext 分區設為通用」。如果裝置群組有許多差異,最好定義多個 SSI。
我可以修改 OEM GSI 的 generic_system.mk (mainline_system.mk) 嗎?
不可以。但原始設備製造商 (OEM) 可以為 OEM GSI 定義新的 Makefile,並繼承 generic_system.mk
檔案,然後改用新的 Makefile。如需範例,請參閱「強制執行產品分割介面」。
我可以從 generic_system.mk 中移除與實作項目衝突的模組嗎?
否。GSI 具有可啟動及可測試的最低模組集。如果您認為某個模組並非必要,請提出錯誤報告,更新 AOSP 中的 generic_system.mk
檔案。