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 duy nhất để xác định lý do khiến 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 của nhân Android để khởi động. 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ị khởi chạy bằng Android 12 trở lên, sử dụng phiên bản kernel 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 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 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 phân tích cú pháp được hoặc vô nghĩa do trình tải khởi động điền đã 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ể 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 đế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ểm đ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 các nhà phát triển trình tải khởi động để khuyến khích họ:
- Cung cấp lý do chính tắc, có thể phân tích cú pháp và dễ nhận biết cho
bootloader_boot_reason_prop
. - Tham gia danh sách
system/core/bootstat/bootstat.cpp
kBootReasonMap
.
- Cung cấp lý do chính tắc, có thể phân tích cú pháp và dễ nhận biết cho
- 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ư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 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 userdata đượ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
.
Sao muộn vậy? Mặc dù bootloader_boot_reason_prop
có sẵn từ sớm trong quá trình khởi động, nhưng chính sách bảo mật của Android sẽ chặn bootloader_boot_reason_prop
khi cần vì bootloader_boot_reason_prop
thể hiện thông tin không chính xác, không phân tích cú pháp được 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 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. Một API tinh tế, có thể phân tích cú pháp và chính tắc cho lý do 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 userdata đã được gắn kết.
Cụ thể:
- Trước khi userdata được gắn,
system_boot_reason_prop
sẽ chứa giá trị từbootloader_boot_reason_prop
. - Sau khi userdata được gắn,
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 khi khởi động (với bootloader_boot_reason_prop
) thành chỉ có sẵn sau khi userdata đã được gắn (với system_boot_reason_prop
).
Logic Bootstat phụ thuộc vào bootloader_boot_reason_prop
tuân thủ và có nhiều thông tin hơn. Khi thuộc tính đó sử dụng một định dạng có thể dự đoán, thì độ chính xác của tất cả các trường hợp khởi động lại và tắt có kiểm soát sẽ được cải thiện, 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 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ự có thể in
reason
,subreason
được phân tách bằng dấu phẩy và một hoặc nhiều phiên bảndetail
.- Một
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 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 (hoặc người đã khởi động lại hoặc 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 con để hỗ trợ xác định hệ thống cụ thể nào dẫn đếnsubreason
. Bạn có thể chỉ định nhiều giá trịdetail
. Các giá trị này thường phải tuân theo một hệ thống 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 ngang nhau.
- Một
Giá trị trống cho bootloader_boot_reason_prop
được coi là bất hợp pháp (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 kết thúc hoặc dấu phẩy) phải thuộc tập hợp sau đây, được chia thành các lý do cốt lõi, lý do chính đáng và lý do không chính đáng:
- kernel set:
- "
watchdog"
"kernel_panic"
- "
- strong set:
"recovery"
"bootloader"
- blunt set:
"cold"
. Thường cho biết việc đặt lại hoàn toàn tất 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
phải 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, đồng thời bộ nhớ dự phòngramoops
(xem trình điều khiểnpstore
trong kernel) chứa nội dung liên tục."shutdown"
"reboot"
. Thường có nghĩa là trạng tháiramoops
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
,hard
vàwarm
cung cấp thông tin về mức độ đặt lại của thiết bị.
Trình tải khởi động phải cung cấp một tập hợp hạt nhân hoặc một tập hợp thô reason
và bạn nên cung cấp subreason
nếu có thể xác định được. Ví dụ: thao tác nhấn và giữ nút 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
nào ở khoảng đầu tiên có thể thuộc bất kỳ subreason
hoặc detail
nào. Tuy nhiên, vì không gian người dùng không thể tạo ra các lý do đặt hạt nhân, nên "watchdog"
có thể được dùng lại sau một lý do đặt thô, 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 cần kiến thức nội bộ chuyên môn để giải mã và/hoặc có thể đọc được bằng mắt thường với 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"
(nên dùng).
Các tổ hợp lý do – lý do phụ
Android dành riêng một tổ hợp reason
– subreason
mà bạn không nên sử dụng quá nhiều trong quá trình sử dụng bình thường, nhưng có thể sử dụng tuỳ 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. Sau đây là một số ví dụ về các kiểu kết hợp được đặt trước:
"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, cho dù là từ trình tải khởi động hay được ghi lại trong lý do khởi động chính tắc, đều phải được ghi lại trong phần kBootReasonMap
của system/core/bootstat/bootstat.cpp
. Danh sách kBootReasonMap
bao gồm cả lý do tuân thủ và lý do 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 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 vận chuyển và không thể thay đổi).
Bạn nên sử dụng các mục hiện có, tuân thủ trong system/core/bootstat/bootstat.cpp
và hạn chế trước khi sử dụng một chuỗi không tuân thủ. Theo nguyên tắc, bạn nên:
- OK để báo cáo
"kernel_panic"
từ trình tải khởi động, vìbootstat
có thể kiểm traramoops
đểkernel_panic signatures
tinh chỉnh các lý do phụ thànhsystem_boot_reason_prop
chính tắc. - Không được báo cáo một 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ẽ làm mất 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 cân nhắc ý nghĩa của
"bark"
đối với những người chưa quen thuộc với công nghệ này và xác định xem cósubreason
nào có ý nghĩa hơn hay 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 một kiểm thử 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 có thể khởi động mà trình tải khởi động có thể cung cấp; các đối tác vẫn có thể cố gắng chạy một kiểm thử thụ động để xác định khả năng tương thích.
Do đó, để tuân thủ, 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 được mô tả ở trên.
Chúng tôi kêu gọi những nhà phát triển như vậy đóng góp cho AOSP (cụ thể là 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 đề liên quan đến lý do khởi động.