표준 부팅 이유

Android 9에는 부트로더 부팅 이유 사양에 다음 변경사항이 포함됩니다.

부팅 이유

부트로더는 고유한 방식으로 사용 가능한 하드웨어 및 메모리 리소스를 사용하여 기기가 재부팅된 이유를 확인한 다음, androidboot.bootreason=<reason>의 실행을 위해 이를 Android 커널 명령줄에 추가하여 확인 내용을 전달합니다. 그런 다음 init에서 이 명령줄을 변환하여 Android 속성 bootloader_boot_reason_prop(ro.boot.bootreason)에 전파합니다. Android 12 이상으로 출시되는 기기의 경우 커널 버전 5.10 이상을 사용하면 androidboot.bootreason=<reason>이 커널 명령줄 대신 bootconfig에 추가됩니다.

부팅 이유 사양

이전 Android 버전은 부팅 이유 형식을 지정했습니다. 형식에는 공백 없이 소문자만 사용하도록 했고, 일부 요구사항(예: kernel_panic, watchdog, cold/warm/hard 보고)을 적용하였으며 기타 고유한 이유를 고려했습니다. 사양이 정밀하지 못하다 보니 때때로 무의미하기까지 한 맞춤 부팅 이유 문자열이 수백 가지로 늘어나 관리하기가 어려워졌습니다. 현재 Android 버전에는 부트로더가 파일링한, 파싱이 거의 불가능하거나 무의미한 콘텐츠가 급증하면서 bootloader_boot_reason_prop의 규정 준수 관련 문제가 발생했습니다.

Android 9 버전을 통해 Android팀은 기존 bootloader_boot_reason_prop이 상당히 증가하고 있으며 런타임에 다시 작성할 수 없다는 것을 인지하게 되었습니다. 따라서, 부트로더 개발자와의 상호작용과 기존 시스템 변경을 통해 부팅 이유 사양을 개선해야 합니다. 이를 위해 Android팀은 다음 활동을 진행하고 있습니다.

  • 부트로더 개발자와 소통하며 다음을 권장합니다.
    • bootloader_boot_reason_prop에 표준 이유와 파싱 및 인식 가능한 이유를 제공합니다.
    • system/core/bootstat/bootstat.cpp kBootReasonMap 목록에 참여합니다.
  • 제어 및 런타임 재작성이 가능한 system_boot_reason_prop의 소스(sys.boot.reason)를 추가합니다. 시스템 애플리케이션의 제한된 집합(예: bootstat, init)은 이 속성을 재작성할 수 있으나, 이를 읽을 수 있는 sepolicy 권한이 모든 애플리케이션에 부여될 수 있습니다.
  • 시스템 부팅 이유 속성인 system_boot_reason_prop의 콘텐츠를 신뢰하기 전에 사용자 데이터가 마운트될 때까지 대기하는 부팅 이유를 사용자에게 알립니다.

지연되는 이유는 무엇일까요? bootloader_boot_reason_prop은 부팅 초기에 사용할 수 있지만, 부정확하고 파싱 가능하지 않으며 비표준화된 정보를 나타내므로 Android 보안 정책에 따라 필요시 차단되기 때문입니다. 대부분의 경우 부팅 시스템을 잘 알고 있는 개발자만 이 정보에 액세스해야 합니다. system_boot_reason_prop을 통해 부팅 이유에 사용되는 상세하고 파싱 가능하며 표준화된 API는 사용자 데이터가 마운트된 에만 안정적이고 정확하게 선택할 수 있습니다. 구체적으로는 다음과 같습니다.

  • 사용자 데이터가 마운트되기 전에 system_boot_reason_propbootloader_boot_reason_prop의 값이 포함됩니다.
  • 사용자 정보가 마운트된 후에 규정을 준수하고 더 정확한 정보를 전달하기 위해 system_boot_reason_prop이 업데이트될 수 있습니다.

따라서, Android 9에서는 부팅 이유를 공식적으로 파악하기 전까지의 기간을 연장하여 부팅 이유가 부팅 상태에서 즉각적으로 정확히 파악(bootloader_boot_reason_prop 사용)되기보다는 사용자 데이터가 마운트된 후에 파악(system_boot_reason_prop 사용)되도록 합니다.

Bootstat 로직은 보다 더 유익하고 규정을 잘 준수하는 bootloader_boot_reason_prop에 따라 다릅니다. 이 속성이 예측 가능한 형식을 사용하는 경우 제어되는 모든 재부팅 및 종료 시나리오의 정확도가 개선되어 system_boot_reason_prop의 정확성과 의미가 구체화되고 확장됩니다.

표준 부팅 이유 형식

Android 9에서 bootloader_boot_reason_prop의 표준 부팅 이유 형식은 다음 구문을 사용합니다.

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

형식 지정 규칙:

  • 소문자
  • 공백 없음(밑줄 사용)
  • 인쇄 가능한 모든 문자
  • 쉼표로 구분된 reason, subreason 및 하나 이상의 detail.
    • 필수 reason은 기기가 재부팅 또는 종료된 이유 중 가장 우선순위가 높은 이유를 나타냅니다.
    • 선택사항인 subreason은 기기가 재부팅이나 종료된 이유 또는 누가 기기를 재부팅이나 종료했는지에 관해 요약을 표시합니다.
    • 선택사항인 detail 값으로 하나 이상입니다. detail은 하위 시스템을 지정하여 어떤 특정 시스템에서 subreason이 발생했는지 파악하도록 지원할 수 있습니다. 일반적으로 중요도의 계층 구조에 따라 detail 값을 여러 개 지정할 수 있습니다. 한편, 중요도가 동일한 다수의 detail 값을 보고할 수도 있습니다.

