Ограниченное хранилище

Области хранения данных ограничивают доступ приложения к внешнему хранилищу. В Android 11 и более поздних версиях приложения, предназначенные для API уровня 30 или выше, должны использовать области хранения данных. В Android 10 приложения могли отказаться от использования областей хранения данных.

Ограничения доступа к приложениям

Цель ограниченного доступа к хранилищу – защитить конфиденциальность данных приложений и пользователей. Это включает защиту пользовательской информации (например, метаданных фотографий), предотвращение изменения или удаления пользовательских файлов приложениями без явного разрешения и защиту конфиденциальных пользовательских документов, скачанных в папку "Скачивания" или другие папки.

Приложения, использующие области хранения данных, могут иметь следующие уровни доступа (фактический доступ зависит от реализации):

  • Чтение и запись собственных файлов без разрешений.
  • Чтение медиафайлов других приложений с разрешением READ_EXTERNAL_STORAGE.
  • Запись в медиафайлы других приложений разрешена только с прямого согласия пользователя (исключения: системная галерея и приложения, имеющие право на доступ ко всем файлам).
  • Нет доступа для чтения или для записи к внешним каталогам данных приложений.

Использование областей хранения данных с FUSE

В Android 11 и более поздних версиях поддерживается файловая система в пространстве пользователя (FUSE), которая позволяет модулю MediaProvider проверять операции с файлами в пространстве пользователя и ограничивать доступ к файлам на основе правил разрешения, запрета или редактирования. Приложения в области хранения данных, использующие FUSE, получают функции конфиденциальности области хранения данных и возможность доступа к файлам по прямому пути (чтобы API файлов продолжали работать в приложениях).

В Android 10 правила ограниченного доступа к файлам применялись к файлам, к которым MediaProvider обращался через API, но не к файлам, к которым обращались напрямую (например, с помощью File API и NDK API), поскольку перехватывать вызовы ядра было слишком сложно. В результате приложения с ограниченным хранилищем не могли получить доступ к файлам, используя прямой путь к файлу. Это ограничение повлияло на возможность разработчиков приложений адаптировать свои приложения, поскольку им пришлось вносить значительные изменения в код, чтобы переписать доступ к File API на MediaProvider API.

FUSE и SDCardFS

Поддержка FUSE в Android 11 не связана с прекращением поддержки SDCardFS, но предоставляет альтернативу Media Store для устройств, которые ранее использовали SDCardFS. Устройства:

  • На устройствах с ОС Android 11 или более поздней версии и ядром 5.4 или более поздней версии нельзя использовать SDCardFS.
  • При переходе на Android 11 или более позднюю версию можно разместить FUSE поверх SDCardFS, чтобы перехватывать операции с файлами и соблюдать требования конфиденциальности.

Настройка производительности FUSE

Ранее Android поддерживал FUSE в Android 7 и более ранних версиях, в которых внешнее хранилище монтировалось как FUSE. Из-за проблем с производительностью и взаимоблокировкой в этой реализации FUSE в Android 8 была представлена SDCardFS. В Android 11 снова поддерживается FUSE с улучшенной и лучше протестированной реализацией libfuse, которую можно настроить для устранения проблем с производительностью, возникавших в Android 7 и более ранних версиях.

Настройка FUSE включает следующие изменения:

  • Обход FUSE для каталогов Android/data и Android/obb, чтобы повысить производительность мобильных игр, которые используют эти каталоги.
  • Оптимизация (например, настройка упреждающего чтения и коэффициентов загрязнения файловой системы FUSE) для поддержания производительности чтения и плавного воспроизведения медиафайлов.
  • Использование кеша обратной записи FUSE.
  • Кэширование разрешений для уменьшения количества межпроцессных взаимодействий с системным сервером.
  • Оптимизация для приложений с доступом ко всем файлам, позволяющая быстрее выполнять массовые операции.

