Adoptable Storage

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 traditional external storage. Android 6.0 introduced the ability to adopt external storage media to act like internal storage.

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.

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 /sdcard) 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 MBR, adoptable storage uses GPT and therefore has file storage limit of ~9ZB.

Apps can be placed on adopted storage media only when the developer has indicated support through the android:installLocation 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 Settings app. Apps moved to adopted media are remembered while the media is ejected, and return when the media is reinserted.


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 dm-crypt configured with the aes-cbc-essiv:sha256 algorithm and a 128-bit key size.

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.

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.

The default encryption algorithm for contents mode is aes-256-xts and for filenames is aes-256-heh. You can change these by changing the values of the properties ro.crypto.volume.contents_mode and ro.crypto.volume.filenames_mode respectively, by setting PRODUCT_PROPERTY_OVERRIDES in

If your kernel does not support HEH filename encryption, you can use CTS mode instead by adding the following to


Performance and stability

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.

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.

Adopted devices must be formatted with a filesystem that supports POSIX permissions and extended attributes, such as ext4 or f2fs. For optimal performance, the f2fs filesystem is recommended for flash-based storage devices.

When performing periodic idle maintenance, the platform issues FI_TRIM to adopted media just like it does for internal storage. The current SD card specification does not support the DISCARD command; but the kernel instead falls back to the ERASE command, which SD card firmware may choose to use for optimization purposes.

Fixing double encryption

In Android 8.x and lower, adoptable storage didn't work with FBE. All existing devices that have adoptable storage used full-disk encryption (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:

  1. Add these patches to your kernel.
  2. To communicate this change with vold, add the following to
    PRODUCT_PROPERTY_OVERRIDES += ro.crypto.allow_encrypt_override=true

If you set this, but the kernel patches aren't present, adoptable storage won't work, and the vold logs will contain an error that it was unable to create the dm device.


To test that adoptable storage is working, run this CTS test:

cts-tradefed run commandAndExit cts-dev \
    -m CtsAppSecurityHostTestCases \
    -t android.appsecurity.cts.AdoptableHostTest

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:

adb shell sm set-virtual-disk true