可采纳存储

Android 一直以来都支持外部存储配件(例如 SD 卡),但由于这些配件的预期临时性以及为传统外部存储提供的最小数据保护,这些配件在历史上仅限于简单的文件存储。Android 6.0 引入了采纳外部存储介质以使其像内部存储一样工作的能力。

当外部存储介质被采纳时,它会被格式化和加密,以便一次只能与一台 Android 设备一起使用。由于介质与采纳它的 Android 设备紧密相连,因此它可以安全地存储所有用户的应用和私有数据。

当用户在可采纳位置插入新的存储介质(例如 SD 卡)时,Android 会询问他们希望如何使用该介质。他们可以选择采纳该介质(这将对其进行格式化和加密),也可以继续按原样使用它进行简单的文件存储。如果他们选择采纳,平台会提供将主要共享存储内容(通常挂载在 /sdcard)迁移到新采纳的介质,从而释放内部存储上的宝贵空间。与传统存储受限于 2TB(因为它使用了 MBR)不同,可采纳存储使用 GPT,因此文件存储限制约为 9ZB。

只有当开发者通过 android:installLocation 属性表明支持时,应用才能放置在采纳的存储介质上。受支持应用的新安装会自动放置在具有最多可用空间的存储设备上,并且用户可以在设置应用中在存储设备之间移动受支持的应用。移动到采纳介质的应用会在介质弹出时被记住,并在介质重新插入时返回。

安全性

平台为每个采纳的设备随机生成加密密钥,并将它们存储在 Android 设备的内部存储中。这实际上使采纳的介质与内部存储一样安全。密钥基于采纳分区 GUID 与采纳的设备相关联。

如果设备配置为在其内部存储上使用基于文件的加密 (FBE),则可采纳存储同时使用 FBE 和元数据加密。否则,可采纳存储使用全盘加密 (FDE)。

采纳设备上的磁盘布局与内部数据分区非常相似,包括 SELinux 标签等。当 Android 设备上支持多用户时,采纳的存储设备也支持多用户,其隔离级别与内部存储相同。

由于采纳的存储设备的内容与采纳它的 Android 设备紧密相连,因此加密密钥不应可从父设备中提取,因此存储设备无法在其他位置挂载。

如果您的设备使用 FBE,请参阅FBE 文档元数据加密文档,了解如何在可采纳存储上配置 FBE 和元数据加密。

性能和稳定性

只有位于稳定位置(例如电池仓内或保护盖后)的外部存储介质才应考虑用于采纳,以帮助避免意外数据丢失或损坏。特别是,连接到手机或平板电脑的 USB 设备绝不应考虑用于采纳。一个常见的例外是连接到电视式设备的外部 USB 驱动器,因为整个电视通常安装在稳定的位置。

当用户采纳新的存储设备时,平台会运行基准测试,并将其性能与内部存储进行比较。如果采纳的设备明显比内部存储慢,平台会警告用户体验可能会降级。此基准测试源自热门 Android 应用的实际 I/O 行为。目前,AOSP 实现只会向用户发出超出单个阈值的警告,但设备制造商可能会进一步调整此功能,例如,如果存储卡速度极慢,则完全拒绝采纳。

已采纳的设备必须使用支持 POSIX 权限和扩展属性的文件系统进行格式化,例如 ext4f2fs。为了获得最佳性能,建议闪存存储设备使用 f2fs 文件系统。

在执行定期空闲维护时,平台会像对内部存储一样,向已采纳的介质发出 FI_TRIM 命令。当前的 SD 卡规范不支持 DISCARD 命令;但内核会回退到 ERASE 命令,SD 卡固件可以选择使用该命令进行优化。

测试

要测试可采纳存储是否正常工作,请运行此 CTS 测试

cts-tradefed run commandAndExit cts-dev \
    -m CtsAppSecurityHostTestCases \
    -t android.appsecurity.cts.AdoptableHostTest

要验证当设备没有内置插槽或 USB 连接器正用于活动的 adb 连接时 USB 驱动器和 SD 卡的行为,请使用

adb shell sm set-virtual-disk true