Android Pony EXpress (APEX) 容器格式是在 Android 10 中推出,用於較低層級系統模組的安裝流程。這種格式可讓您更新不符合標準 Android 應用程式模型的系統元件。例如原生服務和程式庫、硬體抽象層 (HAL)、執行階段 (ART) 和類別程式庫。
「APEX」一詞也可能指 APEX 檔案。
背景
雖然 Android 支援透過套件安裝程式應用程式 (例如 Google Play 商店應用程式) 更新標準應用程式模型中的模組 (例如服務、活動),但對較低層級的 OS 元件使用類似模型有下列缺點:
- APK 型模組無法在開機順序的早期使用。套件管理工具是應用程式資訊的中央存放區,只能從活動管理工具啟動,而活動管理工具會在啟動程序的後續階段準備就緒。
- APK 格式 (尤其是資訊清單) 是為 Android 應用程式設計,不一定適合系統模組。
設計
本節說明 APEX 檔案格式和 APEX 管理員的高階設計,APEX 管理員是管理 APEX 檔案的服務。
如要進一步瞭解為何選擇這種 APEX 設計,請參閱「開發 APEX 時考慮的替代方案」。
APEX 格式
這是 APEX 檔案的格式。
圖 1. APEX 檔案格式
在頂層,APEX 檔案是 ZIP 檔案,其中的檔案會以未壓縮形式儲存,且位於 4 KB 邊界。
APEX 檔案中的四個檔案如下:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
apex_manifest.json
檔案包含套件名稱和版本,用於識別 APEX 檔案。這是 JSON 格式的ApexManifest
通訊協定緩衝區。
APEX 檔案可透過 AndroidManifest.xml
檔案使用 APK 相關工具和基礎架構,例如 ADB、PackageManager 和套件安裝程式應用程式 (例如 Play 商店)。舉例來說,APEX 檔案可以使用現有工具 (例如 aapt
) 檢查檔案中的基本中繼資料。檔案包含套件名稱和版本資訊。這項資訊通常也會顯示在 apex_manifest.json
中。
對於處理 APEX 的新程式碼和系統,建議使用 apex_manifest.json
,而非 AndroidManifest.xml
。AndroidManifest.xml
可能包含額外的指定目標資訊,可供現有的應用程式發布工具使用。
apex_payload.img
是由 dm-verity 支援的 ext4 檔案系統映像檔。映像檔會在執行階段透過迴路裝置掛接。具體來說,雜湊樹狀結構和中繼資料區塊是使用 libavb
程式庫建立。檔案系統酬載未經剖析 (因為圖片應可就地掛接)。一般檔案會包含在 apex_payload.img
檔案中。
apex_pubkey
是用來簽署檔案系統映像檔的公開金鑰。在執行階段,這個金鑰可確保下載的 APEX 與內建分割區中簽署相同 APEX 的實體,是使用相同實體簽署。
APEX 命名規範
為避免平台進步時,新 APEX 發生命名衝突,請遵守下列命名規範:
com.android.*
- 保留給 Android 開放原始碼計畫 APEX。不專屬於任何公司或裝置。
com.<companyname>.*
- 保留給公司。可能由該公司的多部裝置使用。
com.<companyname>.<devicename>.*
- 保留給特定裝置 (或裝置子集) 專屬的 APEX。
APEX 管理員
APEX 管理員 (或 apexd
) 是獨立的原生程序,負責驗證、安裝及解除安裝 APEX 檔案。這個程序會在啟動序列的早期啟動,並準備就緒。APEX 檔案通常會預先安裝在裝置的 /system/apex
下。如果沒有可用的更新,APEX 管理員預設會使用這些套件。
APEX 的更新順序會使用 PackageManager 類別,如下所示。
- 透過套件安裝程式應用程式、ADB 或其他來源下載 APEX 檔案。
- 套件管理工具會啟動安裝程序。套件管理員辨識出檔案為 APEX 後,會將控制權轉移給 APEX 管理員。
- APEX 管理員會驗證 APEX 檔案。
- 如果 APEX 檔案通過驗證,APEX 管理員的內部資料庫就會更新,反映 APEX 檔案會在下次啟動時啟用。
- 套件驗證成功後,安裝要求者會收到廣播。
- 如要繼續安裝,系統必須重新啟動。
下次啟動時,APEX 管理員會啟動、讀取內部資料庫,並對列出的每個 APEX 檔案執行下列操作:
- 驗證 APEX 檔案。
- 從 APEX 檔案建立迴路裝置。
- 在迴路介面裝置上建立裝置對應程式區塊裝置。
- 將裝置對應程式區塊裝置掛載至專屬路徑 (例如
/apex/name@ver
)。
當內部資料庫中列出的所有 APEX 檔案都已掛接時,APEX 管理工具會提供繫結器服務,供其他系統元件查詢已安裝 APEX 檔案的相關資訊。舉例來說,其他系統元件可以查詢裝置中安裝的 APEX 檔案清單,或查詢特定 APEX 的確切掛接路徑,以便存取檔案。
APEX 檔案是 APK 檔案
APEX 檔案是有效的 APK 檔案,因為這類檔案是經過簽署的 ZIP 封存檔 (使用 APK 簽名配置),內含 AndroidManifest.xml
檔案。這樣一來,APEX 檔案就能使用 APK 檔案的基礎架構,例如套件安裝程式應用程式、簽署公用程式和套件管理員。
APEX 檔案中的 AndroidManifest.xml
檔案非常精簡,包含套件 name
、versionCode
,以及用於精細指定目標的選用 targetSdkVersion
、minSdkVersion
和 maxSdkVersion
。這項資訊可讓 APEX 檔案透過現有管道 (例如套件安裝程式應用程式和 ADB) 傳送。
支援的檔案類型
APEX 格式支援下列檔案類型:
- 原生共用程式庫
- 原生可執行檔
- JAR 檔案
- 資料檔案
- 設定檔
這並不代表 APEX 可以更新所有這些檔案類型。檔案類型是否可以更新,取決於平台和檔案類型介面定義的穩定程度。
簽署選項
APEX 檔案的簽署方式有兩種。首先,apex_payload.img
檔案 (具體來說,是附加至 apex_payload.img
的 vbmeta 描述元) 會以金鑰簽署。然後使用 APK 簽署配置 v3 簽署整個 APEX。這個程序會使用兩把不同的金鑰。
在裝置端,系統會安裝與用於簽署 vbmeta 描述元的私密金鑰對應的公開金鑰。APEX 管理員會使用公開金鑰驗證要求安裝的 APEX。每個 APEX 都必須使用不同的金鑰簽署,且在建構和執行階段都會強制執行。
內建分區中的 APEX
APEX 檔案可位於 /system
等內建分割區。分割區已超過 dm-verity,因此 APEX 檔案會直接掛接在迴路裝置上。
如果內建分割區中存在 APEX,只要提供套件名稱相同且版本代碼大於或等於的 APEX 套件,即可更新 APEX。新的 APEX 會儲存在 /data
中,與 APK 類似,新安裝的版本會遮蔽內建分割區中已有的版本。但與 APK 不同的是,新安裝的 APEX 版本只會在重新啟動後啟用。
核心需求
如要在 Android 裝置上支援 APEX 主線模組,必須具備下列 Linux 核心功能:迴路驅動程式和 dm-verity。迴路驅動程式會在 APEX 模組中掛接檔案系統映像檔,而 dm-verity 會驗證 APEX 模組。
使用 APEX 模組時,迴路驅動程式和 dm-verity 的效能對於實現良好的系統效能至關重要。
支援的核心版本
使用核心版本 4.4 以上的裝置支援 APEX 主線模組。搭載 Android 10 以上版本的新裝置必須使用核心 4.9 以上版本,才能支援 APEX 模組。
必要核心修補程式
Android 通用樹狀結構包含支援 APEX 模組的必要核心修補程式。如要取得支援 APEX 的修補程式,請使用最新版本的 Android 通用樹狀結構。
核心版本 4.4
這個版本僅適用於從 Android 9 升級至 Android 10,且想支援 APEX 模組的裝置。強烈建議從 android-4.4
分支進行向下合併,取得必要修補程式。以下是核心版本 4.4 的必要個別修補程式清單。
- UPSTREAM: loop: add ioctl for changing logical block size (4.4)
- BACKPORT: block/loop: set hw_sectors (4.4)
- UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
- ANDROID:mnt:修正 next_descendent (4.4)
- ANDROID:mnt: remount 應傳播至從屬裝置的從屬裝置 (4.4)
- ANDROID:mnt:正確傳播重新掛接 (4.4)
- Revert "ANDROID: dm verity: add minimum prefetch size" (4.4)
- UPSTREAM: loop: drop caches if offset or block_size are changed (4.4)
核心版本 4.9/4.14/4.19
如要取得核心版本 4.9/4.14/4.19 的必要修補程式,請從 android-common
分支向下合併。
必要核心設定選項
以下列出支援 Android 10 中導入的 APEX 模組的基本設定需求。標有星號 (*) 的項目是 Android 9 以下版本的現有規定。
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
核心指令列參數規定
如要支援 APEX,請確保核心指令列參數符合下列規定:
- 不得設定「
loop.max_loop
」 loop.max_part
必須 <= 8
建構 APEX
本節說明如何使用 Android 建構系統建構 APEX。以下是名為 apex.test
的 APEX 的 Android.bp
範例。
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
apex_manifest.json
範例:
{
"name": "com.android.example.apex",
"version": 1
}
file_contexts
範例:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
APEX 中的檔案類型和位置
檔案類型 | APEX 中的位置 |
---|---|
共享相片庫 | /lib 和 /lib64 (/lib/arm 用於 x86 中經過翻譯的 ARM) |
可執行檔 | /bin |
Java 程式庫 | /javalib |
預先建構 | /etc |
遞移依附元件
APEX 檔案會自動納入原生共用程式庫或可執行檔的轉換依附元件。舉例來說,如果 libFoo
依附於 libBar
,則當 libFoo
僅列於 native_shared_libs
屬性中時,系統會一併納入這兩個程式庫。
處理多個 ABI
為裝置的主要和次要應用程式二進位檔介面 (ABI) 安裝 native_shared_libs
屬性。如果 APEX 適用於具有單一 ABI 的裝置 (也就是僅限 32 位元或僅限 64 位元),則只會安裝具有相應 ABI 的程式庫。
請只為裝置的主要 ABI 安裝 binaries
屬性,如下所述:
- 如果裝置僅支援 32 位元,系統只會安裝二進位檔的 32 位元變體版本。
- 如果裝置僅支援 64 位元,則只會安裝二進位的 64 位元變體。
如要精細控管原生程式庫和二進位檔的 ABI,請使用 multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
屬性。
first
:與裝置的主要 ABI 相符。這是二進位檔的預設值。lib32
:如果裝置支援,則會與裝置的 32 位元 ABI 相符。lib64
:與裝置的 64 位元 ABI 相符,支援該 ABI。prefer32
:如果裝置支援,則會與裝置的 32 位元 ABI 相符。如果系統不支援 32 位元 ABI,則會比照 64 位元 ABI。both
:比對兩個 ABI。這是native_shared_libraries
的預設值。
java
、libraries
和 prebuilts
屬性與 ABI 無關。
這個範例適用於支援 32/64 位元,但不偏好 32 位元的裝置:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
vbmeta 簽署
使用不同金鑰簽署每個 APEX。需要新金鑰時,請建立公開/私密金鑰組,並製作 apex_key
模組。使用 key
屬性,透過金鑰簽署 APEX。公開金鑰會自動納入 APEX,名稱為 avb_pubkey
。
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
在上述範例中,公開金鑰的名稱 (foo
) 會成為金鑰的 ID。用來簽署 APEX 的金鑰 ID 會寫入 APEX。在執行階段,apexd
會使用裝置中 ID 相同的公開金鑰驗證 APEX。
APEX 簽署
簽署 APEX 的方式與簽署 APK 相同。為 APEX 簽署兩次,一次是針對迷你檔案系統 (apex_payload.img
檔案),一次是針對整個檔案。
如要在檔案層級簽署 APEX,請透過下列三種方式之一設定 certificate
屬性:
- 未設定:如未設定任何值,系統會使用
PRODUCT_DEFAULT_DEV_CERTIFICATE
中的憑證簽署 APEX。如未設定任何旗標,路徑預設為build/target/product/security/testkey
。 <name>
:APEX 會使用與PRODUCT_DEFAULT_DEV_CERTIFICATE
相同的目錄中的<name>
憑證簽署。:<name>
:APEX 會使用名為<name>
的 Soong 模組所定義的憑證簽署。憑證模組可定義如下。
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
安裝 APEX
如要安裝 APEX,請使用 ADB。
adb install apex_file_name
adb reboot
如果 supportsRebootlessUpdate
在 apex_manifest.json
中設為 true
,且目前安裝的 APEX 未使用 (例如,其中包含的任何服務都已停止),則可以使用 --force-non-staged
旗標安裝新的 APEX,無需重新啟動。
adb install --force-non-staged apex_file_name
使用 APEX
重新啟動後,APEX 會掛載在 /apex/<apex_name>@<version>
目錄。您可以同時掛載同一 APEX 的多個版本。在掛接路徑中,對應最新版本的路徑會繫結掛接至 /apex/<apex_name>
。
用戶端可以使用繫結掛接路徑,從 APEX 讀取或執行檔案。
APEX 通常用於下列用途:
- OEM 或 ODM 會在裝置出貨時,預先載入
/system/apex
下的 APEX。 - APEX 中的檔案是透過
/apex/<apex_name>/
路徑存取。 - 在
/data/apex
中安裝更新版 APEX 時,路徑會在重新啟動後指向新的 APEX。
使用 APEX 更新服務
如要使用 APEX 更新服務,請按照下列步驟操作:
將系統分區中的服務標示為可更新。在服務定義中新增選項
updatable
。/system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
為更新後的服務建立新的
.rc
檔案。使用「override
」選項重新定義現有服務。/apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
服務定義只能在 APEX 的 .rc
檔案中定義。APEX 不支援動作觸發程序。
如果標示為可更新的服務在 APEX 啟動前啟動,系統會延遲啟動,直到 APEX 啟動完成為止。
設定系統以支援 APEX 更新
將下列系統屬性設為 true
,即可支援 APEX 檔案更新。
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
或只是
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
扁平化 APEX
對於舊版裝置,有時無法或不適合更新舊版核心,以完全支援 APEX。舉例來說,核心可能是在沒有 CONFIG_BLK_DEV_LOOP=Y
的情況下建構,而這對於在 APEX 內掛接檔案系統映像檔至關重要。
扁平化 APEX 是特別建構的 APEX,可在搭載舊版核心的裝置上啟用。扁平化 APEX 中的檔案會直接安裝至內建分割區下的目錄。舉例來說,扁平化 APEX lib/libFoo.so
中的 my.apex
會安裝至 /system/apex/my.apex/lib/libFoo.so
。
啟動扁平化 APEX 時,不會用到迴路裝置。整個目錄 /system/apex/my.apex
會直接繫結掛接至 /apex/name@ver
。
無法透過從網路下載更新版本的 APEX 更新扁平化 APEX,因為下載的 APEX 無法扁平化。只能透過一般 OTA 更新扁平化 APEX。
預設設定為扁平化 APEX。也就是說,除非您明確設定裝置建構非扁平化 APEX,以支援 APEX 更新 (如上所述),否則所有 APEX 預設都會扁平化。
裝置「不支援」同時使用扁平化和非扁平化 APEX。裝置中的 APEX 必須全為非扁平化或全為扁平化。
如果專案 (例如 Mainline) 要運送預先簽署的 APEX 預建版本,這點就格外重要。未預先簽署的 APEX (即從來源建構的 APEX) 也應為非扁平化,並以適當的金鑰簽署。如「使用 APEX 更新服務」一文所述,裝置應從 updatable_apex.mk
繼承。
壓縮 APEX
Android 12 以上版本提供 APEX 壓縮功能,可減少可更新 APEX 套件對儲存空間的影響。安裝 APEX 更新後,雖然系統不再使用預先安裝的版本,但仍會佔用相同大小的空間。該空間仍無法使用。
APEX 壓縮功能會在唯讀分割區 (例如 /system
分割區) 使用高度壓縮的 APEX 檔案集,盡量減少對儲存空間的影響。Android 12 以上版本使用 DEFLATE zip 壓縮演算法。
壓縮功能無法對下列項目進行最佳化:
啟動需要在開機順序中很早就掛接的 APEX。
無法更新的 APEX。 只有在
/data
分區上安裝 APEX 的更新版本時,壓縮才有好處。如需可更新 APEX 的完整清單,請參閱「模組化系統元件」頁面。動態共用程式庫 APEX。由於
apexd
一律會啟用這類 APEX 的兩個版本 (預先安裝和升級),因此壓縮這些版本不會增加價值。
壓縮 APEX 檔案格式
這是壓縮 APEX 檔案的格式。
圖 2. 壓縮 APEX 檔案格式
在頂層,壓縮的 APEX 檔案是 ZIP 檔案,內含原始 APEX 檔案 (已解壓縮,壓縮層級為 9),以及其他未壓縮的檔案。
APEX 檔案包含四個檔案:
original_apex
:以壓縮等級 9 壓縮。這是原始的未壓縮 APEX 檔案。apex_manifest.pb
:僅儲存AndroidManifest.xml
:僅儲存apex_pubkey
:僅儲存
apex_manifest.pb
、AndroidManifest.xml
和 apex_pubkey
檔案是 original_apex
中對應檔案的副本。
建構壓縮的 APEX
您可以使用 system/apex/tools
中的 apex_compression_tool.py
工具建構壓縮 APEX。
建構系統提供多個與 APEX 壓縮相關的參數。
在 Android.bp
中,APEX 檔案是否可壓縮是由 compressible
屬性控制:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
PRODUCT_COMPRESSED_APEX
產品標記會控管從來源建構的系統映像檔是否必須包含壓縮的 APEX 檔案。
如要進行本機實驗,您可以將 OVERRIDE_PRODUCT_COMPRESSED_APEX=
設為 true
,強制壓縮 APEX。
建構系統產生的壓縮 APEX 檔案副檔名為 .capex
。這個擴充功能可讓您輕鬆區分 APEX 檔案的壓縮和未壓縮版本。
支援的壓縮演算法
Android 12 僅支援 deflate-zip 壓縮。
在啟動期間啟用壓縮的 APEX 檔案
壓縮的 APEX 啟用前,其中的 original_apex
檔案會解壓縮到 /data/apex/decompressed
目錄。解壓縮後產生的 APEX 檔案會硬連結至 /data/apex/active
目錄。
請參考以下範例,瞭解上述程序。
請將 /system/apex/com.android.foo.capex
視為已啟用的壓縮 APEX,版本代碼為 37。
/system/apex/com.android.foo.capex
內的original_apex
檔案會解壓縮到/data/apex/decompressed/com.android.foo@37.apex
。restorecon /data/apex/decompressed/com.android.foo@37.apex
,確認其 SELinux 標籤是否正確。- 系統會對
/data/apex/decompressed/com.android.foo@37.apex
執行驗證檢查,確保其有效性:apexd
會檢查/data/apex/decompressed/com.android.foo@37.apex
中綁定的公開金鑰,確認該金鑰與/system/apex/com.android.foo.capex
中綁定的金鑰相同。 /data/apex/decompressed/com.android.foo@37.apex
檔案會硬連結至/data/apex/active/com.android.foo@37.apex
目錄。- 系統會在
/data/apex/active/com.android.foo@37.apex
上執行未壓縮 APEX 檔案的正常啟用邏輯。
與 OTA 互動
壓縮 APEX 檔案會影響 OTA 傳送和應用程式。由於 OTA 更新可能包含版本層級高於裝置上現有版本的壓縮 APEX 檔案,因此裝置必須預留一定量的可用空間,才能在重新啟動後套用 OTA 更新。
為支援 OTA 系統,apexd
會公開這兩項繫結器 API:
calculateSizeForCompressedApex
- calculates the size required to decompress APEX files in an OTA package. 這項資訊可用於確認裝置是否有足夠空間,再下載 OTA 更新。reserveSpaceForCompressedApex
- 在磁碟上保留空間,供apexd
日後使用,以便解壓縮 OTA 套件中的壓縮 APEX 檔案。
如果是 A/B OTA 更新,apexd
會在背景嘗試解壓縮,這是 OTA 安裝後例行程序的一部分。如果解壓縮失敗,apexd
會在啟動期間執行解壓縮,套用 OTA 更新。
開發 APEX 時考慮的替代方案
以下是 AOSP 設計 APEX 檔案格式時考量的部分選項,以及納入或排除這些選項的原因。
定期套件管理系統
Linux 發行版有 dpkg
和 rpm
等套件管理系統,不過,由於這些簽章無法在安裝後保護套件,因此未採用於 APEX。只有在安裝套件時才會執行驗證。
攻擊者可以破壞已安裝套件的完整性,且不會遭到察覺。這是 Android 的回歸,所有系統元件都儲存在唯讀檔案系統中,而每個 I/O 的 dm-verity 都會保護檔案系統的完整性。必須禁止或偵測對系統元件的任何竄改行為,以便在裝置遭入侵時拒絕啟動。
使用 dm-crypt 確保完整性
APEX 容器中的檔案來自受 dm-verity 保護的內建分割區 (例如 /system
分割區),即使分割區已掛接,也不允許修改檔案。為確保檔案安全無虞,APEX 中的所有檔案都會儲存在檔案系統映像檔中,並與雜湊樹狀結構和 vbmeta 描述元配對。如果沒有 dm-verity,/data
分割區中的 APEX 就容易在驗證和安裝後遭到非預期的修改。
事實上,/data
分割區也受到 dm-crypt 等加密層保護。雖然這項功能可提供一定程度的防竄改保護,但主要目的是保護隱私,而非確保完整性。攻擊者一旦取得 /data
分區的存取權,就無法再提供任何保護措施。相較於所有系統元件都位於 /system
分區,這也是一種退步。APEX 檔案中的雜湊樹狀結構和 dm-verity 可提供相同等級的內容保護。
將路徑從 /system 重新導向至 /apex
APEX 中封裝的系統元件檔案可透過 /apex/<name>/lib/libfoo.so
等新路徑存取。如果檔案位於 /system
分割區,則可透過 /system/lib/libfoo.so
等路徑存取。APEX 檔案的用戶端 (其他 APEX 檔案或平台) 必須使用新路徑。路徑變更後,您可能需要更新現有程式碼。
雖然將 APEX 檔案中的檔案內容疊加到 /system
分區,可以避免路徑變更,但 Android 團隊決定不要在 /system
分區疊加檔案,因為這樣可能會影響效能,疊加的檔案數量 (甚至可能是一個接一個堆疊) 越多,影響就越大。
另一種做法是盜用檔案存取函式,例如 open
、stat
和 readlink
,將以 /system
開頭的路徑重新導向至 /apex
下的對應路徑。Android 團隊已捨棄這個選項,因為要變更所有接受路徑的函式並不可行。舉例來說,部分應用程式會靜態連結 Bionic,而 Bionic 會實作這些函式。
在這種情況下,這些應用程式不會重新導向。