傳統存儲

Android 外部存儲 HAL 圖標

Android 支持具有傳統存儲的設備,傳統存儲被定義為具有不可變 POSIX 權限類和模式的不區分大小寫的文件系統。傳統存儲的概念包括模擬存儲和便攜式存儲。便攜式存儲被定義為系統未採用的任何外部存儲,因此未格式化和加密或綁定到特定設備。因為傳統的外部存儲為存儲的數據提供了最低限度的保護,所以系統代碼不應將敏感數據存儲在外部存儲上。具體來說,配置和日誌文件應該只存儲在可以有效保護它們的內部存儲中。

多用戶外部存儲

從 Android 4.2 開始,設備可以支持多個用戶,並且外部存儲必須滿足以下約束:

  • 每個用戶必須有自己獨立的主外部存儲,並且不能訪問其他用戶的主外部存儲。
  • /sdcard路徑必鬚根據運行進程的用戶解析為正確的用戶特定的主外部存儲。
  • 作為優化, Android/obb目錄中的大型 OBB 文件的存儲可以在多個用戶之間共享。
  • 輔助外部存儲不得由應用程序寫入,除非在合成權限允許的特定包目錄中。

此功能的默認平台實現利用 Linux 內核命名空間為每個 Zygote 分叉進程創建隔離的掛載表,然後使用綁定掛載將正確的用戶特定主外部存儲提供到該私有命名空間中。

在啟動時,系統會在EMULATED_STORAGE_SOURCE上掛載一個模擬的外部存儲 FUSE 守護程序,該守護程序對應用程序是隱藏的。在 Zygote 分叉之後,它會將 FUSE 守護程序下的適當用戶特定子目錄綁定到EMULATED_STORAGE_TARGET ,以便為應用程序正確解析外部存儲路徑。由於應用程序缺少其他用戶存儲的可訪問掛載點,因此他們只能訪問啟動它的用戶的存儲。

此實現還使用共享子樹內核功能將掛載事件從默認根命名空間傳播到應用命名空間,從而確保 ASEC 容器和 OBB 掛載等功能繼續正常工作。它通過將 rootfs 掛載為共享文件,然後在創建每個 Zygote 命名空間後將其重新掛載為從屬文件來實現此目的。

多個外部存儲設備

從 Android 4.4 開始,多個外部存儲設備通過Context.getExternalFilesDirs()Context.getExternalCacheDirs()Context.getObbDirs()呈現給開發人員。

通過這些 API 顯示的外部存儲設備必須是設備的半永久性部分(例如電池盒中的 SD 卡插槽)。開發人員希望存儲在這些位置的數據能夠長期可用。因此,不應通過這些 API 顯示臨時存儲設備(例如 USB 大容量存儲驅動器)。

WRITE_EXTERNAL_STORAGE權限只能授予對設備上主要外部存儲的寫訪問權限。不得允許應用程序寫入輔助外部存儲設備,除非在合成權限允許的特定包目錄中。以這種方式限制寫入可確保系統可以在卸載應用程序時清理文件。

USB 媒體支持

Android 6.0 支持僅短時間連接到設備的便攜式存儲設備,例如 USB 閃存驅動器。當用戶插入新的便攜式設備時,平台會顯示一條通知,讓他們複製或管理該設備的內容。

在 Android 6.0 中,任何未採用的設備都被視為便攜設備。由於便攜式存儲的連接時間很短,平台避免了媒體掃描等繁重的操作。第三方應用程序必須通過存儲訪問框架才能與便攜式存儲上的文件進行交互;出於隱私和安全原因,直接訪問被明確禁止。