Motivo del inicio canónico

Android 9 incluye los siguientes cambios en la especificación del motivo de inicio del bootloader.

Motivos de inicio

Un bootloader usa hardware y recursos de memoria disponibles de manera única para determinar por qué se reinició un dispositivo y, luego, comunica esa determinación agregando androidboot.bootreason=<reason> a la línea de comandos del kernel de Android para su lanzamiento. Luego, init traduce esta línea de comandos para propagarse a la propiedad bootloader_boot_reason_prop (ro.boot.bootreason) de Android. En el caso de los dispositivos que se lanzan con Android 12 o versiones posteriores, que usan la versión de kernel 5.10 o una versión posterior, androidboot.bootreason=<reason> se agrega a bootconfig en lugar de a la línea de comandos del kernel.

Especificaciones del motivo de inicio

En las versiones anteriores de Android, se especificaba un formato de motivo de inicio que no usaba espacios, estaba en minúsculas, incluía pocos requisitos (como los informes kernel_panic, watchdog, cold/warm/hard) y permitía otros motivos únicos. Esta especificación flexible dio como resultado la proliferación de cientos de strings de motivos de inicio personalizadas (y, a veces, sin sentido) lo que, a su vez, condujo a una situación inmanejable. A partir de la versión actual de Android, el ímpetu del contenido casi no analizable o sin sentido que archiva el bootloader creó problemas de cumplimiento para bootloader_boot_reason_prop.

Con la versión de Android 9, el equipo de Android reconoce que la bootloader_boot_reason_prop heredada tiene un impulso considerable y no se puede reescribir durante el tiempo de ejecución. Por lo tanto, cualquier mejora en la especificación del motivo de inicio debe provenir de las interacciones con los desarrolladores del bootloader y de los ajustes en el sistema existente. Con ese fin, el equipo de Android sigue estos pasos:

  • Interacción con los desarrolladores de bootloader para alentarlos a hacer lo siguiente:
    • Proporciona motivos canónicos, analizables y reconocibles para bootloader_boot_reason_prop.
    • Participar en la lista de kBootReasonMap de system/core/bootstat/bootstat.cpp.
  • Se agrega una fuente controlada y reescritura de entorno de ejecución de system_boot_reason_prop (sys.boot.reason). Un conjunto limitado de apps del sistema (como bootstat y init) puede reescribir esta propiedad, pero todas las apps pueden tener derechos de sepolicy para leerla.
  • Informar a los usuarios el motivo de inicio que deben esperar hasta después de que se activen los datos del usuario antes de confiar en el contenido de la propiedad system_boot_reason_prop del motivo de inicio del sistema

¿Por qué tan tarde? Si bien bootloader_boot_reason_prop está disponible al principio del inicio, la política de seguridad de Android lo bloquea según sea necesario, ya que representa información imprecisa, no analizable y no canónica. En la mayoría de las situaciones, solo los desarrolladores con un conocimiento profundo del sistema de arranque necesitan acceder a esta información. Una API perfeccionada, analizable y canónica por motivo de inicio con system_boot_reason_prop puede recopilarse de manera confiable y precisa solo después de que se activan los datos de usuario. Más precisamente:

  • Antes de que se activen los datos de usuario, system_boot_reason_prop contendrá el valor de bootloader_boot_reason_prop.
  • Después de que se activen los datos del usuario, es posible que se actualice system_boot_reason_prop para que cumpla con los requisitos o informe con información más precisa.

Por esta razón, Android 9 extiende el período antes de que se pueda adquirir oficialmente el motivo de inicio y cambia de ser preciso de inmediato en el inicio (con bootloader_boot_reason_prop) a estar disponible solo después de que se activan los datos de usuario (con system_boot_reason_prop).

La lógica de arranque depende de un bootloader_boot_reason_prop más informativo y compatible. Cuando esa propiedad usa un formato predecible, mejora la precisión de todas las situaciones de reinicio y apagado controlados, lo que, a su vez, refina y expande la precisión y el significado de system_boot_reason_prop.

Formato del motivo de inicio canónico

El formato del motivo de inicio canónico de bootloader_boot_reason_prop en Android 9 usa la siguiente sintaxis:

<reason>,<subreason>,<detail>…

Reglas de formato:

  • Minúscula
  • Sin espacios en blanco (usar subrayado)
  • Todos los caracteres imprimibles
  • Instancias de reason, subreason y una o más detail separadas por comas.
    • Es un reason obligatorio que representa el motivo de mayor prioridad por el que el dispositivo tuvo que reiniciarse o apagarse.
    • Un objeto subreason opcional que representa un breve resumen de por qué se tuvo que reiniciar o apagar el dispositivo (o quién reinició o apagó el dispositivo).
    • Uno o más valores detail opcionales. Un detail puede apuntar a un subsistema para ayudar a determinar qué sistema específico generó el subreason. Puedes especificar varios valores de detail, que, en general, deberían seguir una jerarquía de importancia. Sin embargo, también es aceptable informar varios valores detail de igual importancia.

Un valor vacío para bootloader_boot_reason_prop se considera ilegal (ya que esto permite que otros agentes inserten un motivo de inicio después del hecho).

