Lý do khởi động theo chuẩn

Android 9 có các thay đổi sau đây đối với quy cách về lý do khởi động của trình tải khởi động.

Lý do khởi động

Trình tải khởi động sử dụng các tài nguyên phần cứng và bộ nhớ có sẵn duy nhất để xác định lý do thiết bị khởi động lại, sau đó thông báo kết quả xác định bằng cách thêm androidboot.bootreason=<reason> vào dòng lệnh nhân hệ điều hành Android để khởi chạy. Sau đó, init sẽ dịch dòng lệnh này để truyền đến thuộc tính Android bootloader_boot_reason_prop (ro.boot.bootreason). Đối với các thiết bị chạy Android 12 trở lên và sử dụng kernel phiên bản 5.10 trở lên, androidboot.bootreason=<reason> sẽ được thêm vào bootconfig thay vì dòng lệnh kernel.

Thông số kỹ thuật về lý do khởi động

Các bản phát hành trước đây của Android đã chỉ định một định dạng lý do khởi động không sử dụng dấu cách, tất cả đều là chữ thường, kèm theo một số yêu cầu (chẳng hạn như đối với báo cáo kernel_panic, watchdog, cold/warm/hard) và định dạng này chấp nhận các lý do riêng biệt khác. Thông số kỹ thuật lỏng lẻo này dẫn đến sự gia tăng của hàng trăm chuỗi lý do khởi động tuỳ chỉnh (và đôi khi là vô nghĩa), từ đó dẫn đến một tình huống không thể quản lý. Kể từ bản phát hành Android hiện tại, động lượng tuyệt đối của nội dung gần như không thể phân tích cú pháp hoặc vô nghĩa do trình tải khởi động gửi đã gây ra các vấn đề về việc tuân thủ bootloader_boot_reason_prop.

Với bản phát hành Android 9, nhóm Android nhận thấy rằng bootloader_boot_reason_prop cũ có động lực đáng kể và không thể viết lại trong thời gian chạy. Do đó, mọi điểm cải tiến đối với quy cách về lý do khởi động đều phải bắt nguồn từ hoạt động tương tác với nhà phát triển trình tải khởi động và những điều chỉnh đối với hệ thống hiện có. Để đạt được mục tiêu đó, nhóm Android cần:

  • Tương tác với các nhà phát triển trình tải khởi động để khuyến khích họ:
    • Cung cấp các lý do chính tắc, có thể phân tích cú pháp và dễ nhận dạng cho bootloader_boot_reason_prop.
    • Tham gia danh sách system/core/bootstat/bootstat.cpp kBootReasonMap.
  • Thêm một nguồn được kiểm soát và có thể ghi trong thời gian chạy của system_boot_reason_prop (sys.boot.reason). Một nhóm ứng dụng hệ thống giới hạn (chẳng hạn như bootstatinit) có thể ghi lại thuộc tính này, nhưng tất cả ứng dụng đều có thể được cấp quyền sepolicy để đọc nó.
  • Thông báo cho người dùng về lý do khởi động phải đợi cho đến khi dữ liệu người dùng được kết nối rồi mới tin tưởng nội dung trong thuộc tính lý do khởi động hệ thống system_boot_reason_prop.

Sao lại trễ đến thế? Mặc dù bootloader_boot_reason_prop có sẵn từ sớm khi khởi động, nhưng nó bị chính sách bảo mật Android chặn khi cần thiết vì nó biểu thị thông tin không chính xác, không thể phân tích cú pháp và không chính tắc. Trong hầu hết các trường hợp, chỉ những nhà phát triển có kiến thức chuyên sâu về hệ thống khởi động mới cần truy cập vào thông tin này. API chính tắc, có thể phân tích cú pháp và được tinh chỉnh để khởi động bằng system_boot_reason_prop chỉ có thể được chọn một cách đáng tin cậy và chính xác sau khi dữ liệu người dùng được liên kết. Cụ thể:

  • Trước khi dữ liệu người dùng được gắn kết, system_boot_reason_prop sẽ chứa giá trị từ bootloader_boot_reason_prop.
  • Sau khi dữ liệu người dùng được gắn kết, system_boot_reason_prop có thể được cập nhật để tuân thủ chính sách hoặc để báo cáo thông tin chính xác hơn.

