เหตุผลการบูต Canonical

Android 9 มีการเปลี่ยนแปลงข้อกำหนดเหตุผลในการบูตของ Bootloader ดังต่อไปนี้

เหตุผลในการรีบูต

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 ตามความจำเป็น เนื่องจากแสดงข้อมูลที่ไม่ถูกต้อง แยกวิเคราะห์ไม่ได้ และไม่ใช่ข้อมูลที่ถูกต้อง ในกรณีส่วนใหญ่ มีเพียงนักพัฒนาแอปที่มีความรู้เชิงลึกเกี่ยวกับระบบการบูตเท่านั้นที่ควรเข้าถึงข้อมูลนี้ API ที่ปรับปรุงแล้ว แยกวิเคราะห์ได้ และเป็นมาตรฐาน สำหรับสาเหตุการบูตที่มี system_boot_reason_prop จะเลือกได้อย่างน่าเชื่อถือ และแม่นยำหลังจากติดตั้ง userdata แล้วเท่านั้น ดังนี้

  • ก่อนที่ userdata จะติดตั้ง system_boot_reason_prop จะมีค่าจาก bootloader_boot_reason_prop
  • หลังจากติดตั้ง userdata แล้ว system_boot_reason_prop อาจได้รับการอัปเดตให้เป็นไปตามข้อกำหนดหรือเพื่อ รายงานข้อมูลที่แม่นยำยิ่งขึ้น

ด้วยเหตุนี้ Android 9 จึงขยายระยะเวลา ก่อนที่จะได้รับสาเหตุการบูตอย่างเป็นทางการ โดยเปลี่ยนจากการ ถูกต้องทันทีในการบูต (ด้วย bootloader_boot_reason_prop) เป็นการพร้อมใช้งานหลังจากที่ติดตั้ง userdata แล้วเท่านั้น (ด้วย system_boot_reason_prop)

ตรรกะ Bootstat ขึ้นอยู่กับ bootloader_boot_reason_prop ที่ให้ข้อมูลและเป็นไปตามข้อกำหนดมากขึ้น เมื่อพร็อพเพอร์ตี้นั้นใช้รูปแบบที่คาดการณ์ได้ จะช่วยปรับปรุงความแม่นยำของการรีบูตและการปิดระบบที่ควบคุมทั้งหมด ซึ่งจะช่วยปรับปรุงและขยายความแม่นยำและความหมายของ system_boot_reason_prop

รูปแบบเหตุผลการรีบูต Canonical

รูปแบบเหตุผลการรีบูตที่แน่นอนสำหรับ 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 (ช่วงแรก ก่อนการสิ้นสุดหรือ เครื่องหมายคอมมา) ต้องมาจากชุดต่อไปนี้ซึ่งแบ่งออกเป็นเหตุผลที่เกี่ยวข้องกับเคอร์เนล เหตุผลที่เกี่ยวข้องกับความแข็งแกร่ง และเหตุผลที่เกี่ยวข้องกับความไม่ชัดเจน

  • kernel set:
    • "watchdog"
    • "kernel_panic"
  • strong set:
    • "recovery"
    • "bootloader"
  • blunt set:
    • "cold"โดยทั่วไปจะระบุการรีเซ็ตอุปกรณ์ทั้งหมดอย่างสมบูรณ์ รวมถึงหน่วยความจำ
    • "hard" โดยทั่วไปจะบ่งบอกว่าฮาร์ดแวร์มีการรีเซ็ตสถานะ และramoopsควรเก็บเนื้อหาที่คงอยู่ไว้
    • "warm" โดยทั่วไปจะระบุว่าหน่วยความจำและอุปกรณ์ ยังคงมีสถานะบางอย่าง และramoops (ดูไดรเวอร์ pstore ในเคอร์เนล) ที่จัดเก็บข้อมูลสำรองมีเนื้อหาถาวร
    • "shutdown"
    • "reboot" โดยทั่วไปหมายถึงไม่ทราบสถานะ ramoops และไม่ทราบสถานะฮาร์ดแวร์ ค่านี้เป็นค่าที่ครอบคลุมเนื่องจากค่า cold, hard และ warm ให้ข้อมูลเกี่ยวกับระดับการรีเซ็ตของอุปกรณ์

