Obsługa trybu bezpośredniego rozruchu

Android 7.0 działa w bezpiecznym trybie Direct Boot, gdy urządzenie jest włączone, ale użytkownik go nie odblokował. Aby to umożliwić, system udostępnia 2 lokalizacje przechowywania danych:

  • Zaszyfrowany magazyn danych logowania, który jest domyślnym miejscem przechowywania danych i jest dostępny tylko po odblokowaniu urządzenia przez użytkownika.
  • Zaszyfrowana pamięć urządzenia, która jest dostępna zarówno w trybie bezpośredniego uruchamiania, jak i po odblokowaniu urządzenia przez użytkownika.

Domyślnie aplikacje nie działają w trybie bezpośredniego uruchamiania. Jeśli aplikacja musi wykonać działanie w trybie bezpośredniego uruchamiania, możesz zarejestrować komponenty aplikacji, które mają być uruchamiane w tym trybie. Oto kilka typowych przypadków użycia aplikacji, które muszą działać w trybie bezpośredniego uruchamiania:

  • aplikacje, które mają zaplanowane powiadomienia, np. budziki;
  • aplikacje, które wysyłają użytkownikom ważne powiadomienia, np. aplikacje do SMS-ów;
  • aplikacje, które udostępniają usługi ułatwień dostępu, takie jak TalkBack;

Jeśli aplikacja musi mieć dostęp do danych podczas działania w trybie bezpośredniego uruchamiania, użyj pamięci masowej zaszyfrowanej na urządzeniu. Zaszyfrowana pamięć urządzenia zawiera dane zaszyfrowane kluczem, który jest dostępny tylko po pomyślnym przeprowadzeniu weryfikacji podczas uruchamiania.

W przypadku danych, które muszą być zaszyfrowane kluczem powiązanym z danymi logowania użytkownika, np. kodem PIN lub hasłem, użyj pamięci zaszyfrowanej danymi logowania. Pamięć zaszyfrowana przy użyciu danych logowania jest dostępna po odblokowaniu urządzenia przez użytkownika i pozostaje dostępna do momentu ponownego uruchomienia urządzenia. Jeśli po odblokowaniu urządzenia użytkownik włączy ekran blokady, pamięć zaszyfrowana przy użyciu danych logowania pozostanie dostępna.

Prośba o dostęp do uruchamiania podczas bezpośredniego uruchamiania

Aplikacje muszą zarejestrować swoje komponenty w systemie, zanim będą mogły działać w trybie bezpośredniego uruchamiania lub uzyskać dostęp do zaszyfrowanej pamięci urządzenia. Aplikacje rejestrują się w systemie, oznaczając komponenty jako obsługujące szyfrowanie. Aby oznaczyć komponent jako obsługujący szyfrowanie, ustaw atrybut android:directBootAware na wartość „true” w pliku manifestu.

Komponenty obsługujące szyfrowanie mogą zarejestrować się, aby otrzymywać komunikat ACTION_LOCKED_BOOT_COMPLETED z systemu po ponownym uruchomieniu urządzenia. W tym momencie pamięć urządzenia zaszyfrowana na poziomie urządzenia jest dostępna, a komponent może wykonywać zadania, które muszą być uruchamiane w trybie bezpośredniego uruchamiania, takie jak wyzwalanie zaplanowanego alarmu.

Ten fragment kodu pokazuje, jak zarejestrować BroadcastReceiver jako komponent uwzględniający szyfrowanie i dodać filtr intencji dla ACTION_LOCKED_BOOT_COMPLETED w pliku manifestu aplikacji:

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

Gdy użytkownik odblokuje urządzenie, wszystkie komponenty będą miały dostęp zarówno do pamięci zaszyfrowanej na urządzeniu, jak i do pamięci zaszyfrowanej przy użyciu danych logowania.

Dostęp do zaszyfrowanej pamięci urządzenia

