限定範圍儲存空間會限制應用程式存取外部儲存空間,在 Android 11 以上版本中,指定 API 30 以上版本的應用程式必須使用限定範圍儲存空間。在 Android 10 中,應用程式可以選擇停用限定範圍儲存空間。
應用程式存取限制
限定範圍儲存空間的目標是保護應用程式和使用者資料的隱私權。包括保護使用者資訊 (例如相片中繼資料)、防止應用程式在未明確取得權限的情況下修改或刪除使用者檔案,以及保護下載至「下載」或其他資料夾的機密使用者文件。
使用範圍儲存空間的應用程式可具有下列存取層級 (實際存取權取決於實作方式)。
- 讀取和寫入自己的檔案,但沒有任何權限
- 讀取其他應用程式的媒體檔案 (須具備
READ_EXTERNAL_STORAGE
權限) - 只有在使用者直接同意的情況下,才能寫入其他應用程式的媒體檔案 (系統相簿和符合「所有檔案存取權」資格的應用程式除外)
- 無法讀取或寫入其他應用程式的外部應用程式資料目錄
搭配 FUSE 使用限定範圍儲存空間
Android 11 以上版本支援 Filesystem in Userspace (FUSE),可讓 MediaProvider 模組檢查使用者空間中的檔案作業,並根據政策允許、拒絕或遮蓋檔案存取權。使用 FUSE 的限定範圍儲存空間應用程式可享有限定範圍儲存空間的隱私權功能,並透過直接檔案路徑存取檔案 (讓檔案 API 在應用程式中正常運作)。
Android 10 對 MediaProvider 存取檔案強制執行限定範圍儲存空間規則,但由於攔截核心呼叫需要大量工作,因此不適用於直接存取檔案路徑 (例如使用 File API 和 NDK API)。因此,限定範圍儲存空間中的應用程式無法使用直接檔案路徑存取檔案。這項限制影響了應用程式開發人員的適應能力,因為他們必須大幅修改程式碼,才能將檔案 API 存取權重新編寫為 MediaProvider API。
FUSE 和 SDCardFS
Android 11 支援 FUSE 與淘汰 SDCardFS 無關,但可為先前使用 SDCardFS 的裝置提供 Media Store 替代方案。裝置:
- 如果裝置搭載 Android 11 以上版本,且使用 5.4 以上的 Kernel,就無法使用 SDCardFS。
- 升級至 Android 11 以上版本後,即可在 SDCardFS 上代管 FUSE,攔截檔案作業並達成隱私權目標。
調整 FUSE 效能
Android 先前在 Android 7 以下版本支援 FUSE,當時外部儲存空間是掛接為 FUSE。由於該 FUSE 實作方式會導致效能和死結問題,Android 8 導入了 SDCardFS。Android 11 重新導入 FUSE 支援,並使用經過改良且測試完善的 libfuse
實作,可進行調整以解決 Android 7 以下版本中的效能問題。
FUSE 調整包括下列微調:
- 略過
Android/data
和Android/obb
目錄的 FUSE,提升依賴這些目錄的遊戲應用程式效能。 - 最佳化 (例如調整 FUSE 檔案系統的預先讀取和髒比率),確保讀取作業效能良好,並順暢播放媒體。
- 使用 FUSE 回寫快取。
- 快取權限,減少系統伺服器的 IPC。
- 針對有權存取所有檔案的應用程式進行最佳化,加快大量作業的速度。
上述微調可讓 FUSE 和非 FUSE 裝置的效能不相上下。舉例來說,使用 FUSE 測試經過調整的 Pixel 2,以及使用 Media Store 測試 Pixel 2 時,發現檔案路徑存取和 Media Store 之間的循序讀取效能 (例如影片播放) 相當。不過,使用 FUSE 時,循序寫入的效能略有下降,隨機讀取和寫入速度則可能慢上一倍。
效能測量結果可能會因裝置而異,也可能因特定用途而有所不同。由於 MediaProvider API 的效能最穩定,因此如果應用程式開發人員很重視效能,就應該使用 MediaProvider API。
減少 FUSE 對效能的影響
FUSE 效能影響僅限於大量使用儲存在外部共用儲存空間檔案的使用者。FUSE 會略過外部私人儲存空間 (包括 android/data
和 android/obb
目錄),而內部儲存空間 (例如 /data/data
,許多應用程式會將資料儲存在這個位置,確保資料經過加密且安全無虞) 則不會掛接 FUSE。
如果應用程式很少使用共用外部儲存空間,通常只會與一小部分檔案互動 (通常少於 100 個檔案)。這些應用程式可受益於常見讀寫作業的現有最佳化功能,且在 Android 11 中不應受到任何 FUSE 相關效能影響。
大量使用共用外部儲存空間的應用程式通常會執行大量檔案作業,例如列出或移除含有 1000 個檔案的目錄,或在檔案系統中建立或刪除含有 100 萬個檔案的目錄。Android 11 的 FUSE 可能會影響大量檔案作業,但如果這類應用程式符合
MANAGE_EXTERNAL_STORAGE
權限的資格,就能享有 2020 年 10 月更新中提供的效能最佳化功能。
為避免 FUSE 效能負擔過重,應用程式可以將資料儲存在外部私人儲存空間,或使用 ContentProvider
類別中的大量 API 略過 FUSE,取得效能最佳化的路徑。此外,2020 年 10 月的 MediaProvider 系統元件更新也包含檔案管理員和類似應用程式 (例如備份/還原、防毒) 的效能最佳化功能,這些應用程式持有 MANAGE_EXTERNAL_STORAGE
權限。
隱私權優先於成效
在經過 FUSE 調整的裝置上,Android 10 和 Android 11 的大部分重要使用者歷程效能相同。不過,在測試一組檔案作業的基準時,Android 11 的效能可能會比 Android 10 差。如果檔案存取模式在 Android 11 中效能較差 (例如隨機讀取或寫入),建議使用 MediaProvider API,讓應用程式採用非 FUSE 存取模式,這是最佳且效能一致的選項。
MediaProvider 和 FUSE 更新
MediaProvider 系統元件的行為因 Android 版本而異。
在 Android 10 以下版本中,SDCardFS 是檔案系統,而 MediaProvider 提供檔案集合的介面 (例如圖片、影片、音樂檔案等)。應用程式使用 File API 建立檔案時,可以要求 MediaProvider 掃描檔案並記錄在資料庫中。
在 Android 11 以上版本中,SDCardFS 已遭淘汰,MediaProvider 則成為外部儲存空間的檔案系統處理常式 (適用於 FUSE),可確保外部儲存空間的檔案系統與 MediaProvider 資料庫保持一致。MediaProvider 是 FUSE 檔案系統的使用者空間處理常式,可攔截核心呼叫,確保檔案作業符合隱私權規定。
在 Android 11 以上版本中,MediaProvider 也是模組化系統元件 (Mainline 模組),可在 Android 版本發布後更新。也就是說,如果 MediaProvider 發生效能、隱私權或安全性問題,可以透過 Google Play 商店或其他合作夥伴提供的機制,修正並透過無線方式傳送更新。FUSE 處理常式預期範圍內的任何項目也都能更新,因此可透過更新修正 FUSE 效能回歸和錯誤。