Bootloader ต้องระบุชุดเคอร์เนลหรือชุด reason และขอแนะนำอย่างยิ่งให้ระบุ subreason หากระบุได้ เช่น การกดปุ่มเปิด/ปิดค้างไว้อาจมีหรือไม่มี ramoops ข้อมูลสำรองจะมีเหตุผลในการบูต "reboot,longkey"

reason ช่วงแรก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 หรือบันทึกไว้ในสาเหตุการบูต Canonical ในส่วน kBootReasonMap ของ system/core/bootstat/bootstat.cpp kBootReasonMap รายการนี้ประกอบด้วยเหตุผลที่ปฏิบัติตามข้อกำหนดและเหตุผลเดิมที่ไม่ได้ปฏิบัติตามข้อกำหนด นักพัฒนา Bootloader ควรลงทะเบียนเฉพาะเหตุผลใหม่ที่ เป็นไปตามข้อกำหนดที่นี่ (และไม่ควรลงทะเบียนเหตุผลที่ไม่เป็นไปตามข้อกำหนด เว้นแต่ ผลิตภัณฑ์จะจัดส่งแล้วและเปลี่ยนแปลงไม่ได้)

เราขอแนะนำอย่างยิ่งให้ใช้รายการที่มีอยู่และเป็นไปตามข้อกำหนดใน system/core/bootstat/bootstat.cpp และใช้ความยับยั้งชั่งใจก่อน ใช้สตริงที่ไม่เป็นไปตามข้อกำหนด โดยมีหลักเกณฑ์ดังนี้

  • ตกลงที่จะรายงาน "kernel_panic" จาก โปรแกรมโหลดระบบปฏิบัติการ เนื่องจาก bootstat อาจตรวจสอบ ramoops เพื่อให้ kernel_panic signatures ปรับแต่ง เหตุผลย่อยให้เป็น system_boot_reason_prop ที่เป็นมาตรฐาน
  • ไม่ควรรายงานสตริงที่ไม่เป็นไปตามข้อกำหนดใน kBootReasonMap (เช่น "panic") จาก โปรแกรมโหลดระบบ เนื่องจากในท้ายที่สุดการดำเนินการนี้จะทำให้ความสามารถในการปรับแต่ง reason เสียหาย

ตัวอย่างเช่น หาก kBootReasonMap มี "wdog_bark" นักพัฒนาโปรแกรม Bootloader ควรทำดังนี้

  • เปลี่ยนเป็น "watchdog,bark" แล้วเพิ่มลงในรายการใน kBootReasonMap
  • พิจารณาว่า "bark" มีความหมายอย่างไรสำหรับผู้ที่ไม่คุ้นเคยกับเทคโนโลยี และพิจารณาว่ามี subreason ที่มีความหมายมากกว่า หรือไม่

ยืนยันการปฏิบัติตามข้อกำหนดของเหตุผลในการปิดเครื่อง

ขณะนี้ Android ยังไม่มีการทดสอบ CTS ที่ใช้งานอยู่ซึ่งสามารถทริกเกอร์หรือตรวจสอบสาเหตุการบูตทั้งหมดที่อาจเกิดขึ้นได้อย่างแม่นยำ โดยที่ Bootloader อาจระบุได้ แต่พาร์ทเนอร์ยังคงพยายามเรียกใช้การทดสอบแบบพาสซีฟเพื่อพิจารณาความเข้ากันได้

ด้วยเหตุนี้ การปฏิบัติตามข้อกำหนดของ Bootloader จึงกำหนดให้นักพัฒนา Bootloader ต้องปฏิบัติตามเจตนารมณ์ของกฎและหลักเกณฑ์ที่อธิบายไว้ข้างต้นโดยสมัครใจ เราขอแนะนำให้นักพัฒนาซอฟต์แวร์ดังกล่าวมีส่วนร่วมใน AOSP (โดยเฉพาะใน system/core/bootstat/bootstat.cpp) และใช้โอกาสนี้เป็น ฟอรัมสำหรับการสนทนาเกี่ยวกับปัญหาเหตุผลในการบูต