| <html devsite> |
| <head> |
| <title>Adoptable Storage</title> |
| <meta name="project_path" value="/_project.yaml" /> |
| <meta name="book_path" value="/_book.yaml" /> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| |
| |
| |
| <p>Android has always supported external storage accessories (such as SD cards), but |
| these accessories were historically limited to simple file storage, due to |
| their expected impermanence and the minimal data protection offered to |
| <a href="/devices/storage/traditional">traditional external storage</a>. |
| Android 6.0 introduced the ability to |
| <a href="http://developer.android.com/about/versions/marshmallow/android-6.0.html#adoptable-storage" |
| class="external">adopt</a> external storage media to act like internal |
| storage.</p> |
| |
| <aside class="caution"> |
| <p><strong>Caution</strong>: On devices running Android 7.0-8.1, |
| <a href="/security/encryption/file-based">file-based encryption</a> |
| (FBE) can't be used together with adoptable storage. On devices |
| using FBE, new storage media (such as an SD card) must be used as |
| <a href="/devices/storage/traditional">traditional storage</a>.</p> |
| <p>Devices running Android 9 and higher can use adoptable storage and FBE.</p> |
| </aside> |
| |
| <p>When external storage media is adopted, it’s formatted and encrypted to only |
| work with a single Android device at a time. Because the media is strongly tied |
| to the Android device that adopted it, it can safely store both apps and |
| private data for all users.</p> |
| |
| <p>When users insert new storage media (such as an SD card) in an adoptable |
| location, Android asks them how they want to use the media. They can choose to |
| adopt the media, which formats and encrypts it, or they can continue using it |
| as-is for simple file storage. If they choose to adopt, the platform offers to |
| migrate the primary shared storage contents (typically mounted at |
| <code>/sdcard</code>) to the newly adopted media, freeing up valuable space on |
| internal storage. Unlike traditional storage, which is limited to 2TB due to its |
| use of |
| <a href="https://en.wikipedia.org/wiki/Master_boot_record" class="external">MBR</a>, |
| adoptable storage uses |
| <a href="https://en.wikipedia.org/wiki/GUID_Partition_Table" class="external">GPT</a> |
| and therefore has file storage limit of ~9ZB.</p> |
| |
| <p>Apps can be placed on adopted storage media only when the developer has |
| indicated support through the <code>android:installLocation</code> attribute. |
| New installs of supported apps are automatically placed on the |
| storage device with the most free space, and users can move supported apps |
| between storage devices in the <em>Settings</em> app. Apps moved to adopted |
| media are remembered while the media is ejected, |
| and return when the media is reinserted.</p> |
| |
| <h2 id="security">Security</h2> |
| |
| |
| <p>The platform randomly generates an encryption key for each adopted device, |
| and that key is stored on the internal storage of the Android device. This |
| effectively makes the adopted media as secure as internal storage. Keys are |
| associated with adopted devices based on the adopted partition GUID. The |
| adopted device is encrypted using <code>dm-crypt</code> configured with the |
| <code>aes-cbc-essiv:sha256</code> algorithm |
| and a 128-bit key size. |
| </p> |
| <p>The on-disk layout of the adopted device closely mirrors the internal data |
| partition, including SELinux labels, etc. When multi-user is supported on the |
| Android device, the adopted storage device also supports multi-user with the |
| same level of isolation as internal storage.</p> |
| |
| <p>Because the contents of an adopted storage device are strongly tied to the |
| Android device that adopted it, the encryption keys should not be extractable |
| from the parent device, and therefore the storage device can't be mounted |
| elsewhere.</p> |
| |
| <p> |
| The default encryption algorithm for contents mode is <code>aes-256-xts</code> |
| and for filenames is <code>aes-256-heh</code>. You can change these by changing |
| the values of the properties <code>ro.crypto.volume.contents_mode</code> and |
| <code>ro.crypto.volume.filenames_mode</code> respectively, by setting |
| <code>PRODUCT_PROPERTY_OVERRIDES</code> in <code>device.mk</code>. |
| </p> |
| <p> |
| If your kernel does not support HEH filename encryption, you can use CTS mode |
| instead by adding the following to device.mk: |
| </p> |
| |
| |
| <pre |
| class="prettyprint">PRODUCT_PROPERTY_OVERRIDES += \ |
| ro.crypto.volume.filenames_mode=aes-256-cts</pre> |
| |
| <h2 id="performance_and_stability">Performance and stability</h2> |
| |
| |
| <p>Only external storage media in stable locations, such as a slot inside a |
| battery compartment or behind a protective cover, should be considered for |
| adoption to help avoid accidental data loss or corruption. In particular, USB |
| devices connected to a phone or tablet should never be considered for adoption. |
| One common exception would be an external USB drive connected to a TV-style |
| device, because the entire TV is typically installed in a stable location.</p> |
| |
| <p>When a user adopts a new storage device, the platform runs a benchmark and |
| compares its performance against internal storage. If the adopted device is |
| significantly slower than internal storage, the platform warns the user about a |
| possibly degraded experience. This benchmark was derived from the actual I/O |
| behavior of popular Android apps. Currently, the AOSP implementation will only |
| warn users beyond a single threshold, but device manufacturers may adapt this |
| further, such as rejecting adoption completely if the card is extremely slow.</p> |
| |
| <p>Adopted devices must be formatted with a filesystem that supports POSIX |
| permissions and extended attributes, such as <code>ext4</code> or |
| <code>f2fs</code>. For optimal performance, the <code>f2fs</code> filesystem is |
| recommended for flash-based storage devices.</p> |
| |
| <p>When performing periodic idle maintenance, the platform issues |
| <code>FI_TRIM</code> to adopted media just like it does for internal storage. |
| The current SD card specification does not support the <code>DISCARD</code> |
| command; but the kernel instead falls back to the <code>ERASE</code> command, |
| which SD card firmware may choose to use for optimization purposes.</p> |
| |
| <h3 id="fixing-double-encryption">Fixing double encryption</h3> |
| |
| <p>In Android 8.x and lower, adoptable storage didn't work with FBE. All |
| existing devices that have adoptable storage used |
| <a href="/security/encryption/full-disk">full-disk encryption</a> (FDE). |
| In Android 9, adoptable storage works with FBE. However, by |
| default, file contents are double-encrypted because adoptable storage has an |
| FDE and FBE layer. By default, both layers encrypt file contents, which can |
| slow device performance. To fix the problem of double encryption and speed up |
| device performance: |
| </p> |
| <ol> |
| <li>Add <a href="https://android-review.googlesource.com/q/REQ_NOENCRYPT" |
| class="external">these patches</a> to your kernel.</li> |
| <li>To communicate this change with <code>vold</code>, add the following to |
| <code>device.mk</code>: |
| <pre class="prettyprint">PRODUCT_PROPERTY_OVERRIDES += ro.crypto.allow_encrypt_override=true</pre></li> |
| </ol> |
| <p> |
| If you set this, but the kernel patches aren't present, adoptable storage won't |
| work, and the <code>vold</code> logs will contain an error that it was unable |
| to create the dm device. |
| </p> |
| <aside class="caution"> |
| <strong>Caution:</strong> Don't change this flag with an OTA update because |
| it changes the on-disk format of adoptable storage. |
| </aside> |
| |
| <h2 id="testing">Testing</h2> |
| <p> |
| To test that adoptable storage is working, run this CTS test: |
| </p> |
| |
| |
| <pre |
| class="devsite-terminal devsite-click-to-copy">cts-tradefed run commandAndExit cts-dev \ |
| -m CtsAppSecurityHostTestCases \ |
| -t android.appsecurity.cts.AdoptableHostTest</pre> |
| <p> |
| To verify behavior of USB drives and SD cards when a device doesn't have a |
| built-in slot or when the USB connector is being used for an active adb |
| connection, use: |
| </p> |
| <pre class="prettyprint"> |
| adb shell sm set-virtual-disk true |
| </pre> |
| |
| </body> |
| </html> |