Aby uzyskać dostęp do zaszyfrowanej pamięci urządzenia, utwórz drugą instancję Context, wywołując Context.createDeviceProtectedStorageContext(). Wszystkie wywołania interfejsu Storage API wykonywane przy użyciu tego kontekstu uzyskują dostęp do zaszyfrowanej pamięci urządzenia. W tym przykładzie uzyskujemy dostęp do zaszyfrowanej pamięci urządzenia i otwieramy istniejący plik danych aplikacji:

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...

Używaj pamięci masowej zaszyfrowanej na urządzeniu tylko do przechowywania informacji, które muszą być dostępne w trybie bezpośredniego uruchamiania. Nie używaj pamięci masowej zaszyfrowanej na urządzeniu jako zaszyfrowanego magazynu do zwykłych obciążeń. W przypadku prywatnych informacji o użytkowniku lub zaszyfrowanych danych, które nie są potrzebne w trybie bezpośredniego uruchamiania, użyj pamięci masowej zaszyfrowanej przy użyciu danych logowania.

Otrzymuj powiadomienia o odblokowaniu przez użytkownika

Gdy użytkownik odblokuje urządzenie po ponownym uruchomieniu, aplikacja może przełączyć się na dostęp do pamięci zaszyfrowanej przy użyciu danych logowania i korzystać ze zwykłych usług systemowych, które wymagają danych logowania użytkownika.

Aby otrzymywać powiadomienia, gdy użytkownik odblokuje urządzenie po ponownym uruchomieniu, zarejestruj BroadcastReceiver z uruchomionego komponentu, który będzie nasłuchiwać wiadomości z powiadomieniami o odblokowaniu. Gdy użytkownik odblokuje urządzenie po uruchomieniu:

  • Jeśli aplikacja ma procesy na pierwszym planie, które wymagają natychmiastowego powiadomienia, nasłuchuj wiadomości ACTION_USER_UNLOCKED.
  • Jeśli aplikacja używa tylko procesów w tle, które mogą reagować na opóźnione powiadomienia, nasłuchuj wiadomości ACTION_BOOT_COMPLETED.

Jeśli użytkownik odblokował urządzenie, możesz się o tym dowiedzieć, wywołując metodę UserManager.isUserUnlocked().

Migracja istniejących danych

Jeśli użytkownik zaktualizuje urządzenie, aby korzystać z trybu bezpośredniego uruchamiania, może być konieczne przeniesienie istniejących danych do pamięci masowej zaszyfrowanej na urządzeniu. Aby przenieść ustawienia i dane bazy danych między pamięcią zaszyfrowaną przy użyciu danych logowania a pamięcią zaszyfrowaną na urządzeniu, użyj metod Context.moveSharedPreferencesFrom() i Context.moveDatabaseFrom(), gdzie kontekst docelowy jest obiektem wywołującym metodę, a kontekst źródłowy jest argumentem.

Nie przenoś prywatnych informacji użytkownika, takich jak hasła czy tokeny autoryzacji, z pamięci zaszyfrowanej przy użyciu danych logowania do pamięci zaszyfrowanej na urządzeniu. Decydując o tym, jakie inne dane przenieść do zaszyfrowanej pamięci urządzenia, kieruj się zdrowym rozsądkiem. W niektórych przypadkach może być konieczne zarządzanie oddzielnymi zbiorami danych w 2 zaszyfrowanych magazynach.

Testowanie aplikacji uwzględniającej szyfrowanie

Przetestuj aplikację obsługującą szyfrowanie z włączonym trybem bezpośredniego uruchamiania.

Większość urządzeń z najnowszymi wersjami Androida włącza tryb bezpośredniego uruchamiania, gdy ustawione są dane logowania na ekranie blokady (kod PIN, wzór lub hasło). Dotyczy to wszystkich urządzeń, które korzystają z szyfrowania opartego na plikach. Aby sprawdzić, czy urządzenie korzysta z szyfrowania opartego na plikach, uruchom to polecenie powłoki:

