Register now for Android Dev Summit 2019!

Compatibilidad con el modo de inicio directo

Android 7.0 se ejecuta en un modo de inicio directo seguro cuando el dispositivo se enciende y el usuario no lo ha desbloqueado. A fin de permitir esto, el sistema brinda dos ubicaciones de almacenamiento para los datos:

  • Almacenamiento encriptado por credenciales, que es la ubicación de almacenamiento predeterminada y solo está disponible después de que el usuario desbloquea el dispositivo.
  • Almacenamiento encriptado por dispositivo, que es una ubicación de almacenamiento disponible tanto durante el modo de inicio directo como después de que el usuario desbloquea el dispositivo.

De forma predeterminada, las apps no se ejecutan durante el modo de inicio directo. Si necesitas que tu app se ejecute durante ese modo, registra los componentes que deberían hacerlo. Entre algunos de los casos comunes de apps que necesitan ejecutarse durante el modo de inicio directo se incluyen los siguientes:

  • Apps que tienen notificaciones programadas, como las de alarma
  • Apps que proporcionan notificaciones de usuario importantes, como las de mensajes SMS
  • Apps que brindan servicios de accesibilidad, como TalkBack

Si necesitas que tu app acceda a datos mientras se ejecuta el modo de inicio directo, usa el almacenamiento que encripta dispositivo. Este tipo de almacenamiento contiene datos protegidos con una clave que solo está disponible luego de que el dispositivo realiza un inicio verificado.

En el caso de los datos que se deben encriptar mediante una clave asociada con las credenciales del usuario, como un PIN o una contraseña, usa el almacenamiento encriptado con credenciales. El almacenamiento encriptado con credenciales solo está disponible después de que el usuario desbloquea correctamente el dispositivo y hasta que lo reinicia. Si el usuario habilita la pantalla de bloqueo luego de desbloquear el dispositivo, esto no bloquea el almacenamiento encriptado por credenciales.

Solicitud de acceso para ejecutar durante el inicio directo

Debes registrar los componentes de las apps en el sistema para que estas puedan ejecutarse durante el modo de inicio directo o acceder al almacenamiento encriptado por el dispositivo. Para registrar una app en el sistema, debes marcar los componentes como con reconocimiento de encriptación. Para ello, configura el atributo android:directBootAware como verdadero en el manifiesto.

Los componentes con reconocimiento de encriptación pueden registrarse para recibir un mensaje de transmisión ACTION_LOCKED_BOOT_COMPLETED del sistema cuando se reinicia el dispositivo. En este punto, ya está disponible el almacenamiento encriptado por dispositivo, y el componente puede realizar tareas que se deben ejecutar durante el modo de inicio directo, como activar una alarma programada.

El siguiente fragmento de código es un ejemplo de cómo registrar un BroadcastReceiver como "con reconocimiento de encriptación" y cómo agregar un filtro de intent para ACTION_LOCKED_BOOT_COMPLETED en el manifiesto de la app:

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

Una vez que el usuario haya desbloqueado el dispositivo, todos los componentes podrán acceder tanto al almacenamiento encriptado por dispositivo como al almacenamiento encriptado por credenciales.

Cómo acceder al almacenamiento encriptado por dispositivo

Para acceder al almacenamiento encriptado por dispositivo, crea una segunda instancia de Context invocando a Context.createDeviceProtectedStorageContext(). Todas las llamadas de API de almacenamiento realizadas usando este contexto acceden al almacenamiento encriptado por dispositivo. En el siguiente ejemplo, se accede al almacenamiento encriptado por dispositivo y se abre un archivo de datos de la app existente:

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

Usa el almacenamiento encriptado por dispositivo solo para información a la que se deba poder acceder durante el modo de inicio directo. No lo uses como almacenamiento de propósito general. En el caso de la información privada del usuario o de los datos encriptados que no sean necesarios durante el modo de inicio directo, usa el almacenamiento encriptado con credenciales.

Cómo recibir notificaciones sobre el desbloqueo del usuario

Una vez que el usuario desbloquee el dispositivo después del reinicio, tu app podrá aplicar un cambio al acceso al almacenamiento encriptado por credenciales y usar los servicios comunes del sistema que dependen de credenciales de usuario.