Vì lý do này, Android 9 kéo dài khoảng thời gian trước khi có thể thu nạp chính thức lý do khởi động, thay đổi trạng thái từ tính chính xác ngay lập tức khi khởi động (với bootloader_boot_reason_prop) thành chỉ có sẵn sau khi dữ liệu người dùng đã được kết nối (bằng system_boot_reason_prop).

Logic trạng thái khởi động phụ thuộc vào bootloader_boot_reason_prop tuân thủ và giàu thông tin hơn. Khi thuộc tính đó sử dụng định dạng có thể dự đoán, tính năng này sẽ cải thiện độ chính xác của tất cả các tình huống khởi động lại và tắt nguồn được kiểm soát, từ đó tinh chỉnh và mở rộng độ chính xác cũng như ý nghĩa của system_boot_reason_prop.

Định dạng lý do khởi động chuẩn

Định dạng lý do khởi động chuẩn hoá cho bootloader_boot_reason_prop trong Android 9 sử dụng cú pháp sau:

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

Quy tắc định dạng:

  • Chữ thường
  • Không có khoảng trống (sử dụng dấu gạch dưới)
  • Tất cả ký tự in được
  • reason, subreason và một hoặc nhiều thực thể detail được phân tách bằng dấu phẩy.
    • reason bắt buộc thể hiện lý do có mức độ ưu tiên cao nhất khiến thiết bị phải khởi động lại hoặc tắt.
    • Một subreason (không bắt buộc) thể hiện nội dung tóm tắt ngắn gọn về lý do thiết bị phải khởi động lại/tắt (hoặc người khởi động lại/tắt thiết bị).
    • Một hoặc nhiều giá trị detail không bắt buộc. detail có thể trỏ đến một hệ thống phụ để hỗ trợ việc xác định hệ thống cụ thể nào đã dẫn đến subreason. Bạn có thể chỉ định nhiều giá trị detail và các giá trị này thường phải tuân theo một hệ phân cấp về mức độ quan trọng. Tuy nhiên, bạn cũng có thể báo cáo nhiều giá trị detail có tầm quan trọng như nhau.

Giá trị trống của bootloader_boot_reason_prop bị coi là không hợp lệ (vì điều này cho phép các tác nhân khác chèn lý do khởi động sau khi thực tế).

Yêu cầu về lý do

Giá trị cung cấp cho reason (khoảng đầu tiên, trước khi kết thúc hoặc dấu phẩy) phải thuộc tập hợp sau, được chia theo lý do nhân, mạnh và cùn:

  • bộ nhân hệ điều hành:
    • watchdog"
    • "kernel_panic"
  • tập hợp mạnh:
    • "recovery"
    • "bootloader"
  • thanh cùn:
    • "cold". Nói chung, biểu thị việc đặt lại hoàn toàn tất cả thiết bị, bao gồm cả bộ nhớ.
    • "hard". Thông thường, phần cứng đã được đặt lại trạng thái và ramoops phải giữ lại nội dung cố định.
    • "warm". Thường thì biểu thị bộ nhớ và các thiết bị giữ lại một số trạng thái và kho lưu trữ sao lưu ramoops (xem trình điều khiển pstore trong nhân) chứa nội dung cố định.
    • "shutdown"
    • "reboot". Thông thường, trạng thái ramoops là không xác định và không xác định được trạng thái phần cứng. Giá trị này là một giá trị chung vì các giá trị cold, hardwarm cung cấp manh mối về chiều sâu của quá trình đặt lại thiết bị.

Trình tải khởi động phải cung cấp một nhóm hạt nhân hoặc một nhóm cùn reason, và bạn nên cung cấp một subreason nếu có thể xác định được. Ví dụ: thao tác nhấn và giữ phím nguồn có thể có hoặc không có bản sao lưu ramoops sẽ có lý do khởi động là "reboot,longkey".

