Android has evolved over time to support a wide variety of storage device types and features. All versions of Android support devices with traditional storage, which includes portable and emulated storage. Portable storage can be provided by physical media, like an SD card or USB, that is for temporary data transfer/ file storage. The physical media may remain with the device for an extended period of time, but is not tied to the device and may be removed. SD cards have been available as portable storage since Android 1.0; Android 6.0 added USB support. Emulated storage is provided by exposing a portion of internal storage through an emulation layer and has been available since Android 3.0.
Starting in Android 6.0, Android supports adoptable storage, which is provided by physical media, like an SD card or USB, that is encrypted and formatted to behave like internal storage. Adoptable storage can store all types of application data.
Permissions
Access to external storage is protected by various Android permissions.
Starting in Android 1.0, write access is protected with the
WRITE_EXTERNAL_STORAGE
permission. Starting in Android 4.1, read
access is protected with the READ_EXTERNAL_STORAGE
permission.
Starting in Android 4.4, the owner, group and modes of files on external
storage devices are now synthesized based on directory structure. This enables
apps to manage their package-specific directories on external storage without
requiring they hold the broad WRITE_EXTERNAL_STORAGE
permission.
For example, the app with package name com.example.foo
can now
freely access Android/data/com.example.foo/
on external storage
devices with no permissions. These synthesized permissions are accomplished by
wrapping raw storage devices in a FUSE daemon.
Starting in Android 10, apps that target Android 9
and lower default to legacy storage, and can opt in to isolated storage.
Apps that target Android 10 and default to isolated
storage can temporarily opt out of it. Use the manifest attribute
requestLegacyExternalStorage
,
which controls the storage model, to change the default state.
Since both READ_EXTERNAL_STORAGE
and
WRITE_EXTERNAL_STORAGE
permissions are
soft-restricted, if the installer didn’t whitelist the app, the
permission controls access to the aural and visual collections
only, with no access to the SD card. This applies even if the app
requests legacy storage. For more information about both hard
restrictions and soft restrictions, see
Hard and soft restrictions in Android 10.
If the installer whitelisted the permission, an app running in legacy mode gets the nonisolated permission behavior. The permission controls SD card access, and the aural and visual collections. This happens when either the app targets Android 9 or lower and doesn’t opt in to isolated storage, or it targets Android 10 and opts out.
The whitelist state can be specified only at install time, and can't be changed until the app has been installed.
For more information on setting the READ_EXTERNAL_STORAGE
permission, see
setWhitelistedRestrictedPermissions()
in the
PackageInstaller.SessionParams class.
Android 13 introduces granular media permissions to support apps that
access media files created by other apps. Apps must request one or more of the granular
media permissions listed in
Granular media permissions instead of the READ_EXTERNAL_STORAGE
permission.
Android 14 builds on granular media permissions to allow users to grant partial access to their visual media library when apps request media permissions. See Grant partial access to photos and videos for more information.
Runtime permissions
Android 6.0 introduces a new
runtime permissions model where
apps request capabilities when needed at runtime. Because the new model
includes the READ/WRITE_EXTERNAL_STORAGE
permissions, the platform
needs to dynamically grant storage access without killing or restarting
already-running apps. It does this by maintaining three distinct views of all
mounted storage devices:
/mnt/runtime/default
is shown to apps with no special storage permissions, and to the root namespace whereadbd
and other system components live./mnt/runtime/read
is shown to apps withREAD_EXTERNAL_STORAGE
(SetLEGACY_STORAGE
for Android 10)/mnt/runtime/write
is shown to apps withWRITE_EXTERNAL_STORAGE
At Zygote fork time, we create a mount namespace for each running app and
bind mount the appropriate initial view into place. Later, when runtime
permissions are granted, vold
jumps into the mount namespace of
already-running apps and bind mounts the upgraded view into place. Note that
permission downgrades always result in the app being killed.
The setns()
functionality used to implement this feature
requires at least Linux 3.8, but patches have been backported successfully to
Linux 3.4. The PermissionsHostTest
CTS test can be used to verify
correct kernel behavior.