外部存储空间由 vold
init 服务和 StorageManagerService
系统服务共同管理。外部实体存储卷的装载由 vold
处理:通过执行分阶段操作准备好媒体,然后再将其提供给应用。
注意:在 Android 8.0 中,MountService
类已更名为 StorageManagerService
。
文件映射
对于 Android 4.2.2 及更低版本,特定于设备的 vold.fstab
配置文件定义从 sysfs 设备到文件系统装载点的映射,每行都遵循以下格式:
dev_mount <label> <mount_point> <partition> <sysfs_path> [flags]
label
:卷的标签。mount_point
:要装载卷的文件系统路径。partition
:分区编号(从 1 开始);如果是第一个可用分区,则为“auto”。sysfs_path
:可以提供此装载点的设备的一个或多个 sysfs 路径。这些路径用空格分开,且必须都以/
开头。flags
:(可选)以英文逗号分隔的标记列表,不能包含/
。可能的值包括nonremovable
和encryptable
。
对于 Android 4.3 及更高版本,init、vold 和 recovery 所使用的各种 fstab 文件在 /fstab.<device>
文件中进行统一。对于由 vold
管理的外部存储卷,条目应采用以下格式:
<src> <mnt_point> <type> <mnt_flags> <fs_mgr_flags>
src
:sysfs(通常在 /sys 下装载)下可以提供装载点的设备的路径。路径必须以/
开头。mount_point
:要装载卷的文件系统路径。type
:卷上的文件系统类型。如果是外部卡,则通常为vfat
。mnt_flags
:Vold
会忽略此字段,应将其设置为defaults
fs_mgr_flags
:Vold
会忽略此字段中不包含voldmanaged=
标记的统一的 fstab 中的任何行。该标记必须后跟描述卡的标签,以及分区号或字词auto
,例如voldmanaged=sdcard:auto
。其他可能的标记包括nonremovable
、encryptable=sdcard
、noemulatedsd
和encryptable=userdata
。
配置详情
框架级别以及更高级别的外部存储空间交互通过 StorageManagerService
来处理。由于 Android 6.0 中进行了配置更改(例如移除了 storage_list.xml 资源叠加层),因此配置详情分成了两类。
Android 5.x 及更低版本
特定于设备的 storage_list.xml
配置文件(通常通过 frameworks/base
叠加层提供)定义存储设备的属性和限制。<StorageList>
元素包含一个或多个 <storage>
元素,其中一个元素应被标记为主元素。<storage>
属性包括:
mountPoint
:此装载的文件系统路径。storageDescription
:描述此装载的字符串资源。primary
:如果此装载是主要外部存储空间,则为 true。removable
:如果此装载包含可移动媒体(如实体 SD 卡),则为 true。emulated
:如果此装载由可能使用 FUSE 守护进程的内部存储设备模拟和支持,则为 true。mtp-reserve
:MTP 应为免费存储预留的存储 MB 数。仅在装载被标记为模拟时使用。allowMassStorage
:如果此装载可通过 USB 大容量存储设备共享,则为 true。maxFileSize
:文件大小上限(以 MB 为单位)。
设备可以通过模拟由内部存储支持的文件系统(不区分大小写,无需权限)来提供外部存储。system/core/sdcard
中的 FUSE 守护程序提供一个可能的实现,可添加为特定于设备的 init.rc
服务:
# virtual sdcard daemon running as media_rw (1023) service sdcard /system/bin/sdcard <source_path> <dest_path> 1023 1023 class late_start
其中,source_path
为提供支持的内部存储空间,dest_path
为目标装载点。
配置特定于设备的 init.rc
脚本时,必须将 EXTERNAL_STORAGE
环境变量定义为主要外部存储空间的路径。/sdcard
路径也必须通过符号链接解析到同一位置。如果设备在平台更新之间调整外部存储空间的位置,则应创建符号链接,以便旧的路径继续发挥作用。
Android 6.0
目前,存储子系统的配置集中在特定于设备的 fstab
文件中,并且移除了一些历史静态配置文件/变量,以支持更多动态行为:
storage_list.xml
资源叠加层已被移除,框架已不再使用该叠加层。现在,存储设备在被vold
检测到时动态配置。EMULATED_STORAGE_SOURCE/TARGET
环境变量已被移除,Zygote 已不再使用这些变量来配置特定于用户的装载点。相反,用户隔离现在由特定于用户的 GID 强制执行,主要共享存储空间由vold
在运行时装载到位。- 开发者可以根据其使用情形继续动态或静态构建路径。在路径中包含 UUID 可识别每个卡,以便为开发者提供更清晰的位置。(例如,
/storage/ABCD-1234/report.txt
明显是与/storage/DCBA-4321/report.txt
不同的文件。)
- 开发者可以根据其使用情形继续动态或静态构建路径。在路径中包含 UUID 可识别每个卡,以便为开发者提供更清晰的位置。(例如,
- 硬编码的 FUSE 服务已从特定于设备的
init.rc
文件中移除,在需要时将从vold
动态派生。
除了这些配置更改之外,Android 6.0 还包含可合并的存储设备的概念。对于 Android 6.0 设备,任何未被合并的物理介质都被视为便携式设备。
可合并的存储设备
如需在 fstab
中表示可合并的存储设备,请在 fs_mgr_flags
字段中使用 encryptable=userdata
属性。典型定义如下:
/devices/platform/mtk-msdc.1/mmc_host* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata
合并存储设备时,该平台会擦除内容并写入定义两个分区的 GUID 分区表:
- 一个较小的空
android_meta
分区,预留以备将来使用。分区类型 GUID 为 19A710A2-B3CA-11E4-B026-10604B889DCF。 - 一个较大的
android_ext
分区,使用 dm-crypt 加密并使用ext4
或f2fs
(取决于内核功能)格式化。分区类型 GUID 为 193D1EA4-B3CA-11E4-B075-10604B889DCF。
便携式存储设备
在 fstab
中,具有 voldmanaged
属性的存储设备默认被视为便携式设备,除非定义了其他属性(如 encryptable=userdata
)。例如,典型的 USB OTG 设备的定义如下:
/devices/*/xhci-hcd.0.auto/usb* auto auto defaults voldmanaged=usb:auto
该平台在装载之前使用 blkid
检测文件系统类型,用户可以选择在文件系统不受支持时将媒体格式化。