Admisión del 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 el modo de inicio directo, puedes registrar los componentes de esta que deberían ejecutarse durante este modo. 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 apps de alarma;
  • apps que proporcionan notificaciones de usuario importantes, como las apps 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 encriptado por dispositivo. Este tipo de almacenamiento contiene datos encriptados con una clave que solo está disponible luego de que el dispositivo haya realizado un inicio verificado correctamente.

Para 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 haya desbloqueado correctamente el dispositivo y hasta que lo reinicie. 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 con el sistema para que estas puedan ejecutarse durante el modo de inicio directo o acceder al almacenamiento encriptado por dispositivo. Para registrar una app en el sistema, debes marcar los componentes como con reconocimiento de encriptación. Para marcar tu componente como “con reconocimiento de encriptación”, fija el atributo android:directBootAware en true 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 el dispositivo se haya reiniciado. En este momento, el almacenamiento encriptado por dispositivo está disponible y el componente puede ejecutar las tareas que se deben ejecutar durante el modo de inicio directo, como la activación de 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 de 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.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.

Acceso al almacenamiento encriptado por dispositivo

Para acceder al almacenamiento encriptado por dispositivo, crea una segunda instancia de Context llamando 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:

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 uses el almacenamiento encriptado por dispositivo como almacenamiento encriptado de propósito general. Para la información privada del usuario, o los datos encriptados que no sean necesarios durante el modo de inicio directo, usa el almacenamiento encriptado con credenciales.

Recepción de 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 un 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 desbloqueó el dispositivo, puedes detectarlo llamando a UserManager.isUserUnlocked().

Migración de datos existentes

Si un usuario actualiza el dispositivo para usar el modo de inicio directo, es posible que haya datos existentes que deban migrarse 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.

Usa tu mejor criterio cuando determines los datos que se migrarán entre estos dos tipos de almacenamiento. 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.

Prueba de tu app con reconocimiento de encriptación

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

Advertencia: Al habilitarse el inicio directo se borrarán todos los datos de usuario del dispositivo.

Para los dispositivos compatibles que tienen Android 7.0 instalado, habilita el inicio directo mediante una de las siguientes opciones:

  • En el dispositivo, habilita las Developer options si no lo haz hecho aún yendo a Settings > About phone y presionando Build number siete veces. Una vez que aparezca la pantalla de opciones para el desarrollador, dirígete a Settings > Developer options y selecciona Convert to file encryption.
  • 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, seleccionar “No thanks” si se 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.

Comprobación del 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 encriptación en todo el disco o 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 de 24.0 o superior, getStorageEncryptionStatus() mostrará ENCRYPTION_STATUS_ACTIVE si el dispositivo usa 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.