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
.
- 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
- 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ưbootstat
vàinit
) 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 đếnsubreason
. 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ưuramoops
(xem trình điều khiểnpstore
trong nhân) chứa nội dung cố định."shutdown"
"reboot"
. Thông thường, trạng tháiramoops
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
,hard
vàwarm
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 traramoops
chokernel_panic signatures
để tinh chỉnh các lý do phụ thànhsystem_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ỉnhreason
.
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 trongkBootReasonMap
. - 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.