adb shell getprop ro.crypto.type

Jeśli dane wyjściowe to file, na urządzeniu jest włączone szyfrowanie oparte na plikach.

Na urządzeniach, które domyślnie nie używają szyfrowania opartego na plikach, mogą być dostępne inne opcje testowania trybu bezpośredniego uruchamiania:

  • Niektóre urządzenia, które korzystają z pełnego szyfrowania dysku (ro.crypto.type=block) i mają Androida w wersji od 7.0 do 12, można przekonwertować na szyfrowanie oparte na plikach. Można to zrobić na dwa sposoby:

      Ostrzeżenie: obie metody konwersji na szyfrowanie oparte na plikach powodują usunięcie wszystkich danych użytkownika z urządzenia.

    • Jeśli nie masz jeszcze włączonych Opcji programisty, włącz je na urządzeniu, wybierając Ustawienia > Informacje o telefonie i klikając 7 razy Numer kompilacji. Następnie otwórz Ustawienia > Opcje programisty i wybierz Konwertuj na szyfrowanie plików.
    • Możesz też uruchomić te polecenia powłoki:
      adb reboot-bootloader
      fastboot --wipe-and-use-fbe
      
  • Urządzenia z Androidem 13 lub starszym obsługują „emulowany” tryb bezpośredniego uruchamiania, który wykorzystuje uprawnienia do plików, aby symulować efekty blokowania i odblokowywania zaszyfrowanych plików. Trybu emulacji używaj tylko podczas programowania, ponieważ może on spowodować utratę danych. Aby włączyć emulowany tryb Direct Boot, ustaw wzór blokady na urządzeniu, wybierz „Nie, dziękuję”, gdy pojawi się prośba o bezpieczny ekran startowy podczas ustawiania wzoru blokady, a następnie uruchom to polecenie powłoki:

    adb shell sm set-emulate-fbe true
    

    Aby wyłączyć emulowany tryb Direct Boot, uruchom to polecenie powłoki:

    adb shell sm set-emulate-fbe false
    

    Uruchomienie dowolnego z tych poleceń spowoduje ponowne uruchomienie urządzenia.

Sprawdzanie stanu szyfrowania zasad dotyczących urządzeń

Aplikacje do administrowania urządzeniem mogą używać metody DevicePolicyManager.getStorageEncryptionStatus(), aby sprawdzić bieżący stan szyfrowania urządzenia.

Jeśli Twoja aplikacja jest kierowana na interfejs API na poziomie niższym niż Android 7.0 (API 24), getStorageEncryptionStatus() zwraca ENCRYPTION_STATUS_ACTIVE, gdy urządzenie korzysta z pełnego szyfrowania dysku lub szyfrowania opartego na plikach z funkcją Direct Boot. W obu przypadkach dane są zawsze przechowywane w postaci zaszyfrowanej w spoczynku.

Jeśli aplikacja jest kierowana na Androida 7.0 (API 24) lub nowszego, getStorageEncryptionStatus() zwraca ENCRYPTION_STATUS_ACTIVE, gdy urządzenie korzysta z pełnego szyfrowania dysku. Zwraca wartość ENCRYPTION_STATUS_ACTIVE_PER_USER, jeśli urządzenie korzysta z szyfrowania opartego na plikach z bezpośrednim uruchamianiem.

Jeśli tworzysz aplikację do administrowania urządzeniem, która jest przeznaczona na Androida 7.0, sprawdź zarówno ENCRYPTION_STATUS_ACTIVE, jak i ENCRYPTION_STATUS_ACTIVE_PER_USER, aby określić, czy urządzenie jest zaszyfrowane.

Dodatkowe przykłady kodu

Przykładowa aplikacja DirectBoot pokazuje, jak korzystać z interfejsów API opisanych na tej stronie.