The Android Developer Challenge is back! Submit your idea before December 2.

Compatibilidade com o modo de inicialização direta

O Android 7.0 é executado em um modo seguro de inicialização direta quando o dispositivo é ligado, mas o usuário não o desbloqueia. Para isso, o sistema oferece dois locais de armazenamento para dados:

  • O armazenamento criptografado de credenciais, que é o local de armazenamento padrão e só é disponibilizado depois que o usuário desbloqueia o dispositivo.
  • O armazenamento criptografado do dispositivo, que é um local de armazenamento disponibilizado durante o modo de inicialização direta e depois que o usuário desbloqueia o dispositivo.

Por padrão, os apps não são executados durante o modo de inicialização direta. Se seu app precisa executar ações durante esse modo, você pode registrar os componentes que precisam ser executados. Alguns casos de uso comuns para apps que precisam ser executados no modo de inicialização direta incluem:

  • Apps com notificações programadas, como apps de despertador
  • Apps que fornecem notificações importantes ao usuário, como apps de SMS
  • Aplicativos que fornecem serviços de acessibilidade, como o Talkback

Se seu app precisa acessar dados durante o modo de inicialização direta, use o armazenamento criptografado do dispositivo. Esse tipo de armazenamento contém dados criptografados com uma chave que só é disponibilizada depois que o dispositivo realiza uma inicialização verificada.

Para dados que precisam ser criptografados com uma chave associada a credenciais do usuário, como um PIN ou uma senha, use o armazenamento criptografado de credenciais. Esse tipo de armazenamento só é disponibilizado depois que o usuário desbloqueia o dispositivo e até que ele reinicie o dispositivo. Se o usuário ativar a tela de bloqueio após desbloquear o dispositivo, isso não bloqueará o armazenamento criptografado de credenciais.

Solicitar acesso para executar durante a inicialização direta

Os apps precisam registrar os componentes deles no sistema antes de poderem ser executados no modo de inicialização direta ou acessar o armazenamento criptografado do dispositivo. Os apps são registrados no sistema marcando os componentes como tendo reconhecimento de criptografia. Para marcar seu componente como tendo reconhecimento de criptografia, defina o atributo android:directBootAware como "true" no manifesto.

Componentes com reconhecimento de criptografia podem se registrar para receber uma mensagem de transmissão ACTION_LOCKED_BOOT_COMPLETED do sistema quando o dispositivo é reiniciado. Nesse momento, o armazenamento criptografado do dispositivo é disponibilizado e pode executar tarefas necessárias durante o modo de inicialização direta, como o acionamento de um alarme programado.

O snippet de código a seguir é um exemplo de como registrar que um BroadcastReceiver reconhece criptografia e adicionar um filtro de intent para ACTION_LOCKED_BOOT_COMPLETED no manifesto do app:

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

Quando o usuário desbloquear o dispositivo, todos os componentes poderão acessar o armazenamento criptografado do dispositivo e também o armazenamento criptografado de credenciais.

Acessar o armazenamento criptografado do dispositivo

Para acessar o armazenamento criptografado do dispositivo, crie uma segunda instância de Context chamando Context.createDeviceProtectedStorageContext(). Todas as chamadas da API de armazenamento que usam esse contexto acessam o armazenamento criptografado do dispositivo. O exemplo a seguir acessa o armazenamento criptografado do dispositivo e abre um arquivo de dados existente do app:

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

Use o armazenamento criptografado do dispositivo apenas para informações que precisam estar acessíveis durante o modo de inicialização direta. Não use esse tipo de armazenamento como um repositório criptografado para fins gerais. Para informações particulares do usuário ou para dados criptografados que não são necessários durante o modo de inicialização direta, use o armazenamento criptografado de credenciais.

Receber notificações quando o usuário desbloquear

Quando o usuário desbloquear o dispositivo após a reinicialização, seu app poderá voltar a acessar o armazenamento criptografado de credenciais e usar serviços regulares do sistema que dependem das credenciais do usuário.

