O Android 9 inclui as seguintes alterações na especificação do motivo de inicialização do bootloader.
Razões de inicialização
Um bootloader usa recursos de hardware e memória disponíveis exclusivamente para determinar por que um dispositivo foi reinicializado e, em seguida, comunica essa determinação adicionando androidboot.bootreason=<reason>
à linha de comando do kernel do Android para sua inicialização. init
então traduz esta linha de comando para propagar para a propriedade bootloader_boot_reason_prop
do Android ( ro.boot.bootreason
). Para dispositivos iniciados com Android 12 ou posterior, usando o kernel versão 5.10 ou superior, androidboot.bootreason=<reason>
é adicionado ao bootconfig em vez da linha de comando do kernel.
Especificações do motivo da inicialização
As versões anteriores do Android especificavam um formato de motivo de inicialização que não usava espaços, era todo em letras minúsculas, incluía poucos requisitos (como para relatar kernel_panic
, watchdog
, cold
/ warm
/ hard
) e que fazia concessões para outros motivos exclusivos. Essa especificação frouxa resultou na proliferação de centenas de cadeias de caracteres de motivo de inicialização personalizadas (e às vezes sem sentido), o que, por sua vez, levou a uma situação incontrolável. A partir da versão atual do Android, o grande impulso de conteúdo quase impossível de analisar ou sem sentido arquivado pelo bootloader criou problemas de conformidade para bootloader_boot_reason_prop
.
Com o lançamento do Android 9, a equipe do Android reconhece que o legado bootloader_boot_reason_prop
tem um impulso substancial e não pode ser reescrito em tempo de execução. Quaisquer melhorias na especificação do motivo da inicialização devem, portanto, vir de interações com desenvolvedores do bootloader e ajustes no sistema existente. Para esse fim, a equipe do Android é:
- Envolver-se com desenvolvedores de bootloader para incentivá-los a:
- Forneça razões canônicas, analisáveis e reconhecíveis para
bootloader_boot_reason_prop
. - Participe da lista
system/core/bootstat/bootstat.cpp
kBootReasonMap
.
- Forneça razões canônicas, analisáveis e reconhecíveis para
- Adicionando uma fonte controlada e regravável em tempo de execução do
system_boot_reason_prop
(sys.boot.reason
). Um conjunto limitado de aplicativos do sistema (comobootstat
einit
) pode reescrever essa propriedade, mas todos os aplicativos podem receber direitos de sepolicy para lê-la. - Informar aos usuários o motivo da inicialização para aguardar até que o userdata seja montado antes de confiar no conteúdo da propriedade do motivo da inicialização do sistema
system_boot_reason_prop
.
Por que tão tarde? Embora bootloader_boot_reason_prop
esteja disponível no início da inicialização, ele é bloqueado pela política de segurança do Android conforme a necessidade porque representa informações imprecisas, não analisáveis e não canônicas. Na maioria das situações, apenas desenvolvedores com profundo conhecimento do sistema de inicialização precisarão acessar essas informações. Uma API refinada, analisável e canônica para motivo de inicialização via system_boot_reason_prop
pode ser obtida de maneira confiável e precisa somente após a montagem dos dados do usuário. Especificamente:
- Antes da montagem do userdata,
system_boot_reason_prop
conterá o valor debootloader_boot_reason_prop
. - Após a montagem do userdata,
system_boot_reason_prop
pode ser atualizado para ser compatível ou para relatar informações mais precisas.
Por esse motivo, o Android 9 estende o período de tempo antes que o motivo da inicialização possa ser adquirido oficialmente, alterando-o de ser imediatamente preciso na inicialização (com bootloader_boot_reason_prop
) para estar disponível somente após a montagem do userdata (com system_boot_reason_prop
).
A lógica do Bootstat depende de um bootloader_boot_reason_prop
mais informativo e compatível. Quando essa propriedade usa um formato previsível, ela melhora a precisão de todos os cenários controlados de reinicialização e desligamento, o que, por sua vez, refina e expande a precisão e o significado de system_boot_reason_prop
.
Formato de motivo de inicialização canônico
O formato de motivo de inicialização canônico para bootloader_boot_reason_prop
no Android 9 usa a seguinte sintaxe:
<reason>,<subreason>,<detail>…
Regras de formatação:
- Minúsculas
- Sem espaços em branco (use sublinhado)
- Todos os caracteres imprimíveis
-
reason
separado por vírgula,subreason
e um ou maisdetail
(s).- Um
reason
obrigatório que representa o motivo de maior prioridade pelo qual o dispositivo teve que ser reinicializado ou desligado. - Um
subreason
opcional que representa um breve resumo do motivo pelo qual o dispositivo teve que ser reinicializado ou desligado (ou quem reinicializou ou desligou o dispositivo). - Um ou mais valores
detail
opcionais. Umdetail
pode apontar para um subsistema para ajudar a determinar qual sistema específico resultou nasubreason
. Você pode especificar vários valoresdetail
, que geralmente devem seguir uma hierarquia de importância. No entanto, também é aceitável reportar vários valoresdetail
de igual importância.
- Um
Um valor vazio para bootloader_boot_reason_prop
é considerado ilegal (pois permite que outros agentes injetem um motivo de inicialização após o fato).
Requisitos de motivo
O valor fornecido para reason
(primeiro intervalo, antes da terminação ou vírgula) deve ser do seguinte conjunto dividido em motivos centrais, fortes e contundentes:
- conjunto de kernel:
- "
watchdog"
-
"kernel_panic"
- "
- conjunto forte:
-
"recovery"
-
"bootloader"
-
- conjunto contundente:
-
"cold"
. Geralmente indica uma reinicialização completa de todos os dispositivos, incluindo a memória. -
"hard"
. Geralmente indica que o hardware teve seu estado redefinido eramoops
deve reter conteúdo persistente. -
"warm"
. Geralmente indica que a memória e os dispositivos retêm algum estado, e o armazenamento de suporteramoops
(consulte o driverpstore
no kernel) contém conteúdo persistente. -
"shutdown"
-
"reboot"
. Geralmente significa que o estadoramoops
é desconhecido e o estado do hardware é desconhecido. Este valor é genérico, pois os valorescold
,hard
ewarm
fornecem pistas sobre a profundidade da redefinição do dispositivo.
-
Os carregadores de inicialização devem fornecer um conjunto de kernel ou um conjunto contundente de reason
e são fortemente encorajados a fornecer um subreason
, se puder ser determinado. Por exemplo, pressionar longamente a tecla liga / desliga que pode ou não ter backup ramoops
teria o motivo de inicialização "reboot,longkey"
.
Nenhuma reason
de primeiro período pode fazer parte de qualquer subreason
ou detail
. No entanto, como os motivos definidos pelo kernel não podem ser produzidos pelo espaço do usuário, "watchdog"
pode ser reutilizado após um motivo definido contundente, junto com um detalhe da fonte (por exemplo "reboot,watchdog,service_manager_unresponsive"
ou "reboot,software,watchdog"
).
Os motivos da inicialização não devem exigir conhecimento interno especializado para serem decifrados e/ou devem ser legíveis por humanos com um relatório intuitivo. Exemplos: "shutdown,vbxd"
(ruim), "shutdown,uv"
(melhor), "shutdown,undervoltage"
(preferencial).
Combinações Razão-Subrazão
O Android reserva um conjunto de combinações reason
e subreason
que não devem ser sobrecarregados no uso normal, mas podem ser usados caso a caso se a combinação refletir com precisão a condição associada. Exemplos de combinações reservadas incluem:
-
"reboot,userrequested"
-
"shutdown,userrequested"
-
"shutdown,thermal"
(dethermald
) -
"shutdown,battery"
-
"shutdown,battery,thermal"
(deBatteryStatsService
) -
"reboot,adb"
-
"reboot,shell"
-
"reboot,bootloader"
-
"reboot,recovery"
Para obter mais detalhes, consulte kBootReasonMap
em system/core/bootstat/bootstat.cpp
e o histórico de changelog do git associado no repositório de origem do Android.
Relatando motivos de inicialização
Todos os motivos de inicialização, seja do carregador de inicialização ou registrados no motivo de inicialização canônico, devem ser registrados na seção kBootReasonMap
de system/core/bootstat/bootstat.cpp
. A lista kBootReasonMap
é uma mistura de motivos de conformidade e de não conformidade legados. Os desenvolvedores do bootloader devem registrar aqui apenas novos motivos de conformidade (e não devem registrar motivos de não conformidade, a menos que o produto já tenha sido enviado e não possa ser alterado).
Recomendamos fortemente o uso de entradas compatíveis existentes em system/core/bootstat/bootstat.cpp
e o exercício de moderação antes de usar uma string não compatível. Como orientação, é:
- OK para relatar
"kernel_panic"
do bootloader, poisbootstat
pode inspecionarramoops
em busca dekernel_panic signatures
para refinar os submotivos no canônicosystem_boot_reason_prop
. - Não é correto relatar uma string não compatível em
kBootReasonMap
(como"panic")
do carregador de inicialização, pois isso acabará prejudicando a capacidade de refinar oreason
.
Por exemplo, se kBootReasonMap
contém "wdog_bark"
, um desenvolvedor de bootloader deve:
- Mude para
"watchdog,bark"
e adicione à lista emkBootReasonMap
. - Considere o que
"bark"
significa para quem não está familiarizado com a tecnologia e determine se umsubreason
mais significativo está disponível.
Verificando a conformidade do motivo de inicialização
No momento, o Android não fornece um teste CTS ativo que possa acionar ou inspecionar com precisão todos os possíveis motivos de inicialização que um bootloader pode fornecer; os parceiros ainda podem tentar executar um teste passivo para determinar a compatibilidade.
Como resultado, a conformidade do bootloader exige que os desenvolvedores do bootloader sigam voluntariamente o espírito das regras e diretrizes descritas acima. Instamos esses desenvolvedores a contribuir com o AOSP (especificamente para system/core/bootstat/bootstat.cpp
) e usar esta oportunidade como um fórum para discussões sobre problemas de motivo de inicialização.