Android 9 มีการเปลี่ยนแปลงข้อกำหนดเหตุผลการบูตของ Bootloader ดังต่อไปนี้
เหตุผลในการบูต
บูตโหลดเดอร์ใช้ทรัพยากรฮาร์ดแวร์และหน่วยความจำที่มีให้อย่างเฉพาะเจาะจงเพื่อพิจารณาสาเหตุที่อุปกรณ์รีบูต จากนั้นจะสื่อสารการตัดสินนั้นโดยการเพิ่ม 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 ซึ่งทำให้เกิดปัญหาการปฏิบัติตามข้อกำหนดสำหรับ bootloader_boot_reason_prop
เมื่อเปิดตัว Android 9 ทีม Android ตระหนักดีว่า bootloader_boot_reason_prop
รุ่นเดิมมีการใช้งานจำนวนมากและไม่สามารถเขียนใหม่ได้เมื่อรันไทม์ ดังนั้น การปรับปรุงข้อกำหนดเหตุผลการบูตจึงต้องมาจากการทำงานร่วมกับนักพัฒนา Bootloader และการปรับเปลี่ยนระบบที่มีอยู่ ด้วยเหตุนี้ ทีม Android จึงดำเนินการดังนี้
- การมีส่วนร่วมกับนักพัฒนา Bootloader เพื่อกระตุ้นให้ดำเนินการต่อไปนี้
- ระบุเหตุผลที่ถูกต้อง แยกวิเคราะห์ได้ และจดจำได้ให้กับ
bootloader_boot_reason_prop
- เข้าร่วมรายการ
system/core/bootstat/bootstat.cpp
kBootReasonMap
- ระบุเหตุผลที่ถูกต้อง แยกวิเคราะห์ได้ และจดจำได้ให้กับ
- การเพิ่มแหล่งที่มาของ
system_boot_reason_prop
(sys.boot.reason
) ที่ควบคุมได้และเขียนซ้ำได้ในรันไทม์ แอประบบชุดจํากัด (เช่นbootstat
และinit
) สามารถเขียนพร็อพเพอร์ตี้นี้ซ้ำได้ แต่แอปทั้งหมดจะได้รับสิทธิ์ sepolicy ในการอ่าน - แจ้งให้ผู้ใช้ทราบถึงสาเหตุการบูตเพื่อรอจนกว่าระบบจะต่อเชื่อม userdata แล้ว ก่อนเชื่อถือเนื้อหาในพร็อพเพอร์ตี้สาเหตุการบูตของระบบ
system_boot_reason_prop
ทำไมถึงล่าช้า แม้ว่า bootloader_boot_reason_prop
จะพร้อมใช้งานตั้งแต่ช่วงต้นของการบูต แต่นโยบายความปลอดภัยของ Android จะบล็อก bootloader_boot_reason_prop
ตามความจำเป็นเนื่องจากแสดงข้อมูลที่ไม่เป็นความจริง ไม่สามารถแยกวิเคราะห์ได้ และไม่ถูกต้อง
ในสถานการณ์ส่วนใหญ่ มีเพียงนักพัฒนาซอฟต์แวร์ที่มีความเชี่ยวชาญด้านระบบบูตเท่านั้นที่ควรเข้าถึงข้อมูลนี้ได้ API สำหรับเหตุผลในการบูตที่มี system_boot_reason_prop
ที่ปรับแต่งแล้ว แยกวิเคราะห์ได้ และตามมาตรฐานจะได้รับการแยกออกอย่างถูกต้องและเชื่อถือได้หลังจากการต่อเชื่อม userdata แล้วเท่านั้น
ดังนี้
- ก่อนที่ระบบจะต่อเชื่อม userdata
system_boot_reason_prop
จะมีค่าจากbootloader_boot_reason_prop
- หลังจากใส่ข้อมูลผู้ใช้แล้ว ระบบอาจอัปเดต
system_boot_reason_prop
เพื่อให้เป็นไปตามข้อกําหนดหรือเพื่อรายงานข้อมูลที่แม่นยํายิ่งขึ้น
ด้วยเหตุนี้ Android 9 จึงขยายระยะเวลาก่อนที่จะรับเหตุผลการบูตอย่างเป็นทางการ ซึ่งเปลี่ยนจากข้อมูลที่ถูกต้องทันทีในการบูต (ใช้ bootloader_boot_reason_prop
) ไปเป็นข้อมูลที่พร้อมใช้งานหลังจากมีการต่อเชื่อม userdata แล้วเท่านั้น (ใช้ system_boot_reason_prop
)
ตรรกะ Bootstat ขึ้นอยู่กับข้อมูลที่ให้ข้อมูลและเป็นไปตามข้อกำหนดมากขึ้น
bootloader_boot_reason_prop
เมื่อพร็อพเพอร์ตี้ดังกล่าวใช้รูปแบบที่คาดการณ์ได้ ก็จะปรับปรุงความแม่นยำของสถานการณ์การรีบูตและการปิดระบบที่มีการควบคุมทั้งหมด ซึ่งจะช่วยปรับแต่งและขยายความแม่นยำและความหมายของ system_boot_reason_prop
รูปแบบเหตุผลการบูตตามรูปแบบบัญญัติ
รูปแบบเหตุผลการบูตตามหลักเกณฑ์สำหรับ bootloader_boot_reason_prop
ใน Android 9 ใช้ไวยากรณ์ต่อไปนี้
<reason>,<subreason>,<detail>…
กฎการจัดรูปแบบ
- ตัวพิมพ์เล็ก
- ไม่มีค่าว่าง (ใช้ขีดเส้นใต้)
- อักขระที่พิมพ์ได้ทั้งหมด
reason
,subreason
และdetail
อย่างน้อย 1 รายการที่คั่นด้วยคอมมาreason
ที่ต้องระบุซึ่งแสดงถึงเหตุผลที่มีลำดับความสำคัญสูงสุดที่ทําให้อุปกรณ์ต้องรีบูตหรือปิดsubreason
(ไม่บังคับ) ที่แสดงข้อมูลสรุปสั้นๆ เกี่ยวกับสาเหตุที่อุปกรณ์ต้องรีบูตหรือปิดเครื่อง (หรือผู้ที่รีบูตหรือปิดเครื่อง)- ค่า
detail
ที่ไม่บังคับอย่างน้อย 1 ค่า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
ให้เบาะแสเกี่ยวกับระดับการรีเซ็ตอุปกรณ์
บูตโหลดเดอร์ต้องระบุชุดเคอร์เนลหรือชุด Blunt reason
และขอแนะนำอย่างยิ่งให้ระบุ subreason
หากระบุได้ เช่น การกดปุ่มเปิด/ปิดค้างไว้ที่อาจมีหรือไม่มีramoops
ข้อมูลสํารองจะมีเหตุผลการบูต"reboot,longkey"
reason
ช่วงแรกต้องไม่เป็นส่วนหนึ่งของ subreason
หรือ detail
อย่างไรก็ตาม เนื่องจากพื้นที่ผู้ใช้ไม่สามารถสร้างเหตุผลของชุดเคอร์เนลได้ "watchdog"
จึงอาจนํามาใช้ซ้ำหลังจากเหตุผลของชุดที่ชัดเจน พร้อมกับรายละเอียดของแหล่งที่มา (เช่น "reboot,watchdog,service_manager_unresponsive"
หรือ "reboot,software,watchdog"
)
สาเหตุการบูตไม่ควรต้องใช้ความรู้ภายในระดับผู้เชี่ยวชาญในการถอดรหัส และ/หรือควรเป็นภาษาที่มนุษย์อ่านได้พร้อมรายงานที่ใช้งานง่าย ตัวอย่าง
"shutdown,vbxd"
(ไม่ดี), "shutdown,uv"
(ดีกว่า),
"shutdown,undervoltage"
(แนะนำ)
ชุดค่าผสมของเหตุผลและเหตุผลย่อย
Android สงวนชุดค่าผสม reason
-subreason
ที่ไม่ควรใช้มากเกินไปในการใช้งานปกติ แต่ใช้ได้ในแต่ละกรณีหากชุดค่าผสมแสดงถึงเงื่อนไขที่เกี่ยวข้องอย่างถูกต้อง ตัวอย่างชุดค่าผสมที่สงวนไว้ ได้แก่
"reboot,userrequested"
"shutdown,userrequested"
"shutdown,thermal"
(จากthermald
)"shutdown,battery"
"shutdown,battery,thermal"
(จากBatteryStatsService
)"reboot,adb"
"reboot,shell"
"reboot,bootloader"
"reboot,recovery"
ดูรายละเอียดเพิ่มเติมได้ที่ kBootReasonMap
ใน system/core/bootstat/bootstat.cpp
และประวัติบันทึกการเปลี่ยนแปลงของ git ที่เชื่อมโยงกันในห้องเก็บข้อมูลซอร์สโค้ดของ Android
รายงานเหตุผลในการบูต
เหตุผลในการบูตทั้งหมด ไม่ว่าจะเป็นจาก Bootloader หรือบันทึกไว้ในเหตุผลในการบูตตามหลักเกณฑ์ ต้องบันทึกไว้ในส่วน kBootReasonMap
ของ system/core/bootstat/bootstat.cpp
รายการ kBootReasonMap
จะรวมสาเหตุที่ไม่เป็นไปตามข้อกำหนดเดิมและสาเหตุที่ไม่เป็นไปตามข้อกำหนดในปัจจุบัน นักพัฒนาซอฟต์แวร์ Bootloader ควรลงทะเบียนเฉพาะเหตุผลใหม่ที่ไม่เป็นไปตามข้อกำหนดที่นี่ (และไม่ควรลงทะเบียนเหตุผลที่ไม่เป็นไปตามข้อกำหนด เว้นแต่ว่าผลิตภัณฑ์จะจัดส่งไปแล้วและเปลี่ยนแปลงไม่ได้)
เราขอแนะนําอย่างยิ่งให้ใช้รายการที่มีอยู่ซึ่งเป็นไปตามข้อกําหนดใน system/core/bootstat/bootstat.cpp
และพิจารณาอย่างรอบคอบก่อนใช้สตริงที่ไม่เป็นไปตามข้อกําหนด หลักเกณฑ์มีดังนี้
- ตกลงเพื่อรายงาน
"kernel_panic"
จาก bootloader เนื่องจากbootstat
อาจตรวจสอบramoops
สำหรับkernel_panic signatures
เพื่อปรับแต่งเหตุผลย่อยเป็นsystem_boot_reason_prop
ที่เป็นมาตรฐานได้ - ไม่อนุญาตให้รายงานสตริงที่ไม่เป็นไปตามข้อกำหนดใน
kBootReasonMap
(เช่น"panic")
จาก bootloader เนื่องจากท้ายที่สุดแล้วจะทำให้ไม่สามารถปรับแต่งreason
ได้
ตัวอย่างเช่น หาก kBootReasonMap
มี "wdog_bark"
นักพัฒนาโปรแกรมบูตควรทำดังนี้
- เปลี่ยนเป็น
"watchdog,bark"
และเพิ่มลงในรายการในkBootReasonMap
- พิจารณาว่า
"bark"
หมายถึงอะไรสำหรับผู้ที่ไม่คุ้นเคยกับเทคโนโลยี และพิจารณาว่าsubreason
ที่สื่อความหมายมากกว่ามีให้ใช้งานหรือไม่
ยืนยันการปฏิบัติตามข้อกำหนดของเหตุผลในการบูต
ขณะนี้ Android ไม่ได้จัดเตรียมการทดสอบ CTS แบบแอ็กทีฟที่อาจทริกเกอร์หรือตรวจสอบสาเหตุการบูตที่เป็นไปได้ทั้งหมดที่โปรแกรมบูตสามารถระบุได้ พาร์ทเนอร์ยังคงพยายามทำการทดสอบแบบพาสซีฟเพื่อพิจารณาความเข้ากันได้ได้
ด้วยเหตุนี้ การปฏิบัติตามข้อกำหนดของบูตโหลดเดอร์จึงกำหนดให้นักพัฒนาบูตโหลดเดอร์ต้องปฏิบัติตามเจตนารมณ์ของกฎและหลักเกณฑ์ที่อธิบายไว้ข้างต้นด้วยความสมัครใจ
เราขอแนะนำให้นักพัฒนาแอปดังกล่าวมีส่วนร่วมใน AOSP (โดยเฉพาะใน system/core/bootstat/bootstat.cpp
) และใช้โอกาสนี้ในฟอรัมเพื่อพูดคุยเกี่ยวกับปัญหาเกี่ยวกับเหตุผลในการบูต