Requisitos del motivo

El valor asignado para reason (primer intervalo, antes de la finalización o la coma) debe ser del siguiente conjunto dividido en motivos de kernel, fuertes y contundentes:

  • conjunto de kernels:
    • "watchdog"
    • "kernel_panic"
  • conjunto sólido:
    • "recovery"
    • "bootloader"
  • blunt set:
    • "cold". Por lo general, indica un restablecimiento completo de todos los dispositivos, incluida la memoria.
    • "hard": Por lo general, indica que se restableció el estado del hardware y que ramoops debe retener el contenido persistente.
    • "warm". Por lo general, indica que la memoria y los dispositivos conservan cierto estado, y el almacén de copias de seguridad de ramoops (consulta el controlador pstore en el kernel) incluye contenido persistente.
    • "shutdown"
    • "reboot": Por lo general, significa que el estado ramoops es desconocido y el estado del hardware. Este valor es genérico, ya que los valores cold, hard y warm proporcionan pistas sobre la profundidad del restablecimiento del dispositivo.

Los bootloaders deben proporcionar un conjunto de kernels o un conjunto blunt reason, y se recomienda que proporcionen un subreason si se puede determinar. Por ejemplo, si mantienes presionada la tecla de encendido y no tiene una copia de seguridad de ramoops, el motivo de inicio es "reboot,longkey".

Ningún reason del primer intervalo puede ser parte de cualquier subreason o detail. Sin embargo, debido a que el espacio del usuario no puede producir los motivos del conjunto de kernel, es posible que "watchdog" se reutilice después de un motivo de conjunto de kernel, junto con un detalle de la fuente (por ejemplo, "reboot,watchdog,service_manager_unresponsive" o "reboot,software,watchdog").

Los motivos de inicio no deben requerir conocimientos internos expertos para descifrarlos ni deben ser legibles por humanos con un informe intuitivo. Ejemplos: "shutdown,vbxd" (malo), "shutdown,uv" (mejor), "shutdown,undervoltage" (opción preferida).

Combinaciones de motivo y submotivo

Android reserva un conjunto de combinaciones reason-subreason que no deben sobrecargarse durante el uso normal, pero que se pueden usar caso por caso si la combinación refleja con exactitud la condición asociada. Estos son algunos ejemplos de combinaciones reservadas:

  • "reboot,userrequested"
  • "shutdown,userrequested"
  • "shutdown,thermal" (desde thermald)
  • "shutdown,battery"
  • "shutdown,battery,thermal" (desde BatteryStatsService)
  • "reboot,adb"
  • "reboot,shell"
  • "reboot,bootloader"
  • "reboot,recovery"

Para obtener más información, consulta kBootReasonMap en system/core/bootstat/bootstat.cpp y el historial de registro de cambios de Git asociado en el repositorio de código fuente de Android.

Informar motivos de inicio

Todos los motivos de inicio, ya sea desde el bootloader o registrados en el motivo de inicio canónico, deben registrarse en la sección kBootReasonMap de system/core/bootstat/bootstat.cpp. La lista kBootReasonMap combina los motivos de cumplimiento y los motivos heredados de incumplimiento. Los desarrolladores del bootloader solo deben registrar aquí nuevos motivos de cumplimiento (y no deben registrar los de incumplimiento, a menos que el producto ya se haya enviado y no se pueda cambiar).

Te recomendamos usar entradas existentes que cumplan con los requisitos en system/core/bootstat/bootstat.cpp y tener restricciones antes de usar una cadena que no cumpla con las políticas. A modo de lineamiento, debes cumplir con los siguientes requisitos:

  • OK para informar "kernel_panic" desde el bootloader, ya que bootstat puede inspeccionar ramoops en busca de kernel_panic signatures para definir mejor los submotivos en la system_boot_reason_prop canónica.
  • No es correcto informar una cadena que no cumple con las políticas en kBootReasonMap (como "panic") del bootloader, ya que, en última instancia, esto interrumpirá la capacidad de definir mejor el reason).

Por ejemplo, si kBootReasonMap contiene "wdog_bark", un desarrollador de bootloader debe hacer lo siguiente:

  • Cambia a "watchdog,bark" y agrégalo a la lista en kBootReasonMap.
  • Considera qué significa "bark" para los usuarios que no estén familiarizados con la tecnología y determina si hay disponible una subreason más significativa.

Verifica el cumplimiento del motivo de inicio

En este momento, Android no proporciona una prueba activa de CTS que pueda activar o inspeccionar con precisión todos los motivos de inicio posibles que podría proporcionar un bootloader; los socios aún pueden intentar ejecutar una prueba pasiva para determinar la compatibilidad.

Como resultado, el cumplimiento del bootloader requiere que los desarrolladores de bootloader cumplan voluntariamente con el espíritu de las reglas y los lineamientos descritos anteriormente. Instamos a estos desarrolladores a que contribuyan al AOSP (específicamente a system/core/bootstat/bootstat.cpp) y a que usen esta oportunidad como foro para debatir sobre problemas con el motivo de inicio.