Описанные выше настройки позволяют добиться сопоставимой производительности устройств с FUSE и без него. Например, при тестировании настроенного Pixel 2 с использованием FUSE и Pixel 2 с использованием Media Store была обнаружена сопоставимая производительность последовательного чтения (например, воспроизведения видео) при доступе к пути к файлу и Media Store. Однако последовательные операции записи с FUSE выполнялись немного медленнее, а случайные операции чтения и записи могли быть в два раза медленнее.

Показатели производительности могут различаться в зависимости от устройства и конкретного сценария использования. Поскольку API MediaProvider обеспечивают наиболее стабильную работу, разработчикам приложений, которые заботятся о производительности, следует использовать API MediaProvider.

Как уменьшить влияние FUSE на производительность

Влияние FUSE на производительность ограничивается только активными пользователями файлов, хранящихся на внешнем общем хранилище. Внешнее частное хранилище (включая каталоги android/data и android/obb) обходится FUSE, а внутреннее хранилище (например, /data/data, где многие приложения хранят данные, чтобы они были зашифрованы и защищены) не монтируется FUSE.

  • Приложения, которые редко используют общее внешнее хранилище, обычно взаимодействуют с ограниченным набором файлов (как правило, менее 100). Эти приложения используют существующие оптимизации для распространенных операций чтения и записи, поэтому в Android 11 не должны испытывать проблем с производительностью, связанных с FUSE.

  • Приложения, которые активно используют общее внешнее хранилище, обычно выполняют массовые операции с файлами, например перечисляют или удаляют каталог с 1000 файлов или создают или удаляют каталог с миллионом файлов в файловой системе. Массовые операции с файлами могут выполняться медленнее из-за FUSE в Android 11, но если такие приложения соответствуют требованиям для разрешения MANAGE_EXTERNAL_STORAGE, то они могут воспользоваться оптимизацией производительности, которая была добавлена в обновлении от октября 2020 года.

Чтобы избежать снижения производительности, приложения могут хранить данные во внешнем личном хранилище или использовать API для массовых операций в классе ContentProvider. Это позволяет обойти FUSE и оптимизировать производительность. Кроме того, в октябре 2020 года мы оптимизировали работу системного компонента MediaProvider для файловых менеджеров и других приложений, у которых есть разрешение MANAGE_EXTERNAL_STORAGE, например антивирусов и программ для резервного копирования и восстановления данных.

Конфиденциальность важнее производительности

На устройствах, настроенных для FUSE, большинство критически важных действий пользователей выполняются одинаково быстро как в Android 10, так и в Android 11. Однако при тестировании показателей производительности на наборе операций с файлами Android 11 может показать результаты хуже, чем Android 10. Если в Android 11 доступ к файлам выполняется медленнее (например, при случайном чтении или записи), рекомендуем использовать API MediaProvider, чтобы предоставить приложениям режим доступа без FUSE. Это самый эффективный и стабильный вариант.

Обновления MediaProvider и FUSE

Поведение системного компонента MediaProvider различается в разных версиях Android.

  • В Android 10 и более ранних версиях SDCardFS была файловой системой, а MediaProvider предоставлял интерфейс для коллекций файлов (например, изображений, видео, музыкальных файлов и т. д.). Когда приложение создавало файл с помощью File API, оно могло попросить MediaProvider просканировать файл и записать его в базу данных.

  • В Android 11 и более поздних версиях SDCardFS считается устаревшей, а MediaProvider становится обработчиком файловой системы (для FUSE) для внешнего хранилища, обеспечивая согласованность файловой системы во внешнем хранилище и базы данных MediaProvider. Как обработчик пользовательского пространства для файловой системы FUSE, MediaProvider может перехватывать вызовы ядра и обеспечивать конфиденциальность операций с файлами.

В Android 11 и более поздних версиях MediaProvider также является модульным системным компонентом (модулем Mainline), который можно обновлять отдельно от выпусков Android. Это означает, что проблемы с производительностью, конфиденциальностью или безопасностью, обнаруженные в MediaProvider, можно исправить и доставить по беспроводной сети из Google Play или с помощью других механизмов, предоставленных партнерами. Все, что входит в область действия обработчика FUSE, также можно обновлять, что позволяет исправлять регрессии производительности и ошибки FUSE.