Para receber uma notificação quando o usuário desbloquear o dispositivo depois de uma reinicialização, registre um BroadcastReceiver a partir do componente em execução para ouvir mensagens de notificação de desbloqueio. Quando o usuário desbloqueia o dispositivo após a inicialização:

  • Se o app tiver processos em primeiro plano que precisem de notificação imediata, ouça a mensagem ACTION_USER_UNLOCKED.
  • Se o app usar somente processos em segundo plano que possam agir sobre uma notificação atrasada, ouça a mensagem ACTION_BOOT_COMPLETED.

Você poderá saber se o usuário desbloqueou o dispositivo chamando UserManager.isUserUnlocked().

Migrar dados existentes

Se o usuário atualizar o dispositivo para usar o modo de inicialização direta, você poderá ter dados que precisem ser migrados para o armazenamento criptografado do dispositivo. Use Context.moveSharedPreferencesFrom() e Context.moveDatabaseFrom() para migrar dados de preferências e do banco de dados entre o armazenamento criptografado de credenciais e o armazenamento criptografado do dispositivo.

Tenha bom senso ao decidir quais dados migrar do armazenamento criptografado de credenciais para o armazenamento criptografado do dispositivo. Não migre informações particulares do usuário, como senhas ou tokens de autorização, para o armazenamento criptografado do dispositivo. Em alguns casos, pode ser necessário gerenciar conjuntos separados de dados nos dois repositórios criptografados.

Testar o app com reconhecimento de criptografia

Teste seu app com reconhecimento de criptografia com o modo de inicialização direta ativado. Existem duas maneiras de ativar a inicialização direta.

Atenção: ao ativar a inicialização direta, você exclui permanentemente todos os dados do usuário no dispositivo.

Em dispositivos compatíveis com o Android 7.0 instalado, ative a inicialização direta seguindo um destes procedimentos:

  • No dispositivo, ative as Opções do desenvolvedor acessando Config. > Sobre o telefone e tocando em Número da versão sete vezes. Quando a tela de opções do desenvolvedor for disponibilizada, acesse Configurações > Opções do desenvolvedor e selecione Converter para criptografia de arquivos.
  • Use os seguintes comandos de shell adb para ativar o modo de inicialização direta:
        $ adb reboot-bootloader
        $ fastboot --wipe-and-use-fbe
        

Um modo de inicialização direta emulado também está disponível, caso você precise trocar de modo nos dispositivos de teste. É preciso usar o modo emulado somente durante o desenvolvimento, porque ele pode causar perda de dados. Para ativar o modo de inicialização direta emulado, defina um padrão de bloqueio no dispositivo. Caso seja solicitada uma tela de inicialização segura ao definir esse padrão, escolha "No thanks" e, em seguida, use o seguinte comando de shell adb:

    $ adb shell sm set-emulate-fbe true
    

Para desativar o modo de inicialização direta emulado, use o seguinte comando:

    $ adb shell sm set-emulate-fbe false
    

O uso desses comandos faz com que o dispositivo seja reinicializado.

Verificar o status de criptografia da política do dispositivo

Apps de administração de dispositivos podem usar DevicePolicyManager.getStorageEncryptionStatus() para verificar o status atual de criptografia do dispositivo. Se seu app for direcionado a um nível de API anterior ao 24.0 (Android 7.0), getStorageEncryptionStatus() retornará ENCRYPTION_STATUS_ACTIVE se o dispositivo estiver usando a criptografia de disco completo ou a criptografia baseada em arquivo com inicialização direta. Em ambos os casos, os dados são sempre armazenados criptografados em repouso. Se seu app for direcionado a um nível de API igual ou posterior ao 24.0, getStorageEncryptionStatus() retornará ENCRYPTION_STATUS_ACTIVE se o dispositivo estiver usando a criptografia de disco completo. Ele retornará ENCRYPTION_STATUS_ACTIVE_PER_USER se o dispositivo estiver usando a criptografia baseada em arquivo com a inicialização direta.

Se você criar um app de administração de dispositivos direcionado ao Android 7.0, verifique a presença de ENCRYPTION_STATUS_ACTIVE e ENCRYPTION_STATUS_ACTIVE_PER_USER para determinar se o dispositivo é criptografado.

Outros exemplos de código

O exemplo da Inicialização direta do Android (em inglês) demonstra com mais detalhes o uso das APIs abordadas nesta página.