이후에 다른 에이전트가 부팅 이유를 삽입할 수 있으므로 bootloader_boot_reason_prop의 값이 비어 있는 경우에는 잘못된 것으로 간주합니다.

이유 요구사항

reason에 지정된 값(첫 스팬으로 마침표나 쉼표 앞에 위치)은 커널, 타당도가 높은 이유, 타당도가 낮은 이유로 구분되는 다음 집합에 속해야 합니다.

  • 커널 집합은 다음과 같습니다.
    • "watchdog"
    • "kernel_panic"
  • 타당도가 높은 이유의 집합입니다.
    • "recovery"
    • "bootloader"
  • 타당도가 낮은 이유의 집합입니다.
    • "cold": 일반적으로 메모리를 포함한 모든 기기의 전체 재설정을 나타냅니다.
    • "hard": 일반적으로 하드웨어에서 상태를 재설정했으며 ramoops는 영구 콘텐츠를 유지해야 합니다.
    • "warm": 일반적으로 메모리와 기기에서 일부 상태를 유지하며 저장을 지원하는 ramoops(커널의 pstore 드라이버 참고)에는 영구 콘텐츠가 포함됩니다.
    • "shutdown"
    • "reboot": 일반적으로 ramoops 상태 및 하드웨어 상태를 알 수 없음을 의미합니다. cold, hard, warm 값이 기기 재설정의 깊이에 관한 정보를 제공하기 때문에 이 값은 포괄적인 값입니다.

부트로더는 커널 집합 또는 타당도가 낮은 집합 reason을 제공해야 하며, 결정이 가능하다면 subreason을 제공하는 것이 좋습니다. 예를 들어, 전원 키를 길게 누를 경우(ramoops 백업 가능 또는 불가) 부팅 이유가 "reboot,longkey"일 수 있습니다.

첫 스팬이 아닌 reasonsubreason 또는 detail의 일부일 수 있습니다. 하지만, 사용자 공간에서 커널 집합 이유를 생성할 수 없으므로 "watchdog"은 타당도가 낮은 집합 이유 후에 소스의 세부사항과 함께 재사용될 수 있습니다(예: "reboot,watchdog,service_manager_unresponsive" 또는 "reboot,software,watchdog").

부팅 이유는 전문적인 내부 지식이 없이도 이해할 수 있어야 하고 직관적인 보고로 사람이 알아볼 수 있어야 합니다. 예를 들어, "shutdown,vbxd"(나쁨), "shutdown,uv"(보통), "shutdown,undervoltage"(양호)로 표시하는 식입니다.

이유 및 하위 이유 조합

Android는 일반적인 사용에서 오버로드되지 않는 reasonsubreason의 조합을 미리 지정해 두었지만, 조합이 관련 조건을 정확하게 반영하는 경우 사례별로 사용할 수 있습니다. 지정된 조합의 예는 다음과 같습니다.

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

자세한 내용은 system/core/bootstat/bootstat.cppkBootReasonMap과 Android 소스 저장소의 관련 Git 변경 로그 기록을 참고하세요.

부팅 이유 보고

모든 부팅 이유는 부트로더에서 발생하든 표준 부팅 이유에 기록되든지와 상관없이 system/core/bootstat/bootstat.cppkBootReasonMap 섹션에 기록되어야 합니다. kBootReasonMap 목록에는 규정을 준수하는 이유와 규정을 준수하지 않는 기존 이유가 혼합되어 있습니다. 부트로더 개발자는 여기에 규정을 준수하는 새로운 이유만 등록해야 하며, 제품이 이미 배송되어 변경할 수 없는 경우가 아닌 이상 규정을 준수하지 않는 이유를 등록해서는 안 됩니다.

규정을 준수하지 않는 문자열을 사용하기보다는 규정을 준수하는 system/core/bootstat/bootstat.cpp의 기존 항목을 사용하고 제한을 실행하는 것이 좋습니다. 가이드라인은 다음과 같습니다.

  • bootstat에서 ramoops를 검사하여 kernel_panic signatures가 하위 이유를 표준 system_boot_reason_prop으로 세분화할 수 있으므로 부트로더의 "kernel_panic"을 보고해도 됩니다.
  • 부트로더의 kBootReasonMap과 같이 규정을 준수하지 않는 문자열(예: "panic")을 보고해서는 안 됩니다. 이 경우 reason을 세분화하는 기능이 결국 중지되기 때문입니다.

예를 들어, kBootReasonMap"wdog_bark"를 포함하는 경우 부트로더 개발자는 다음을 따라야 합니다.

  • "watchdog,bark"로 변경하고 kBootReasonMap의 목록에 추가합니다.
  • 이 기술에 익숙하지 않은 경우 "bark"를 어떻게 이해할지 고려하고 더 유용한 subreason을 사용할 수 있는지 확인하세요.

부팅 이유 규정 준수 자체 검사

현재 Android는 부트로더가 제공할 수 있는 모든 가능한 부팅 이유를 정확하게 트리거하거나 검사할 수 있는 활성 CTS 테스트를 제공하지 않습니다. 파트너는 수동적 테스트를 실행하여 호환성을 확인할 수 있습니다.

따라서, 부트로더 규정을 준수하려면 부트로더 개발자가 위에 설명된 규칙 및 가이드라인의 의도와 의미에 동의하고 이를 자발적으로 준수해야 합니다. 부트로더 개발자의 경우 AOSP(특히, system/core/bootstat/bootstat.cpp)에 기여하면서 이를 부팅 이유 문제에 관한 토론의 장으로 활용하시기 바랍니다.