Android 11 將 product
分區取消組合,使其遭到捨棄
不受 system
和 vendor
分區影響本次異動中
您現在可以控管 product
分區對原生和 Java 的存取權
介面 (與 vendor
強制執行介面的方式類似)
分區)。
強制執行原生介面
如要啟用原生介面的強制執行功能,請設定 PRODUCT_PRODUCT_VNDK_VERSION
至 current
。(版本在運送時會自動設為 current
目標的 API 級別大於 29)。強制執行的好處如下:
product
分區中的原生模組要連結:- 以靜態或動態方式傳送至
product
分區中的其他模組, 包括靜態、共用或標頭程式庫 - 以動態方式導入
system
分區中的 VNDK 程式庫。
- 以靜態或動態方式傳送至
product
分區中未封裝 APK 中的 JNI 程式庫,以便連結至/product/lib
或/product/lib64
中的程式庫 (除 NDK 程式庫)。
違規處置不允許「product
」以外的其他連結
建構時間強制執行機制 (Android.bp)
在 Android 11 中,系統模組可以建立產品
以及核心和供應商圖片變化版本的產品子類。原生時
已啟用介面強制執行功能 (PRODUCT_PRODUCT_VNDK_VERSION
設為
current
):
product
分區中的原生模組改用產品子類 核心變化版本Android.bp
檔案中有product_available: true
的模組為 可用的產品子類指定
product_specific: true
的程式庫或二進位檔可連結至其他 指定product_specific: true
或product_available: true
的程式庫 該檔案位於其Android.bp
檔案中。VNDK 程式庫的
Android.bp
檔案中必須包含product_available: true
因此product
二進位檔可以連結至 VNDK 程式庫。
下表摘要說明用來建立圖片的 Android.bp
屬性
子類
Android.bp 中的屬性 | 已建立變化版本 | |
---|---|---|
強制執行前 | 違規處置後 | |
預設 (無) | 核心肌群
(包括 /system 、/system_ext 和
/product )。 |
核心肌群
(包含 /system 和 /system_ext ,但不包含
/product )。 |
system_ext_specific: true |
Core | Core |
product_specific: true |
Core | 產品 |
vendor: true |
販賣機 | 販賣機 |
vendor_available: true |
核心、供應商 | 核心、供應商 |
product_available: true |
無 | 核心, 產品 |
「vendor_available: true 」和「product_available:
true 」 |
無 | 核心、產品、供應商 |
「system_ext_specific: true 」和「vendor_available:
true 」 |
核心、供應商 | 核心、供應商 |
「product_specific: true 」和「vendor_available:
true 」 |
核心、供應商 | 產品、供應商 |
建構時間強制執行機制 (Android.mk)
啟用原生介面強制執行功能後,系統會將原生模組安裝到
有 product
個分區的 native:product
連結類型只能連結至
其他 native:product
或 native:vndk
模組。嘗試連結到任何
以外的模組會導致建構系統產生連結類型檢查
錯誤。
執行階段強制執行
原生介面強制執行設定後,
生物連結器不允許系統程序使用 product
程式庫
為無法連結的 product
程序建立 product
區段
product
分區外的程式庫 (但這類程序可連結至
VNDK 程式庫)。如果嘗試違反執行階段連結設定,就會導致
並產生 CANNOT LINK EXECUTABLE
錯誤訊息
強制執行 Java 介面
如要啟用強制執行 Java 介面,請設定
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
到 true
。(值為
當目標的運送 API 級別為 true
時,會自動設為 true
大於 29)。啟用時,強制執行允許或禁止下列行為:
存取:
API | /system | /system_ext | /product | /vendor | /data |
---|---|---|---|---|---|
公用 API | |||||
@SystemApi | |||||
@隱藏 API |
與 vendor
分區相同,product
中的應用程式或 Java 程式庫
分區只能使用公用和系統 API。連結到圖書館
而不得使用隱藏的 API。這項限制包括在建構期間連結
執行偵錯。
建構時間強制執行機制
在建構期間,Make 和 Soong 驗證 product
中的 Java 模組
分區不會透過檢查 platform_apis
和
sdk_version
欄位。product
分區中應用程式的 sdk_version
必須
必須在 API 中填入 current
、system_current
或數字版本,以及
platform_apis
欄位必須留空。
執行階段強制執行
Android 執行階段會驗證 product
分區中的應用程式是否未使用
包括反射 API詳情請參閱「
非 SDK
介面。
啟用產品介面強制執行功能
請按照本節的步驟強制啟用產品介面。
步驟 | 工作 | 必填 |
---|---|---|
1 | 定義自己的系統 makefile,指定
system 分區,然後設定構件路徑規定檢查
在 device.mk 中 (避免安裝非系統模組)
至 system 分區)。 |
否 |
2 | 清理允許清單。 | 否 |
3 | 強制執行原生介面,並找出執行階段連結失敗 (可在 與 Java 強制執行平行處理工作)。 | 是 |
4 | 強制執行 Java 介面並驗證執行階段行為 (可以平行執行) 原生強制執行設定)。 | 是 |
5 | 檢查執行階段行為。 | 是 |
6 | 配合產品介面強制執行狀態更新 device.mk 。 |
是 |
步驟 1:建立 makefile 並啟用構件路徑檢查
在這個步驟中,您將定義 system
makefile。
建立定義
system
分區套件的 makefile。適用對象 例如,請使用下列指令建立oem_system.mk
檔案:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)
在
device.mk
檔案中,繼承system
的通用 makefile 以及啟用 Artifact 路徑需求條件檢查功能。例如:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
關於構件路徑要求
當 PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
設為 true
或 strict
時,
建構系統可防止其他 makefile 中定義的套件安裝
require-artifacts-in-path
中定義的路徑「並」防止套件
根據目前 makefile 的定義,安裝路徑外的構件
定義於 require-artifacts-in-path
。
在上述範例中,PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS
設定為
strict
,oem_system.mk
以外的 makefile 無法包含安裝於
root
或 system
分區。如要加入這些模組,您必須
在 oem_system.mk
檔案本身或隨附的 makefile 中定義程序。
如果嘗試將模組安裝到不允許的路徑,會導致建構中斷。修正方法
中斷時,請執行下列其中一項動作:
選項 1:在內含的 makefiles 中加入系統模組
oem_system.mk
。如此一來,就能符合構件路徑要求 (因為 模組現已存在於隨附的 makefile 中),因此允許將模組安裝至 「require-Artifacts-in-path」中定義了一組路徑方法 2:將模組安裝至
system_ext
或product
分區 (以及 不要將模組安裝至system
分區)。方法 3:將模組新增至
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
。這份清單會列出允許的模組 。
步驟 2:清空允許清單
在這個步驟中,您將讓 PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
空白,讓所有共用 oem_system.mk
的裝置也能共用單一system
圖片。如要清空允許清單,請將清單中的所有模組移到
system_ext
或 product
分區,或將分區新增至 system
來建立檔案。這個
步驟並非必要,因為不必定義一般的 system
映像檔,
允許強制使用產品介面不過,如果您清空允許清單
使用 system_ext
定義 system
邊界時相當實用。
步驟 3:強制執行原生介面
在這個步驟中,您將設定 PRODUCT_PRODUCT_VNDK_VERSION := current
,然後
並解決建構和執行階段錯誤。檢查裝置啟動和記錄
並且找出並修正執行階段連結失敗的問題:
設定
PRODUCT_PRODUCT_VNDK_VERSION := current
。建構裝置及尋找建構錯誤。您可能會看到幾個版本 缺少產品子類或核心子類。常見的休息時間 包括:
- 含有
product_specific: true
的任何hidl_interface
模組都不會 適用於系統模組如要修正,請替換product_specific: true
system_ext_specific: true
。 - 模組可能缺少產品所需的產品子類
模組。如要修正問題,請透過下列方式為
product
分區提供該模組: 設定product_available: true
或將模組移至product
數量。product_specific: true
- 含有
解決建構錯誤,並確保裝置建構成功。
刷新映像檔,並在裝置開機和記錄中尋找執行階段錯誤。
- 如果測試案例記錄中的
linker
標記顯示CANNOT LINK EXECUTABLE
訊息,就表示 make 檔案缺少依附元件 (無法在 建構時間)。 - 如要從建構系統檢查,請將必要的程式庫新增至
shared_libs:
或required:
欄位。
- 如果測試案例記錄中的
按照上述指南解決缺少的依附元件。
步驟 4:強制執行 Java 介面
在這個步驟中,您將設定 PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true
找出並修正導致的建構錯誤。尋找以下兩種特定錯誤:
連結類型錯誤。這個錯誤表示應用程式連結至 Java 模組
sdk_version
的靜態元素如要修正這個問題,您可以擴大應用程式的sdk_version
,或限製程式庫的sdk_version
。錯誤示例:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
符號錯誤。這個錯誤表示找不到符號, 位於隱藏的 API 中如要修正,請使用可見 (非隱藏) API,或尋找 。錯誤示例:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
步驟 5:檢查執行階段行為
在這個步驟中,您將驗證執行階段行為是否符合預期。對於以下類型的應用程式:
進行偵錯時,您可以透過記錄監控隱藏的 API 用量
StrictMode.detectNonSdkApiUsage
(應用程式使用
隱藏的 API)。或者,您也可以使用
veridex
靜態分析工具來取得用量類型 (連結或反映)、
限制等級和呼叫堆疊
Veridex 語法:
./art/tools/veridex/appcompat.sh --dex-file={apk file}
veridex 結果範例:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
如要進一步瞭解 veridex 的使用方式,請參閱「使用 veridex 進行測試 工具。
步驟 6:更新 device.mk
修正所有建構與執行階段失敗,並驗證執行階段
行為都符合預期,請在 device.mk
中設定以下內容:
PRODUCT_PRODUCT_VNDK_VERSION := current
PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true