Adoptable Storage Architecture
Adoptable Storage (introduced in Android 6.0 Marshmallow) allows a user to format a removable storage device (like a microSD card or a USB drive) to act like internal storage. Once "adopted," the device becomes an encrypted, private volume that the system uses to store apps, app data, and media seamlessly.
Adoptable SD Card: Encrypted as Internal Storage
When a drive is adopted, it ceases to be a traditional "Public Volume" (typically formatted as FAT32/exFAT). Instead, Android treats it as an extension of the /data partition.
Key characteristics of adopted storage:
- Encryption: The disk is encrypted using a key randomly generated by Android. This key is stored on the device's internal memory. Consequently, the adopted SD card cannot be read if inserted into a PC or another Android phone.
- Filesystem: The drive is formatted with a Linux file system, usually EXT4 or F2FS, to support POSIX permissions, symlinks, and extended attributes required by Android apps.
Partition and Format Flow
The process of adopting a storage device is orchestrated by StorageManagerService and executed by vold.
- Partitioning: The framework sends a
partition()command tovold.volduses tools likesgdiskto rewrite the partition table of the SD card. It typically creates an Android metadata partition and a primary data partition. - Key Generation: A new encryption key is generated and stored in the internal
/data/misc/volddirectory. - Formatting:
voldformats the newly created partition withmkfs.ext4ormake_f2fs, applying the encryption parameters viafscrypt. - Mounting: The volume is mounted. The framework maps it into the user's view, often shifting the primary shared storage (
/sdcard) onto this new volume.
App and Data Migration
Once adopted, users can migrate their existing data to the new storage.
// Example: Requesting migration via StorageManager
StorageManager sm = context.getSystemService(StorageManager.class);
sm.setPrimaryStorageUuid(adoptedVolumeUuid, new IPackageMoveObserver.Stub() {
@Override
public void onCreated(int moveId, Bundle extras) {}
@Override
public void onStatusChanged(int moveId, int status, long estMillis) {
// Handle progress updates
}
});
When an app is installed, the PackageManagerService determines the best location for it based on the app's manifest flag android:installLocation. If an adopted volume is present and has space, the APK, optimized DEX, and app data directory (/data/user/0/com.example.app) can be physically placed on the SD card.
Practical Commands
You can simulate and manage adoptable storage using the sm (Storage Manager) command-line tool.
List available disks:
adb shell sm list-disks
Output example: disk:179,64
Force adoption of a disk: To format the entire disk as private/adoptable storage:
adb shell sm partition disk:179,64 private
Mixed partitioning: Format 50% as adoptable (private) and 50% as portable (public):
adb shell sm partition disk:179,64 mixed 50