Clay Murphy | f9d451e | 2014-10-21 18:11:12 -0700 | [diff] [blame] | 1 | page.title=External Storage |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 2 | @jd:body |
| 3 | |
| 4 | <!-- |
Heidi von Markham | 1e7b8b7 | 2015-03-09 10:13:48 -0700 | [diff] [blame] | 5 | Copyright 2015 The Android Open Source Project |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 6 | |
| 7 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 8 | you may not use this file except in compliance with the License. |
| 9 | You may obtain a copy of the License at |
| 10 | |
| 11 | http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | |
| 13 | Unless required by applicable law or agreed to in writing, software |
| 14 | distributed under the License is distributed on an "AS IS" BASIS, |
| 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 16 | See the License for the specific language governing permissions and |
| 17 | limitations under the License. |
| 18 | --> |
Clay Murphy | 1d5f8fe | 2015-05-18 16:44:07 -0700 | [diff] [blame] | 19 | <div id="qv-wrapper"> |
| 20 | <div id="qv"> |
| 21 | <h2>In this document</h2> |
| 22 | <ol id="auto-toc"> |
| 23 | </ol> |
| 24 | </div> |
| 25 | </div> |
Ken Sumrall | 93c0b9c | 2013-04-16 15:43:27 -0700 | [diff] [blame] | 26 | |
Heidi von Markham | b493fb6 | 2015-03-25 12:35:11 -0700 | [diff] [blame] | 27 | <img style="float: right; margin: 0px 15px 15px 15px;" src="images/ape_fwk_hal_extstor.png" alt="Android external storage HAL icon"/> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 28 | |
| 29 | <p>Android supports devices with external storage, which is defined to be a |
| 30 | case-insensitive filesystem with immutable POSIX permission classes and |
| 31 | modes. External storage can be provided by physical media (such as an SD |
| 32 | card), or by exposing a portion of internal storage through an emulation |
| 33 | layer. Devices may contain multiple instances of external storage.</p> |
| 34 | |
| 35 | <p>Access to external storage is protected by various Android |
| 36 | permissions. Starting in Android 1.0, write access is protected with the |
| 37 | <code>WRITE_EXTERNAL_STORAGE</code> permission. Starting in Android 4.1, |
| 38 | read access is protected with the <code>READ_EXTERNAL_STORAGE</code> |
| 39 | permission.</p> |
| 40 | |
| 41 | <p>Starting in Android 4.4, the owner, group and modes of files on external |
| 42 | storage devices are now synthesized based on directory structure. This |
| 43 | enables apps to manage their package-specific directories on external |
| 44 | storage without requiring they hold the broad |
| 45 | <code>WRITE_EXTERNAL_STORAGE</code> permission. For example, the app with |
| 46 | package name <code>com.example.foo</code> can now freely access |
| 47 | <code>Android/data/com.example.foo/</code> on external storage devices with |
| 48 | no permissions. These synthesized permissions are accomplished by wrapping |
| 49 | raw storage devices in a FUSE daemon.</p> |
| 50 | |
| 51 | <p>Since external storage offers minimal protection for stored data, system |
| 52 | code should not store sensitive data on external storage. Specifically, |
| 53 | configuration and log files should only be stored on internal storage where |
| 54 | they can be effectively protected.</p> |
| 55 | |
| 56 | |
| 57 | <h2 id="multiple-external-storage-devices">Multiple external storage devices</h2> |
| 58 | |
| 59 | <p>Starting in Android 4.4, multiple external storage devices are surfaced |
| 60 | to developers through <code>Context.getExternalFilesDirs()</code>, |
| 61 | <code>Context.getExternalCacheDirs()</code>, and |
| 62 | <code>Context.getObbDirs()</code>.</p> |
| 63 | |
| 64 | </p>External storage devices surfaced through these APIs must be a |
| 65 | semi-permanent part of the device (such as an SD card slot in a battery |
| 66 | compartment). Developers expect data stored in these locations to be |
| 67 | available over long periods of time. For this reason, transient storage |
| 68 | devices (such as USB mass storage drives) should not be surfaced through |
| 69 | these APIs.</p> |
| 70 | |
| 71 | <p>The <code>WRITE_EXTERNAL_STORAGE</code> permission must only grant write |
| 72 | access to the primary external storage on a device. Apps must not be |
| 73 | allowed to write to secondary external storage devices, except in their |
| 74 | package-specific directories as allowed by synthesized |
| 75 | permissions. Restricting writes in this way ensures the system can clean |
| 76 | up files when applications are uninstalled.</p> |
| 77 | |
| 78 | |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 79 | <h2 id="multi-user-external-storage">Multi-user external storage</h2> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 80 | |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 81 | <p>Starting in Android 4.2, devices can support multiple users, and external |
| 82 | storage must meet the following constraints:</p> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 83 | |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 84 | <ul> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 85 | <li>Each user must have their own isolated primary external storage, and |
| 86 | must not have access to the primary external storage of other users.</li> |
| 87 | <li>The <code>/sdcard</code> path must resolve to the correct user-specific |
| 88 | primary external storage based on the user a process is running as.</li> |
| 89 | <li>Storage for large OBB files in the <code>Android/obb</code> directory |
| 90 | may be shared between multiple users as an optimization.</li> |
| 91 | <li>Secondary external storage must not be writable by apps, except in |
| 92 | package-specific directories as allowed by synthesized permissions.</li> |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 93 | </ul> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 94 | |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 95 | <p>The default platform implementation of this feature leverages Linux kernel |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 96 | namespaces to create isolated mount tables for each Zygote-forked process, |
| 97 | and then uses bind mounts to offer the correct user-specific primary external |
Robert Ly | 35f2fda | 2013-01-29 16:27:05 -0800 | [diff] [blame] | 98 | storage into that private namespace.</p> |
Jeff Sharkey | 790c02d | 2013-10-18 13:57:33 -0700 | [diff] [blame] | 99 | |
| 100 | <p>At boot, the system mounts a single emulated external storage FUSE daemon |
| 101 | at <code>EMULATED_STORAGE_SOURCE</code>, which is hidden from apps. After |
| 102 | the Zygote forks, it bind mounts the appropriate user-specific subdirectory |
| 103 | from under the FUSE daemon to <code>EMULATED_STORAGE_TARGET</code> so that |
| 104 | external storage paths resolve correctly for the app. Because an app lacks |
| 105 | accessible mount points for other users' storage, they can only access |
| 106 | storage for the user it was started as.</p> |
| 107 | |
| 108 | <p>This implementation also uses the shared subtree kernel feature to |
| 109 | propagate mount events from the default root namespace into app namespaces, |
| 110 | which ensures that features like ASEC containers and OBB mounting continue |
| 111 | working correctly. It does this by mounting the rootfs as shared, and then |
| 112 | remounting it as slave after each Zygote namespace is created.</p> |