存储

Android 外部存储设备 HAL 图标

Android 一直在不断发展,以期支持各种存储设备类型和功能。所有 Android 版本均支持配有传统存储空间(包括便携式存储空间和模拟存储空间)的设备。便携式存储空间是指物理介质(例如 SD 卡或 USB 设备),用于进行临时数据传输/文件存储。物理介质可以随设备一起保留更长时间,但并非固定在设备上,可以移除。自 Android 1.0 开始,SD 卡已可用作便携式存储;Android 6.0 增加了对 USB 的支持。模拟存储空间可通过将部分内部存储空间暴露于模拟层来实现,从 Android 3.0 开始便已支持此功能。

从 Android 6.0 开始,Android 支持可合并的存储设备,这种存储设备是指可以像内部存储设备那样进行加密和格式化的物理介质(例如 SD 卡或 USB 设备)。可合并的存储设备可存储各类应用数据。

权限

对外部存储设备的访问受各种 Android 权限的保护。 从 Android 1.0 开始,采用 WRITE_EXTERNAL_STORAGE 权限保护写入访问。从 Android 4.1 开始,采用 READ_EXTERNAL_STORAGE 权限保护读取访问。

从 Android 4.4 开始,外部存储设备上的文件所有者、组和模式根据目录结构合成。这样,应用可在外部存储设备上管理其文件包特定目录,而无需获得广泛的 WRITE_EXTERNAL_STORAGE 权限。 例如,文件包名称为 com.example.foo 的应用现在可以自由访问外部存储设备上的 Android/data/com.example.foo/,没有权限限制。通过将原始存储设备封装在 FUSE 守护进程中,可实现此类合成权限。

从 Android 10 开始,以 Android 9 及更低版本为目标平台的应用默认使用旧版存储空间,并且可以选择使用隔离存储空间。 以 Android 10 为目标平台并默认使用隔离存储空间的应用可以暂时选择停用隔离存储空间。可使用控制存储模型的清单属性 requestLegacyExternalStorage 更改默认状态。

由于 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限均受到软性限制,因此,如果安装程序未将应用列入白名单,则权限仅能控制对听觉和视觉集合的访问,而无权访问 SD 卡。即使在应用请求访问旧版存储空间时,也同样如此。如需详细了解硬性限制和软性限制,请参阅 Android 10 中的硬性限制和软性限制

如果安装程序将该权限列入白名单,则以旧模式运行的应用将获得非隔离权限行为。该权限可控制 SD 卡访问权限,以及听觉和视觉集合。如果应用以 Android 9 或更低版本为目标平台且不选择使用隔离存储空间,或者以 Android 10 为目标平台且选择停用隔离存储空间,就会出现这种情况。

白名单状态只能在安装时指定,并且在应用安装完成后才能更改。

如需详细了解如何设置 READ_EXTERNAL_STORAGE 权限,请参阅 PackageInstaller.SessionParams 类中的 setWhitelistedRestrictedPermissions()

运行时权限

Android 6.0 引入了一种新的运行时权限模式,在该模式下,应用可在运行时根据需要请求各项功能。由于新模式包含 READ/WRITE_EXTERNAL_STORAGE 权限,因此平台需要动态授予存储空间访问权限,同时无需终止或重启已在运行的应用。通过为所有已安装的存储设备维护以下三个不同视图,可实现该模式:

  • /mnt/runtime/default,向无特殊存储空间权限的应用以及 adbd 和其他系统组件所在的根命名空间显示
  • /mnt/runtime/read,向具有 READ_EXTERNAL_STORAGE 的应用显示(针对 Android 10 设置 LEGACY_STORAGE
  • /mnt/runtime/write,向具有 WRITE_EXTERNAL_STORAGE 的应用显示

在创建 Zygote 分支时,我们会为各运行应用创建装载命名空间,并将相应的初始视图挂载到位。稍后,在授予运行时权限后,vold 将跳转到已在运行应用的装载命名空间,并将升级后的视图挂载到位。请注意,权限降级定会导致应用被终止。

用于实现此特性的 setns() 功能至少需要运行 Linux 3.8,但补丁已成功向后移植至 Linux 3.4。PermissionsHostTest CTS 测试可用于验证内核行为是否正确。