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

Android 9 có những 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 riêng biệt để xác định lý do thiết bị khởi động lại, sau đó truyền đạt thông tin xác định đó bằng cách thêm androidboot.bootreason=<reason> vào dòng lệnh kernel Android để khởi chạy. init sau đó 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ị phát hành với Android 12 trở lên, sử dụng phiên bản kernel 5.10 trở lên, androidboot.bootreason=<reason> được thêm vào bootconfig thay vì dòng lệnh kernel.

Quy cách về lý do khởi động

Các bản phát hành trước của Android đã chỉ định một định dạng lý do khởi động không có dấu cách, tất cả đều là chữ thường, có ít yêu cầu (chẳng hạn như để báo cáo kernel_panic, watchdog, cold/warm/hard) và cho phép các lý do duy nhất khác. Quy cách 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 vô nghĩa), từ đó dẫn đến tình trạng không thể quản lý. Kể từ bản phát hành Android hiện tại, động lực lớn 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 đã tạo ra các vấn đề về việc tuân thủ đối với 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ể ghi lại trong thời gian chạy. Do đó, mọi cải tiến đối với quy cách về lý do khởi động phải đến từ các hoạt động tương tác với nhà phát triển trình tải khởi động và các điều chỉnh đối với hệ thống hiện có. Để đạt được mục tiêu đó, nhóm Android đang:

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

Tại sao lại muộn như vậy? Mặc dù bootloader_boot_reason_prop có sẵn từ sớm trong quá trình khởi động, nhưng thuộc tính này bị chặn bởi chính sách bảo mật của Android theo nhu cầu vì thuộc tính này đại diện cho thông tin không chính xác, không thể phân tích cú pháp và không chuẩn. Trong hầu hết các trường hợp, chỉ những nhà phát triển có kiến thức sâu rộng về hệ thống khởi động mới cần truy cập thông tin này. Bạn chỉ có thể chọn một API tinh chỉnh, có thể phân tích cú pháp và chuẩn cho lý do khởi động bằng system_boot_reason_prop một cách đáng tin cậy và chính xác sau khi dữ liệu người dùng được gắ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ủ 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ể chính thức thu thập lý do khởi động, thay đổi từ việc chính xác ngay lập tức trong quá trình 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 gắn kết (với system_boot_reason_prop).

Logic Bootstat phụ thuộc vào nhiều thông tin hơn và tuân thủ hơn bootloader_boot_reason_prop. Khi thuộc tính đó sử dụng định dạng có thể dự đoán, thuộc tính đó 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 máy được kiểm soát, từ đó tinh chỉnh và mở rộng độ chính xác và ý 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 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ả các ký tự in được
  • reason, subreason được phân tách bằng dấu phẩy và một hoặc nhiều thực thể detail.
    • reason bắt buộc đại diện cho 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áy.
    • subreason không bắt buộc đại diện cho bản tóm tắt ngắn gọn về lý do thiết bị phải khởi động lại hoặc tắt máy (hoặc người đã khởi động lại hoặc tắt máy ).
    • Một hoặc nhiều giá trị detail không bắt buộc. A detail có thể trỏ đến một hệ thống con để giúp xác định hệ thống cụ thể nào dẫn đến subreason. Bạn có thể chỉ định nhiều detail giá trị, thường phải tuân theo hệ thống phân cấp mức độ quan trọng. Tuy nhiên, bạn cũng có thể báo cáo nhiều detail giá trị có mức độ quan trọng bằng nhau.

Giá trị trống cho bootloader_boot_reason_prop được 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 đó).

Yêu cầu về lý do

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

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

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

Không có reason nào trong khoảng đầu tiên có thể là một phần của bất kỳ subreason hoặc detail nào. Tuy nhiên, vì các lý do tập hợp kernel không thể được tạo bởi không gian người dùng, nên "watchdog" có thể được sử dụng lại sau lý do tập hợp chung chung, cùng với 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 yêu cầu kiến thức nội bộ chuyên môn để giải mã và/hoặc phải dễ đọc đối với con người bằng 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).

Các kiểu kết hợp lý do-lý do phụ

Android dành riêng một tập hợp các kiểu kết hợp reason-subreason không nên bị quá tải trong quá trình sử dụng bình thường nhưng có thể được sử dụng theo từng trường hợp nếu kiểu kết hợp phản ánh chính xác điều kiện liên quan. Sau đây là các ví dụ về kiểu kết hợp dành riêng:

  • "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 chi tiết, hãy tham khảo kBootReasonMap trong system/core/bootstat/bootstat.cpp và nhật ký thay đổi git liên quan trong kho lưu trữ nguồn Android.

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

Tất cả các lý do khởi động, từ trình tải khởi động hoặc được ghi lại trong lý do khởi động chuẩn, phải được ghi lại trong phần kBootReasonMap của system/core/bootstat/bootstat.cpp. Danh sách kBootReasonMap là sự kết hợp của các lý do tuân thủ và không tuân thủ cũ. Nhà phát triển trình tải khởi động chỉ nên đăng ký các lý do tuân thủ mới 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 vận chuyển và không thể thay đổi).

Bạn nên sử dụng các mục tuân thủ hiện có 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, đó là:

  • OK để báo cáo "kernel_panic" từ trình tải khởi động, vì bootstat có thể kiểm tra ramoops để tìm kernel_panic signatures nhằm tinh chỉnh các lý do phụ thành system_boot_reason_prop chuẩn.
  • Không OK để báo cáo chuỗi không tuân thủ trong kBootReasonMap (chẳng hạn như "panic") từ 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", 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.
  • Cân nhắc ý 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 nào có ý nghĩa hơn không.

Xác minh việc tuân thủ lý do khởi động

Hiện tại, Android không cung cấp bài kiểm tra CTS đang hoạt động có thể kích hoạt hoặc kiểm tra chính xác tất cả các lý do khởi động mà trình tải khởi động có thể cung cấp; đối tác vẫn có thể cố gắng chạy bài kiểm tra 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 nhà phát triển trình tải khởi động tự nguyện tuân thủ tinh thần của các quy tắc và nguyên tắc được mô tả ở trên. Chúng tôi kêu gọi các nhà phát triển đó đóng góp cho AOSP (cụ thể là cho system/core/bootstat/bootstat.cpp) và sử dụng cơ hội này làm diễn đàn thảo luận về các vấn đề liên quan đến lý do khởi động.