限定範圍儲存空間

限定範圍儲存空間會限制應用程式存取外部儲存空間。在 Android 11 以上版本中,指定 API 30 以上版本的應用程式必須使用限定範圍儲存空間。在 Android 10 中,應用程式可以選擇停用限定範圍儲存空間。

應用程式存取權限制

限定範圍儲存空間旨在保護應用程式和使用者資料的隱私權。這包括保護使用者資訊 (例如相片的 metadata)、防止應用程式在未經明確授權的情況下修改或刪除使用者檔案,以及保護下載到「下載」或其他資料夾的機密使用者文件。

使用受限儲存空間的應用程式可擁有下列存取層級 (實際存取權取決於實作方式)。

  • 讀取寫入自身檔案的權限,且無須取得任何權限
  • 使用 READ_EXTERNAL_STORAGE 權限,讀取其他應用程式的媒體檔案
  • 只有在使用者直接同意的情況下,才能存取其他應用程式媒體檔案的「寫入」 (授予系統庫,以及符合「所有檔案存取權」的應用程式除外)
  • 無法讀取寫入其他應用程式的外部應用程式資料目錄

搭配 FUSE 使用限定範圍儲存空間

Android 11 以上版本支援使用者空間中的檔案系統 (FUSE),可讓 MediaProvider 模組檢查使用者空間中的檔案作業,並根據政策設定檔案存取權的許可拒絕遮蓋存取權。使用 FUSE 的限定範圍儲存空間應用程式可取得限定範圍儲存空間的隱私權功能,以及使用直接檔案路徑存取檔案的功能 (讓檔案 API 在應用程式中運作)。

由於攔截核心呼叫需要花費心力,Android 10 會針對 MediaProvider 的檔案存取作業強制執行限定範圍儲存空間規則,但不會針對直接檔案路徑存取作業 (例如使用 File API 和 NDK API) 強制執行此規則。因此,使用限定範圍儲存空間的應用程式無法使用直接檔案路徑存取檔案。這項限制影響了應用程式開發人員,因為需要大幅變更程式碼,以重新編寫 MediaProvider API 的 File API 存取權。

FUSE 和 SDCardFS

Android 11 支援 FUSE 與SDCardFS 淘汰無關,但對於先前使用 SDCardFS 的裝置,它確實提供了 Media Store 的替代方案。裝置:

  • 透過核心 5.4 以上版本啟動 Android 11 以上版本時,無法使用 SDCardFS。
  • 升級至 Android 11 以上版本後,您可以在 SDCardFS 上代管 FUSE,以便攔截檔案作業並達成隱私權目標。

FUSE 效能調整

Android 7 以下版本先前支援 FUSE,在這些版本中,外部儲存空間會掛載為 FUSE。由於 FUSE 實作方式存在效能和死結問題,Android 8 因此推出了 SDCardFS。Android 11 使用經過改善且經過更完善測試的 libfuse 實作方式,重新支援 FUSE,可調整以解決 Android 7 以下版本的效能問題。

FUSE 調整包含下列調整:

  • 針對 Android/dataAndroid/obb 目錄略過 FUSE,藉此改善仰賴這些目錄的遊戲應用程式效能。
  • 最佳化 (例如調整 FUSE 檔案系統的預讀和髒比率),以維持讀取效能和流暢的媒體播放。
  • 使用 FUSE 寫回快取。
  • 快取權限,以減少對系統伺服器的 IPC。
  • 針對具有「所有檔案」存取權的應用程式進行最佳化,加快大量作業速度。

上述調整可在 FUSE 和非 FUSE 裝置之間產生類似的效能。舉例來說,使用 FUSE 測試經過調整的 Pixel 2,以及使用媒體儲存空間測試 Pixel 2,我們發現檔案路徑存取和媒體儲存空間之間的循序讀取效能相當。不過,使用 FUSE 的連續寫入速度稍微較慢,隨機讀取和寫入速度則可能慢上兩倍。

效能評估結果可能會因裝置和特定用途而異。由於 MediaProvider API 可提供最穩定的效能,因此在意效能的應用程式開發人員應在應用程式中使用 MediaProvider API。

降低 FUSE 對效能造成的影響

FUSE 效能影響只會影響儲存在外部共用儲存空間中的檔案的大量使用者。FUSE 會略過外部私人儲存空間 (包括 android/dataandroid/obb 目錄),而內部儲存空間 (例如 /data/data,許多應用程式會在此儲存資料,以便加密及保護資料) 則不會掛載 FUSE。

  • 使用共用外部儲存空間的應用程式通常會與有限的檔案互動 (通常少於 100 個檔案)。這些應用程式可從現有的常見讀取和寫入作業最佳化功能中受益,在 Android 11 中不應受到任何 FUSE 相關效能影響。

  • 大量使用共用外部儲存空間的應用程式通常會執行大量檔案作業,例如列出或移除含有 1,000 個檔案的目錄,或是在檔案系統上建立或刪除含有百萬個檔案的目錄。在 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 資料庫保持一致。做為 FUSE 檔案系統的使用者空間處理程序,MediaProvider 可以攔截核心呼叫,並確保檔案作業的隱私安全性。

在 Android 11 以上版本中,MediaProvider 也是可在 Android 版本之外更新的模組化系統元件 (Mainline 模組)。也就是說,MediaProvider 中出現的效能、隱私權或安全性問題,可以透過 Google Play 商店或其他合作夥伴提供的機制,以無線方式修正並提供更新。範圍內的任何 FUSE 處理常式預期內容也能更新,讓更新內容修正 FUSE 效能回歸和錯誤。