Поддержка режима Direct Boot

В Android 7.0 предусмотрен безопасный режим прямой загрузки, который активируется, когда устройство включено, но не разблокировано. Для этого в системе предусмотрено два хранилища данных:

  • Хранилище с шифрованием учетных данных – хранилище по умолчанию, доступное только после разблокировки устройства.
  • Зашифрованное хранилище устройства. Доступно как в режиме прямой загрузки, так и после разблокировки устройства.

По умолчанию приложения не запускаются в режиме прямой загрузки. Если вашему приложению нужно выполнять действия в режиме Direct Boot, вы можете зарегистрировать компоненты приложения, которые будут запускаться в этом режиме. Вот несколько примеров приложений, которым может потребоваться работать в режиме прямой загрузки:

  • Приложения с запланированными уведомлениями, например будильники.
  • Приложения, которые отправляют пользователям важные уведомления, например приложения для обмена SMS.
  • Приложения, которые предоставляют специальные возможности, например TalkBack.

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

Для данных, которые должны быть зашифрованы с помощью ключа, связанного с учетными данными пользователя, например PIN-кодом или паролем, используйте хранилище, зашифрованное с помощью учетных данных. Хранилище с шифрованием учетных данных доступно после того, как пользователь разблокирует устройство, и до перезапуска устройства. Если пользователь включит блокировку экрана после разблокировки устройства, хранилище с шифрованием на основе учетных данных останется доступным.

Запрос на доступ к запуску в режиме прямого запуска

Чтобы компоненты приложения могли работать в режиме прямого запуска или получать доступ к зашифрованному хранилищу устройства, их необходимо зарегистрировать в системе. Приложения регистрируются в системе, помечая компоненты как поддерживающие шифрование. Чтобы отметить компонент как поддерживающий шифрование, задайте для атрибута android:directBootAware значение true в манифесте.

Компоненты, поддерживающие шифрование, могут зарегистрироваться для получения ACTION_LOCKED_BOOT_COMPLETED оповещения от системы после перезапуска устройства. В этот момент становится доступным зашифрованное хранилище устройства, и ваш компонент может выполнять задачи, которые должны выполняться в режиме прямой загрузки, например запускать запланированный будильник.

В следующем фрагменте кода показано, как зарегистрировать BroadcastReceiver с поддержкой шифрования и добавить фильтр интентов для ACTION_LOCKED_BOOT_COMPLETED в манифест приложения:

<receiver
  android:directBootAware="true" >
  ...
  <intent-filter>
    <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
  </intent-filter>
</receiver>

После разблокировки устройства все компоненты могут получить доступ к хранилищу с шифрованием устройства и хранилищу с шифрованием учетных данных.

Доступ к зашифрованному хранилищу устройства

Чтобы получить доступ к зашифрованному хранилищу устройства, создайте второй экземпляр Context, вызвав Context.createDeviceProtectedStorageContext(). Все вызовы Storage API, выполненные с использованием этого контекста, получают доступ к зашифрованному хранилищу устройства. В следующем примере показано, как получить доступ к зашифрованному хранилищу устройства и открыть существующий файл данных приложения:

Kotlin

val directBootContext: Context = appContext.createDeviceProtectedStorageContext()
// Access appDataFilename that lives in device encrypted storage
val inStream: InputStream = directBootContext.openFileInput(appDataFilename)
// Use inStream to read content...

Java

Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...

Используйте хранилище с шифрованием на уровне устройства только для информации, которая должна быть доступна в режиме Direct Boot. Не используйте зашифрованное хранилище устройства в качестве зашифрованного хранилища общего назначения. Для личной информации пользователей или зашифрованных данных, которые не нужны в режиме прямой загрузки, используйте хранилище, зашифрованное с помощью учетных данных.

Уведомления о разблокировке пользователем

Когда пользователь разблокирует устройство после перезапуска, приложение сможет получить доступ к хранилищу, зашифрованному с помощью учетных данных, и использовать обычные системные сервисы, зависящие от учетных данных пользователя.

Чтобы получать уведомления о том, что пользователь разблокировал устройство после перезагрузки, зарегистрируйте BroadcastReceiver из запущенного компонента. Когда пользователь разблокирует устройство после загрузки:

  • Если в вашем приложении есть активные процессы, которые требуют немедленного уведомления, настройте прослушивание сообщения ACTION_USER_UNLOCKED.
  • Если в вашем приложении используются только фоновые процессы, которые могут реагировать на уведомления с задержкой, отслеживайте сообщение ACTION_BOOT_COMPLETED.

