Motivo de inicio canónico

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

Motivos de inicio

Un cargador de arranque usa recursos de hardware y memoria disponibles de forma exclusiva 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 inicio. Luego, init traduce esta línea de comandos para propagarla a la propiedad de Android bootloader_boot_reason_prop (ro.boot.bootreason). En los dispositivos que se lanzan con Android 12 o versiones posteriores, y que usan la versión del kernel 5.10 o posterior, androidboot.bootreason=<reason> se agrega a bootconfig en lugar de a la línea de comandos del kernel.

Especificaciones del motivo de inicio

Las versiones anteriores de Android especificaban un formato de motivo de inicio que no usaba espacios, era todo en minúsculas, incluía pocos requisitos (como para informar kernel_panic, watchdog, cold/warm/hard) y que permitía otros motivos únicos. Esta especificación poco precisa provocó la proliferación de cientos de cadenas de motivos de arranque personalizadas (y, a veces, sin sentido), lo que, a su vez, generó una situación inmanejable. En la versión actual de Android, el gran impulso del contenido casi no analizable o sin sentido que registra el bootloader generó problemas de cumplimiento para bootloader_boot_reason_prop.

Con el lanzamiento de Android 9, el equipo de Android reconoce que el bootloader_boot_reason_prop heredado tiene un impulso considerable y no se puede volver a escribir 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 los ajustes al sistema existente. Para ello, el equipo de Android hace lo siguiente:

  • Interactuar con los desarrolladores del bootloader para alentarlos a hacer lo siguiente:
    • Proporciona motivos canónicos, analizables y reconocibles para bootloader_boot_reason_prop.
    • Participa en la lista de system/core/bootstat/bootstat.cpp kBootReasonMap.
  • Agrega una fuente controlada y reescribible en el tiempo de ejecución de system_boot_reason_prop (sys.boot.reason). Un conjunto limitado de apps del sistema (como bootstat y init) pueden reescribir esta propiedad, pero se pueden otorgar derechos de sepolicy a todas las apps para leerla.
  • Informa a los usuarios sobre el motivo de inicio para que esperen hasta que se monte userdata antes de confiar en el contenido de la propiedad del motivo de inicio del sistema system_boot_reason_prop.

¿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 porque representa información imprecisa, no analizable y no canónica. En la mayoría de los casos, solo los desarrolladores con un conocimiento profundo del sistema de arranque deberían necesitar acceder a esta información. Una API refinada, analizable y canónica para el motivo de inicio con system_boot_reason_prop se puede detectar de forma confiable y precisa solo después de que se haya activado el montaje de los datos del usuario. Más precisamente:

  • Antes de que se carguen los datos del usuario, system_boot_reason_prop contendrá el valor de bootloader_boot_reason_prop.
  • Después de que se cargan los datos del usuario, system_boot_reason_prop se puede actualizar para cumplir con los requisitos o para informar información más precisa.

Por este motivo, Android 9 extiende el período antes de que se pueda adquirir oficialmente el motivo de inicio, y lo cambia de ser preciso de inmediato en el inicio (con bootloader_boot_reason_prop) a estar disponible solo después de que se haya activado userdata (con system_boot_reason_prop).

La lógica de Bootstat 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 controladas de reinicio y apagado, 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 para bootloader_boot_reason_prop en Android 9 usa la siguiente sintaxis:

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

Reglas de formato:

  • Minúscula
  • Sin espacios en blanco (usa un guion bajo)
  • Todos los caracteres imprimibles
  • reason, subreason y una o más instancias de 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 subreason opcional que representa un breve resumen de por qué el dispositivo tuvo que reiniciarse o apagarse (o quién lo reinició o apagó).
    • Uno o más valores de 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, por lo general, deben seguir una jerarquía de importancia. Sin embargo, también es aceptable informar varios valores de detail de igual importancia.

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

Requisitos del motivo

El valor proporcionado para reason (primer intervalo, antes de la finalización o la coma) debe ser uno de los siguientes conjuntos divididos en motivos principales, secundarios y terciarios:

  • kernel set:
    • "watchdog"
    • "kernel_panic"
  • conjunto fuerte:
    • "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 el hardware restableció su estado y que ramoops debe conservar el contenido persistente.
    • "warm": Por lo general, indica que la memoria y los dispositivos conservan algún estado, y que el almacén de respaldo de ramoops (consulta el controlador pstore en el kernel) contiene contenido persistente.
    • "shutdown"
    • "reboot". Por lo general, significa que se desconoce el estado de ramoops y el estado del hardware. Este valor es un comodín, ya que los valores cold, hard y warm proporcionan pistas sobre la profundidad del restablecimiento del dispositivo.

Los bootloaders deben proporcionar un conjunto de kernel o un conjunto de kernel sin procesar reason, y se recomienda que proporcionen un subreason si se puede determinar. Por ejemplo, una presión prolongada de la tecla de encendido que puede tener o no una copia de seguridad de ramoops tendría el motivo de inicio "reboot,longkey".

Ningún primer tramo reason puede formar parte de ningún subreason ni detail. Sin embargo, como el espacio del usuario no puede generar motivos de configuración del kernel, "watchdog" se puede reutilizar después de un motivo de configuración general, 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 especializados para descifrarlos ni ser legibles por humanos con un informe intuitivo. Ejemplos: "shutdown,vbxd" (mala), "shutdown,uv" (mejor), "shutdown,undervoltage" (preferida).

Combinaciones de motivo y submotivo

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

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

Para obtener más detalles, 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.

Informa los motivos de arranque

Todos los motivos de inicio, ya sea del 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 es una combinación de motivos de incumplimiento heredados y de cumplimiento. Los desarrolladores del cargador de arranque solo deben registrar aquí los motivos nuevos que cumplan con los requisitos (y no deben registrar los motivos que no cumplan con los requisitos, a menos que el producto ya se haya enviado y no se pueda cambiar).

Te recomendamos que uses entradas existentes y que cumplan con los requisitos en system/core/bootstat/bootstat.cpp y que te moderes antes de usar una cadena que no cumpla con los requisitos. Como guía, se recomienda lo siguiente:

  • OK para informar "kernel_panic" desde el cargador de arranque, ya que bootstat puede inspeccionar ramoops para kernel_panic signatures y, así, refinar los motivos secundarios en el system_boot_reason_prop canónico.
  • No está bien informar una cadena que no cumple con los requisitos en kBootReasonMap (como "panic") del cargador de arranque, ya que, en última instancia, esto impedirá refinar el reason.

Por ejemplo, si kBootReasonMap contiene "wdog_bark", un desarrollador de cargador de arranque debería hacer lo siguiente:

  • Cambia a "watchdog,bark" y agrégalo a la lista en kBootReasonMap.
  • Considera qué significa "bark" para quienes no conocen la tecnología y determina si hay un subreason más significativo disponible.

Verifica el cumplimiento del motivo de inicio

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

Por lo tanto, el cumplimiento del bootloader requiere que los desarrolladores de bootloaders se adhieran voluntariamente al espíritu de las reglas y los lineamientos descritos anteriormente. Instamos a los desarrolladores a que contribuyan al AOSP (específicamente a system/core/bootstat/bootstat.cpp) y utilicen esta oportunidad como foro para debatir sobre los problemas relacionados con el motivo de inicio.