本頁面介紹了 Android 裝置原始設備製造商 (OEM) 可用於在各產品系列中擁有專屬共用系統映像檔 (SSI) 的幾種機制。這份文件也提出了相關程序,說明如何在 AOSP 建構的通用系統映像檔 (GSI) 上,建立原始設備製造商 (OEM) 擁有的 SSI。
背景
透過 Project Treble,單一 Android 系統已分成兩個部分:硬體專屬部分 (供應商實作) 和通用 OS 部分 (Android OS 架構)。每個軟體都會安裝在不同的分區:供應商分區用於硬體專屬軟體,系統分區用於一般 OS 軟體。系統會在兩個區段中定義並強制執行版本介面,稱為供應商介面 (VINTF)。使用這個分割系統,您可以修改系統分割區,而無須修改供應商分割區,反之亦然。
動機
在 AOSP 中發布的架構程式碼已符合 Treble 架構,並且與舊版供應商實作項目維持回溯相容性。舉例來說,從 Android 10 AOSP 來源建構的通用系統映像檔,可在任何搭載 Android 8 以上版本且符合 Treble 規範的裝置上執行。消費者裝置出貨時搭載的 Android 版本,會由 SoC 供應商和原始設備製造商修改。(請參閱「Android 版本的生命週期」)。這些對架構所做的變更和擴充功能並非為了維持回溯相容性而編寫,因此會導致 OS 升級作業變得更複雜,成本也更高。裝置專屬的變更和修改會增加升級 Android 作業系統版本的成本和複雜度。
在 Android 11 推出之前,合作夥伴無法透過明確的架構,為 Android 作業系統架構建構模組擴充功能。本文件說明 SoC 供應商和原始設備製造商可採取的步驟,以建立 SSI。也就是說,這會是從 Android 作業系統架構來源建立的單一映像檔,可在多個裝置上重複使用,以便維持與供應商實作項目的回溯相容性,並大幅降低 Android 作業系統升級的複雜度和成本。如需建立 SSI 的具體步驟,請參閱「建議的 GSI 準則 SSI 步驟」一節,請注意,您不必使用所有四個步驟。您選擇的步驟 (例如僅限步驟 1) 取決於您的實作方式。
SSI 總覽
透過 SSI,產品專屬軟體元件和 OEM 擴充功能會放置在新的 /product
分割區。/product
分區中的元件會使用明確且穩定的介面,與 /system
分區中的元件互動。原始設備製造商 (OEM) 可以選擇建構一個 SSI,也可以建構少數 SSI 供多個裝置 SKU 使用。當新版 Android 作業系統推出時,原始設備製造商只需要一次更新 SSI 至最新的 Android 版本。他們可以重複使用 SSI 來更新多部裝置,而無須更新 /product
分割區。
請注意,原始設備製造商 (OEM) 和 SoC 供應商會建構 SSI,其中包含原始設備製造商所需的所有自訂功能和修改項目。本頁提供的機制和最佳做法,可協助原始設備製造商達成下列重要目標:
- 在多個裝置 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
分割區包含以 Android 開放原始碼計畫為基礎的元件,而/system_ext
實作後,則會包含 OEM 和 SoC 供應商擴充功能,以及與 Android 開放原始碼計畫元件緊密結合的元件。舉例來說,OEM Java 架構程式庫為 OEM 自有應用程式提供自訂 API,因此較適合放在/system_ext
中,而非/system
分割區。/system
和/system_ext
區隔的內容皆由 OEM 修改的 Android 來源建構而成。/system_ext
分區並非必要,但對於與以 AOSP 為基礎的元件緊密結合的任何自訂功能和擴充功能,使用此分區會帶來好處。這項區別可協助您找出需要進行的變更,以便在一段時間內將這類元件從/system_ext
區隔移至/product
區隔。
產品:產品或裝置專屬元件集合,代表 Android OS 的原始設備製造商 (OEM) 自訂選項和擴充功能。將 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
- VNDK
- 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 中推出的選用分區。(這是非 AOSP 元件與 /system
分區中 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
區隔中的模組可不受限制地使用系統資源,反之亦然。為在 Android 10 中實現 SSI,產品元件會分割為 /system_ext
和 /product
區隔。/system_ext
分割區不必遵守 Android 9 中 /product
分割區的系統元件使用限制。自 Android 10 起,/product
分區必須從 /system
分區中解除套件,且必須使用 /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,因為這些 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
映像檔。
本節提供指南,供 OEM 廠商在使用 AOSP 或接近 AOSP 的系統映像檔時,將自訂項目模組化為 /system_ext
和 /product
分區。如果原始設備製造商 (OEM) 從 Android 開放原始碼計畫來源建構系統映像檔,則可使用 Android 開放原始碼計畫提供的 GSI 取代所建構的系統映像檔。不過,原始設備製造商 (OEM) 不必一次完成所有步驟 (使用 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) 可以修改這些檔案,讓原始設備製造商 GSI 除了包含 Android 開放原始碼計畫 GSI 檔案外,還能包含原始設備製造商專屬檔案。不過,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 午餐目標 generic_system_*
取得 AOSP GSI。
您可以定期搭配 allowlist
參數執行 compare_images
工具,監控允許清單以外的差異。這樣可避免需要對原始設備製造商 (OEM) GSI 進行額外修改。
圖 5. 定義許可清單,以減少 OEM GSI 中的修改檔案清單
步驟 4:讓原始設備製造商 (OEM) GSI 的二進位檔與 Android 開放原始碼計畫 (AOSP) GSI 相同
清除許可清單後,原始設備製造商 (OEM) 就能將 AOSP GSI 用於自家產品的系統映像檔。為了清理許可清單,原始設備製造商可以放棄在原始設備 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
,為 Java 模組設定 PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true
,確保裝置會強制執行產品介面。如果裝置的 PRODUCT_SHIPPING_API_LEVEL
大於或等於 30
,系統會自動設定這些變數。詳情請參閱「強制執行產品分割區介面」一文。
讓 /system_ext 分區成為常見分區
/system_ext
分割區可能會因裝置而異,因為它可能包含裝置專屬的系統內建模組。由於 SSI 包含 /system
和 /system_ext
分區,因此 /system_ext
分區的差異會妨礙原始設備製造商定義 SSI。OEM 可以擁有自己的 SSI,並且透過移除任何差異,讓 /system_ext
分區共用,在多個裝置之間共用該 SSI。
本節提供建議,說明如何讓 /system_ext
分區成為常見分區。
公開系統分區中的隱藏 API
許多特定產品的應用程式無法安裝在產品分區,因為這些應用程式會使用隱藏的 API,而這類 API 在產品分區中是禁止使用的。如要將裝置專用應用程式移至產品分區,請移除隱藏 API 的使用。
從應用程式中移除隱藏的 API 的首選方式,是找出替代的公用或系統 API 來取代這些 API。如果沒有 API 可取代隱藏的 API,原始設備製造商 (OEM) 可以為 AOSP 做出貢獻,為其裝置定義新的系統 API。
或者,OEM 也可以在 /system_ext
區隔中建立自己的 Java SDK 程式庫,藉此定義自訂 API。它可以使用系統分區中的隱藏 API,並可將 API 提供給產品或供應商分區中的應用程式。為了確保回溯相容性,原始設備製造商必須凍結產品端 API。
納入所有 APK 的超集合,並略過每個裝置的部分套件安裝作業
某些系統內建的套件在不同裝置上並不常見。將這些 APK 模組解除綁定,並移至產品或供應商分區,可能會相當困難。作為暫時性解決方案,原始設備製造商 (OEM) 可以讓 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)」一文。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 定義新的製作檔,並改用新製作檔。如需範例,請參閱「強制執行產品分割區介面」。
我可以從 generic_system.mk 中移除與實作衝突的模組嗎?
否。GSI 包含一組可啟動和測試的模組。如果您認為某個模組不是必要的,請提出錯誤報告,以便更新 AOSP 中的 generic_system.mk
檔案。