设备配置

外部存储由 vold init 服务和 MountService 系统服务共同管理。外部物理存储卷的装载由 vold 处理,它通过执行分阶段操作来准备好媒体,然后再将其提供给应用。

文件映射

对于 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:可选的逗号分隔标记列表,不能包含 /。可能的值包括 nonremovableencryptable

对于 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_flagsVold 会忽略此字段,应将其设置为 defaults
  • fs_mgr_flagsVold 会忽略此字段中不包含 voldmanaged= 标记的统一的 fstab 中的任何行。该标记必须后跟描述卡的标签,以及分区号或字词 auto。例如:voldmanaged=sdcard:auto。其他可能的标记有 nonremovableencryptable=sdcardnoemulatedsdencryptable=userdata

配置详情

框架层以及以上的外部存储交互通过 MountService 进行处理。由于 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 不同的文件。)
  • 硬编码的 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 加密并使用 ext4f2fs(取决于内核功能)格式化。分区类型 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 检测文件系统类型,用户可以选择在文件系统不受支持时将媒体格式化。