Чтобы узнать, разблокировал ли пользователь устройство, вызовите метод UserManager.isUserUnlocked().

Перенос существующих данных

Если пользователь обновит устройство, чтобы использовать режим Direct Boot, вам может потребоваться перенести существующие данные в хранилище, зашифрованное на уровне устройства. Чтобы перенести настройки и данные базы данных между хранилищем, зашифрованным с помощью учетных данных, и хранилищем, зашифрованным на устройстве, используйте методы Context.moveSharedPreferencesFrom() и Context.moveDatabaseFrom(). При этом контекст назначения должен быть вызывающим методом, а исходный контекст – аргументом.

Не переносите личную информацию пользователей, например пароли или токены авторизации, из хранилища, зашифрованного с помощью учетных данных, в хранилище, зашифрованное с помощью устройства. Решение о том, какие ещё данные следует перенести в хранилище с шифрованием устройства, принимайте на свое усмотрение. В некоторых случаях вам может потребоваться управлять отдельными наборами данных в двух зашифрованных хранилищах.

Как протестировать приложение, поддерживающее шифрование

Протестируйте приложение, поддерживающее шифрование, с включенным режимом прямой загрузки.

На большинстве устройств с последними версиями Android режим Direct Boot включается, когда задан способ разблокировки экрана (PIN-код, графический ключ или пароль). В частности, это касается всех устройств, на которых используется шифрование на уровне файлов. Чтобы проверить, используется ли на устройстве шифрование на уровне файлов, выполните следующую команду оболочки:

adb shell getprop ro.crypto.type

Если выводится file, то на устройстве включено шифрование на уровне файлов.

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

  • На некоторых устройствах с полным шифрованием дисков (ro.crypto.type=block) и ОС Android 7.0–12 можно перейти на шифрование на уровне файлов. Сделать это можно двумя способами:

      Внимание! При переходе на шифрование на уровне файлов все пользовательские данные на устройстве будут удалены.

    • На устройстве включите Для разработчиков, если вы ещё этого не сделали. Для этого перейдите в Настройки > О телефоне и семь раз нажмите Номер сборки. Затем выберите Настройки > Для разработчиков и нажмите Перейти на шифрование файлов.
    • Вы также можете выполнить следующие команды оболочки:
      adb reboot-bootloader
      fastboot --wipe-and-use-fbe
      
  • Устройства с Android 13 или более ранней версией поддерживают эмулированный режим прямой загрузки, в котором разрешения файлов используются для имитации блокировки и разблокировки зашифрованных файлов. Используйте режим эмуляции только во время разработки, так как он может привести к потере данных. Чтобы включить эмуляцию режима Direct Boot, установите графический ключ на устройстве, выберите "Нет", если при установке графического ключа появится запрос на безопасный запуск, а затем выполните следующую команду оболочки:

    adb shell sm set-emulate-fbe true
    

    Чтобы отключить эмуляцию режима Direct Boot, выполните следующую команду:

    adb shell sm set-emulate-fbe false
    

    После выполнения любой из этих команд устройство перезагрузится.

Как проверить статус шифрования в правилах для устройств

Приложения для администрирования устройств могут использовать DevicePolicyManager.getStorageEncryptionStatus(), чтобы проверять текущий статус шифрования устройства.

Если целевой уровень API вашего приложения ниже Android 7.0 (API 24), метод getStorageEncryptionStatus() возвращает значение ENCRYPTION_STATUS_ACTIVE, когда на устройстве используется полное шифрование диска или шифрование на уровне файлов с режимом Direct Boot. В обоих случаях данные всегда хранятся в зашифрованном виде.

Если приложение предназначено для Android 7.0 (API 24) или более поздней версии, getStorageEncryptionStatus() возвращает ENCRYPTION_STATUS_ACTIVE, когда на устройстве используется полное шифрование дисков. Возвращает ENCRYPTION_STATUS_ACTIVE_PER_USER, если на устройстве используется шифрование на уровне файлов с режимом Direct Boot.

Если вы создаете приложение для администрирования устройств, предназначенное для Android 7.0, обязательно проверьте ENCRYPTION_STATUS_ACTIVE и ENCRYPTION_STATUS_ACTIVE_PER_USER, чтобы определить, зашифровано ли устройство.

Дополнительные примеры кода

Пример DirectBoot демонстрирует использование API, описанных на этой странице.