2013年1月8日火曜日

External Storage Technical Information

Android supports devices with external storage, which is defined to be a
case-insensitive and permissionless filesystem. External storage can be
provided by physical media (such as an SD card), or by an emulation layer backed
by internal storage. Devices may contain multiple instances of external
storage, but currently only the primary external storage is exposed to
developers through API.

## Device specific configuration

External storage is managed by a combination of the `vold` init service and
`MountService` system service.

Mounting of physical external storage volumes is handled by `vold`, which
performs staging operations to prepare the media before exposing it to apps.
The device-specific `vold.fstab` configuration file defines mappings from sysfs
devices to filesystem mount points, and each line follows this format:

dev_mount <label> <mount_point> <partition> <sysfs_path> [flags]

* `label`: Label for the volume.
* `mount_point`: Filesystem path where the volume should be mounted.
* `partition`: Partition number (1 based), or 'auto' for first usable partition.
* `sysfs_path`: One or more sysfs paths to devices that can provide this mount
point. Separated by spaces, and each must start with `/`.
* `flags`: Optional comma separated list of flags, must not contain `/`.
Possible values include `nonremovable` and `encryptable`.

External storage interactions at and above the framework level are handled
through `MountService`. The device-specific `storage_list.xml` configuration
file, typically provided through a `frameworks/base` overlay, defines the
attributes and constraints of storage devices. The `<StorageList>` element
contains one or more `<storage>` elements, exactly one of which should be marked
primary. `<storage>` attributes include:

* `mountPoint`: filesystem path of this mount.
* `storageDescription`: string resource that describes this mount.
* `primary`: true if this mount is the primary external storage.
* `removable`: true if this mount has removable media, such as a physical SD
card.
* `emulated`: true if this mount is emulated and is backed by internal storage,
possibly using a FUSE daemon.
* `mtp-reserve`: number of MB of storage that MTP should reserve for free
storage. Only used when mount is marked as emulated.
* `allowMassStorage`: true if this mount can be shared via USB mass storage.
* `maxFileSize`: maximum file size in MB.

Devices may provide external storage by emulating a case-insensitive,
permissionless filesystem backed by internal storage. One possible
implementation is provided by the FUSE daemon in `system/core/sdcard`, which can
be added as a device-specific `init.rc` service:

# virtual sdcard daemon running as media_rw (1023)
service sdcard /system/bin/sdcard <source_path> <dest_path> 1023 1023
class late_start

Where `source_path` is the backing internal storage and `dest_path` is the
target mount point.

When configuring a device-specific `init.rc` script, the `EXTERNAL_STORAGE`
environment variable must be defined as the path to the primary external
storage. The `/sdcard` path must also resolve to the same location, possibly
through a symlink. If a device adjusts the location of external storage between
platform updates, symlinks should be created so that old paths continue working.

As an example, here's the storage configuration for Xoom, which uses a FUSE
daemon to provide primary external storage, and includes a physical SD card as
secondary external storage:

* [vold.fstab](https://android.googlesource.com/device/moto/wingray/+/master/vold.fstab)
* [storage_list.xml](https://android.googlesource.com/device/moto/wingray/+/master/overlay/frameworks/base/core/res/res/xml/storage_list.xml)

Access to external storage is protected by various Android permissions.
Starting in Android 1.0, write access is protected with the
`WRITE_EXTERNAL_STORAGE` permission, implemented using the `sdcard_rw` GID.
Starting in Android 4.1, read access is protected with the new
`READ_EXTERNAL_STORAGE` permission, implemented using the `sdcard_r` GID. To
implement the read permission, a new top-level `/storage` directory was created
such that processes must hold the `sdcard_r` GID to traverse into it.

Since external storage offers no support for traditional POSIX filesystem
permissions, system code should not store sensitive data on external storage.
Specifically, configuration and log files should only be stored on internal
storage where they can be effectively protected.

## Multi-user external storage

Starting in Android 4.2, devices can support multiple users, and external
storage must meet the following constraints:

* Each user must have their own isolated primary external storage, and must not
have access to the primary external storage of other users.
* The `/sdcard` path must resolve to the correct user-specific primary external
storage based on the user a process is running as.
* Storage for large OBB files in the `Android/obb` directory may be shared
between multiple users as an optimization.
* Secondary external storage must not be writable by apps.

The default platform implementation of this feature leverages Linux kernel
namespaces to create isolated mount tables for each Zygote-forked process, and
then uses bind mounts to offer the correct user-specific primary external
storage into that private namespace.

At boot, the system mounts a single emulated external storage FUSE daemon at
`EMULATED_STORAGE_SOURCE`, which is hidden from apps. After the Zygote forks,
it bind mounts the appropriate user-specific subdirectory from under the FUSE
daemon to `EMULATED_STORAGE_TARGET` so that external storage paths resolve
correctly for the app. Because an app lacks accessible mount points for other
users' storage, they can only access storage for the user it was started as.

This implementation also uses the shared subtree kernel feature to propagate
mount events from the default root namespace into app namespaces, which ensures
that features like ASEC containers and OBB mounting continue working correctly.
It does this by mounting the rootfs as shared, and then remounting it as slave
after each Zygote namespace is created.
https://android.googlesource.com/platform/docs/source.android.com/+/master/src/tech/storage/index.md#

0 件のコメント:

コメントを投稿