Không có reason span đầu tiên nào có thể thuộc bất kỳ subreason hoặc detail nào. Tuy nhiên, do không gian của người dùng tạo ra các lý do liên quan đến tập nhân, nên "watchdog" có thể được sử dụng lại sau một lý do đặt ra cùn, cùng với một thông tin chi tiết về nguồn (ví dụ: "reboot,watchdog,service_manager_unresponsive" hoặc "reboot,software,watchdog").

Lý do khởi động không đòi hỏi kiến thức nội bộ của chuyên gia để giải mã và/hoặc phải dễ đọc đối với con người thông qua một báo cáo trực quan. Ví dụ: "shutdown,vbxd" (không tốt), "shutdown,uv" (tốt hơn), "shutdown,undervoltage" (ưu tiên).

Tổ hợp lý do và lý do phụ

Android đặt trước một tập hợp các tổ hợp reason-subreason không được bị quá tải trong cách sử dụng bình thường, nhưng có thể được sử dụng theo từng trường hợp nếu tổ hợp đó phản ánh chính xác điều kiện liên quan. Ví dụ về các kiểu kết hợp đặt trước bao gồm:

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

Để biết thêm thông tin, vui lòng tham khảo kBootReasonMap trong system/core/bootstat/bootstat.cpp và nhật ký thay đổi git liên kết trong kho lưu trữ nguồn Android.

Báo cáo lý do khởi động

Bạn phải ghi lại mọi lý do khởi động, kể cả từ trình tải khởi động hay ghi lại trong lý do khởi động chính tắc, trong phần kBootReasonMap của system/core/bootstat/bootstat.cpp. Danh sách kBootReasonMap là sự kết hợp giữa các lý do tuân thủ và không tuân thủ. Nhà phát triển trình tải khởi động chỉ nên đăng ký các lý do mới tuân thủ tại đây (và không nên đăng ký các lý do không tuân thủ, trừ phi sản phẩm đã được xuất xưởng và không thể thay đổi).

Bạn nên sử dụng các mục nhập hiện có và tuân thủ trong system/core/bootstat/bootstat.cpp và hạn chế trước khi sử dụng chuỗi không tuân thủ. Theo nguyên tắc, công cụ này:

  • OK để báo cáo "kernel_panic" qua trình tải khởi động, vì bootstat có thể kiểm tra ramoops cho kernel_panic signatures để tinh chỉnh các lý do phụ thành system_boot_reason_prop chính tắc.
  • Không thể báo cáo một chuỗi không tuân thủ trong kBootReasonMap (chẳng hạn như "panic") trong trình tải khởi động, vì điều này cuối cùng sẽ phá vỡ khả năng tinh chỉnh reason.

Ví dụ: nếu kBootReasonMap chứa "wdog_bark", thì nhà phát triển trình tải khởi động nên:

  • Thay đổi thành "watchdog,bark" và thêm vào danh sách trong kBootReasonMap.
  • Hãy xem xét ý nghĩa của "bark" đối với những người không quen thuộc với công nghệ này và xác định xem có subreason có ý nghĩa hơn hay không.

Xác minh tính tuân thủ lý do khởi động

Hiện tại, Android chưa cung cấp chương trình kiểm thử CTS đang hoạt động có thể kích hoạt hoặc kiểm tra chính xác mọi lý do khởi động mà trình tải khởi động có thể đưa ra. Các đối tác vẫn có thể thử chạy kiểm thử thụ động để xác định khả năng tương thích.

Do đó, việc tuân thủ trình tải khởi động yêu cầu các nhà phát triển trình tải khởi động phải tự nguyện tuân thủ tinh thần của các quy tắc và nguyên tắc nêu trên. Chúng tôi kêu gọi các nhà phát triển đó đóng góp cho AOSP (dành riêng cho system/core/bootstat/bootstat.cpp) và tận dụng cơ hội này làm diễn đàn để thảo luận về các vấn đề về lý do khởi động.