1<!-- 2 Copyright 2012 The Android Open Source Project 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15--> 16 17# External Storage Technical Information 18 19Android supports devices with external storage, which is defined to be a 20case-insensitive and permissionless filesystem. External storage can be 21provided by physical media (such as an SD card), or by an emulation layer backed 22by internal storage. Devices may contain multiple instances of external 23storage, but currently only the primary external storage is exposed to 24developers through API. 25 26## Device specific configuration 27 28External storage is managed by a combination of the `vold` init service and 29`MountService` system service. 30 31Mounting of physical external storage volumes is handled by `vold`, which 32performs staging operations to prepare the media before exposing it to apps. 33The device-specific `vold.fstab` configuration file defines mappings from sysfs 34devices to filesystem mount points, and each line follows this format: 35 36 dev_mount <label> <mount_point> <partition> <sysfs_path> [flags] 37 38* `label`: Label for the volume. 39* `mount_point`: Filesystem path where the volume should be mounted. 40* `partition`: Partition number (1 based), or 'auto' for first usable partition. 41* `sysfs_path`: One or more sysfs paths to devices that can provide this mount 42point. Separated by spaces, and each must start with `/`. 43* `flags`: Optional comma separated list of flags, must not contain `/`. 44Possible values include `nonremovable` and `encryptable`. 45 46External storage interactions at and above the framework level are handled 47through `MountService`. The device-specific `storage_list.xml` configuration 48file, typically provided through a `frameworks/base` overlay, defines the 49attributes and constraints of storage devices. The `<StorageList>` element 50contains one or more `<storage>` elements, exactly one of which should be marked 51primary. `<storage>` attributes include: 52 53* `mountPoint`: filesystem path of this mount. 54* `storageDescription`: string resource that describes this mount. 55* `primary`: true if this mount is the primary external storage. 56* `removable`: true if this mount has removable media, such as a physical SD 57card. 58* `emulated`: true if this mount is emulated and is backed by internal storage, 59possibly using a FUSE daemon. 60* `mtp-reserve`: number of MB of storage that MTP should reserve for free 61storage. Only used when mount is marked as emulated. 62* `allowMassStorage`: true if this mount can be shared via USB mass storage. 63* `maxFileSize`: maximum file size in MB. 64 65Devices may provide external storage by emulating a case-insensitive, 66permissionless filesystem backed by internal storage. One possible 67implementation is provided by the FUSE daemon in `system/core/sdcard`, which can 68be added as a device-specific `init.rc` service: 69 70 # virtual sdcard daemon running as media_rw (1023) 71 service sdcard /system/bin/sdcard <source_path> <dest_path> 1023 1023 72 class late_start 73 74Where `source_path` is the backing internal storage and `dest_path` is the 75target mount point. 76 77When configuring a device-specific `init.rc` script, the `EXTERNAL_STORAGE` 78environment variable must be defined as the path to the primary external 79storage. The `/sdcard` path must also resolve to the same location, possibly 80through a symlink. If a device adjusts the location of external storage between 81platform updates, symlinks should be created so that old paths continue working. 82 83As an example, here’s the storage configuration for Xoom, which uses a FUSE 84daemon to provide primary external storage, and includes a physical SD card as 85secondary external storage: 86 87* [vold.fstab](https://android.googlesource.com/device/moto/wingray/+/master/vold.fstab) 88* [storage_list.xml](https://android.googlesource.com/device/moto/wingray/+/master/overlay/frameworks/base/core/res/res/xml/storage_list.xml) 89 90Access to external storage is protected by various Android permissions. 91Starting in Android 1.0, write access is protected with the 92`WRITE_EXTERNAL_STORAGE` permission, implemented using the `sdcard_rw` GID. 93Starting in Android 4.1, read access is protected with the new 94`READ_EXTERNAL_STORAGE` permission, implemented using the `sdcard_r` GID. To 95implement the read permission, a new top-level `/storage` directory was created 96such that processes must hold the `sdcard_r` GID to traverse into it. 97 98Since external storage offers no support for traditional POSIX filesystem 99permissions, system code should not store sensitive data on external storage. 100Specifically, configuration and log files should only be stored on internal 101storage where they can be effectively protected. 102 103## Multi-user external storage 104 105Starting in Android 4.2, devices can support multiple users, and external 106storage must meet the following constraints: 107 108* Each user must have their own isolated primary external storage, and must not 109have access to the primary external storage of other users. 110* The `/sdcard` path must resolve to the correct user-specific primary external 111storage based on the user a process is running as. 112* Storage for large OBB files in the `Android/obb` directory may be shared 113between multiple users as an optimization. 114* Secondary external storage must not be writable by apps. 115 116The default platform implementation of this feature leverages Linux kernel 117namespaces to create isolated mount tables for each Zygote-forked process, and 118then uses bind mounts to offer the correct user-specific primary external 119storage into that private namespace. 120 121At boot, the system mounts a single emulated external storage FUSE daemon at 122`EMULATED_STORAGE_SOURCE`, which is hidden from apps. After the Zygote forks, 123it bind mounts the appropriate user-specific subdirectory from under the FUSE 124daemon to `EMULATED_STORAGE_TARGET` so that external storage paths resolve 125correctly for the app. Because an app lacks accessible mount points for other 126users’ storage, they can only access storage for the user it was started as. 127 128This implementation also uses the shared subtree kernel feature to propagate 129mount events from the default root namespace into app namespaces, which ensures 130that features like ASEC containers and OBB mounting continue working correctly. 131It does this by mounting the rootfs as shared, and then remounting it as slave 132after each Zygote namespace is created. 133