Para recibir una notificación cuando el usuario desbloquee el dispositivo luego de reiniciarlo, registra el elemento BroadcastReceiver de un componente en ejecución para detectar mensajes de notificación de desbloqueo. Cuando el usuario desbloquee el dispositivo después del reinicio:

  • Si en tu app hay procesos en primer plano que requieren notificación inmediata, busca el mensaje ACTION_USER_UNLOCKED.
  • Si tu app solo usa procesos en segundo plano que pueden influir en una notificación demorada, busca el mensaje ACTION_BOOT_COMPLETED.

Si el usuario desbloquea el dispositivo, puedes detectarlo invocando a UserManager.isUserUnlocked().

Cómo migrar datos existentes

Si un usuario actualiza el dispositivo para usar el modo de inicio directo, es posible que haya datos existentes que se deban migrar al almacenamiento encriptado por dispositivo. Usa Context.moveSharedPreferencesFrom() y Context.moveDatabaseFrom() para migrar datos de preferencia y de base de datos del almacenamiento encriptado por credenciales al almacenamiento encriptado por dispositivo.

Debes tener cuidado cuando decidas qué datos migrar entre estos dos tipos de almacenamiento encriptado. No debes migrar información privada del usuario, como contraseñas o tokens de autorización, al almacenamiento encriptado por el dispositivo. En algunos casos, es posible que debas gestionar conjuntos separados de datos en ambos tipos de almacenamiento encriptado.

Cómo probar tu app con reconocimiento de encriptación

Prueba tu app con el reconocimiento de encriptación en el modo de inicio directo habilitado. Hay dos maneras de habilitar el inicio directo.

Precaución: Si habilitas el inicio directo, se borrarán todos los datos de usuario del dispositivo.

En el caso de los dispositivos compatibles que ejecutan Android 7.0, habilita el inicio directo mediante una de las siguientes opciones:

  • En el dispositivo, habilita Opciones para desarrolladores (si no lo has hecho aún) yendo a Configuración > Acerca del teléfono y presionando Número de compilación siete veces. Una vez que aparezca la pantalla de opciones para el desarrollador, dirígete a Configuración > Opciones para desarrolladores y selecciona Convertir a encriptación de archivo.
  • Usa los siguientes comandos shell adb para habilitar el modo de inicio directo:
        $ adb reboot-bootloader
        $ fastboot --wipe-and-use-fbe
        

También está disponible un modo de inicio directo emulado en caso de que debas cambiar de modo en tus dispositivos de prueba. El modo emulado solo debería usarse durante el desarrollo, y puede provocar la pérdida de datos. Para habilitar el modo de inicio directo emulado, debes establecer un patrón de bloqueo en el dispositivo, elegir "No, gracias" si te pregunta si deseas un inicio seguro al configurar un patrón de bloqueo y, luego, usar el siguiente comando shell adb:

    $ adb shell sm set-emulate-fbe true
    

Para desactivar el modo de inicio directo emulado, usa el siguiente comando:

    $ adb shell sm set-emulate-fbe false
    

El uso de estos comandos provoca el reinicio del dispositivo.

Cómo comprobar el estado de encriptación de la política de dispositivo

Las apps de administración de dispositivos pueden usar DevicePolicyManager.getStorageEncryptionStatus() para comprobar el estado de encriptación actual del dispositivo. Si tu app está dirigida a un nivel de API inferior a 24.0 (Android 7.0), getStorageEncryptionStatus() mostrará ENCRYPTION_STATUS_ACTIVE si el dispositivo está usando la encriptación en todo el disco o la encriptación basada en archivos con inicio directo. En ambos casos, los datos se almacenan siempre encriptados de forma estática. Si tu app está dirigida a un nivel de API 24.0 o superior, getStorageEncryptionStatus() mostrará ENCRYPTION_STATUS_ACTIVE si el dispositivo usa la encriptación en todo el disco. Mostrará ENCRYPTION_STATUS_ACTIVE_PER_USER si el dispositivo usa encriptación basada en archivos con inicio directo.

Si compilas una app de administración de dispositivos dirigida a Android 7.0, asegúrate de buscar ENCRYPTION_STATUS_ACTIVE y ENCRYPTION_STATUS_ACTIVE_PER_USER para determinar si el dispositivo está encriptado.

Códigos de ejemplo adicionales

El ejemplo de inicio directo de Android también muestra cómo usar las API que se indican en esta página.