कैननिकल बूट की वजह

Android 9 में, बूटलोडर के बूट होने की वजह के स्पेसिफ़िकेशन में ये बदलाव किए गए हैं.

बूट होने की वजहें

बूटलोडर, डिवाइस के लिए उपलब्ध हार्डवेयर और मेमोरी संसाधनों का इस्तेमाल करके यह पता लगाता है कि डिवाइस रीबूट क्यों हुआ. इसके बाद, वह इस जानकारी को Android कर्नल कमांड लाइन में androidboot.bootreason=<reason> जोड़कर, डिवाइस को लॉन्च करने के लिए भेजता है. इसके बाद, init इस कमांड लाइन को Android प्रॉपर्टी bootloader_boot_reason_prop (ro.boot.bootreason) में बदलता है. Android 12 या इसके बाद के वर्शन के साथ लॉन्च होने वाले डिवाइसों के लिए, कर्नेल वर्शन 5.10 या इसके बाद के वर्शन का इस्तेमाल करके, androidboot.bootreason=<reason> को कर्नेल कमांड लाइन के बजाय बूटकॉन्फ़िग में जोड़ा जाता है.

बूट होने की वजह के बारे में जानकारी

Android के पिछले वर्शन में, बूट होने की वजह बताने वाले फ़ॉर्मैट के बारे में बताया गया था. इसमें स्पेस का इस्तेमाल नहीं किया जाता था, सभी अक्षर छोटे होते थे, और कुछ ज़रूरी शर्तें शामिल होती थीं. जैसे, kernel_panic, watchdog, cold/warm/hard की रिपोर्टिंग के लिए. साथ ही, इसमें अन्य खास वजहों को भी शामिल किया जाता था. इस वजह से, बूट होने की वजह बताने वाली सैकड़ों कस्टम स्ट्रिंग (कभी-कभी इनका कोई मतलब नहीं होता) का इस्तेमाल होने लगा. इससे स्थिति को मैनेज करना मुश्किल हो गया. Android के मौजूदा वर्शन में, बूटलोडर ने ऐसा कॉन्टेंट फ़ाइल किया है जिसे पार्स करना मुश्किल है या जिसका कोई मतलब नहीं है. इस वजह से, bootloader_boot_reason_prop को नीति के पालन से जुड़ी समस्याएं आ रही हैं.

Android 9 के रिलीज़ होने के बाद, Android टीम ने यह माना है कि लेगसी bootloader_boot_reason_prop का इस्तेमाल काफ़ी बढ़ गया है. इसलिए, इसे रनटाइम में फिर से नहीं लिखा जा सकता. इसलिए, बूट होने की वजह के बारे में जानकारी देने वाले स्पेसिफ़िकेशन में कोई भी सुधार, बूटलोडर डेवलपर के साथ इंटरैक्शन और मौजूदा सिस्टम में बदलाव करके किया जाना चाहिए. इसके लिए, Android टीम यह काम कर रही है:

  • बूटलोडर डेवलपर से जुड़ना, ताकि उन्हें इन कामों के लिए बढ़ावा दिया जा सके:
    • 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 की सुरक्षा नीति के तहत इसे ज़रूरत के हिसाब से ब्लॉक कर दिया जाता है. ऐसा इसलिए किया जाता है, क्योंकि यह गलत, पार्स न की जा सकने वाली, और गैर-मानक जानकारी दिखाता है. ज़्यादातर मामलों में, इस जानकारी को सिर्फ़ उन डेवलपर को ऐक्सेस करना चाहिए जिन्हें बूट सिस्टम के बारे में पूरी जानकारी हो. बूट होने की वजह के लिए, system_boot_reason_prop के साथ बेहतर, पार्स किया जा सकने वाला, और कैननिकल एपीआई को सिर्फ़ तब भरोसेमंद और सटीक तरीके से चुना जा सकता है, जब उपयोगकर्ता डेटा माउंट हो गया हो. खास तौर से:

  • उपयोगकर्ता डेटा के माउंट होने से पहले, system_boot_reason_prop में bootloader_boot_reason_prop से मिली वैल्यू शामिल होगी.
  • उपयोगकर्ता के डेटा को माउंट करने के बाद, system_boot_reason_prop को नीति का पालन करने के लिए अपडेट किया जा सकता है. इसके अलावा, ज़्यादा सटीक जानकारी देने के लिए भी इसे अपडेट किया जा सकता है.

इस वजह से, Android 9 में बूट होने की वजह का पता लगाने में लगने वाले समय को बढ़ा दिया गया है. इसे बूट होने के तुरंत बाद (bootloader_boot_reason_prop के साथ) सटीक जानकारी देने वाले सिस्टम से बदलकर, सिर्फ़ तब उपलब्ध होने वाले सिस्टम में बदल दिया गया है, जब उपयोगकर्ता का डेटा माउंट हो जाता है (system_boot_reason_prop के साथ).

बूटस्टैट का लॉजिक, ज़्यादा जानकारी देने वाले और नीति का पालन करने वाले bootloader_boot_reason_prop पर निर्भर करता है. जब वह प्रॉपर्टी अनुमान लगाने लायक फ़ॉर्मैट का इस्तेमाल करती है, तो इससे डिवाइस को फिर से चालू करने और बंद करने से जुड़े सभी कंट्रोल किए गए मामलों की सटीक जानकारी मिलती है. इससे system_boot_reason_prop की सटीक जानकारी और मतलब को बेहतर बनाने और बढ़ाने में मदद मिलती है.

बूट होने की वजह का कैननिकल फ़ॉर्मैट

Android 9 में, bootloader_boot_reason_prop के लिए बूट होने की वजह का कैननिकल फ़ॉर्मैट इस सिंटैक्स का इस्तेमाल करता है:

<reason>,<subreason>,<detail>…

फ़ॉर्मैटिंग के नियम:

  • लोअर केस
  • कोई भी फ़ील्ड खाली न हो (अंडरलाइन का इस्तेमाल करें)
  • प्रिंट किए जा सकने वाले सभी वर्ण
  • कॉमा से अलग किए गए reason, subreason, और एक या इससे ज़्यादा detail इंस्टेंस.
    • यह ज़रूरी reason है. इससे यह पता चलता है कि डिवाइस को रीबूट या बंद क्यों करना पड़ा. यह सबसे अहम वजह होती है.
    • यह एक वैकल्पिक subreason है. इसमें यह जानकारी होती है कि डिवाइस को रीबूट या बंद क्यों करना पड़ा. इसके अलावा, इसमें यह भी बताया जाता है कि डिवाइस को किसने रीबूट या बंद किया.
    • एक या उससे ज़्यादा वैकल्पिक detail वैल्यू. detail किसी सबसिस्टम की ओर इशारा कर सकता है, ताकि यह तय करने में मदद मिल सके कि किस सिस्टम की वजह से subreason हुआ. detail के लिए एक से ज़्यादा वैल्यू दी जा सकती हैं. आम तौर पर, इन्हें अहमियत के हिसाब से क्रम में रखा जाना चाहिए. हालांकि, एक जैसी अहमियत वाली कई detail वैल्यू की रिपोर्ट भी की जा सकती है.

bootloader_boot_reason_prop के लिए खाली वैल्यू को अमान्य माना जाता है. इसकी वजह यह है कि इससे अन्य एजेंट, बूट होने की वजह को बाद में जोड़ सकते हैं.

वजह बताने से जुड़ी ज़रूरी शर्तें

reason (पहले स्पैन, खत्म होने या कॉमा से पहले) के लिए दी गई वैल्यू, नीचे दिए गए सेट में से होनी चाहिए. इन्हें कर्नेल, स्ट्रॉन्ग, और ब्लंट वजहों के हिसाब से बांटा गया है:

  • कर्नेल सेट:
    • "watchdog"
    • "kernel_panic"
  • strong set:
    • "recovery"
    • "bootloader"
  • blunt set:
    • "cold". आम तौर पर, इससे सभी डिवाइसों को पूरी तरह से रीसेट करने का पता चलता है. इसमें मेमोरी भी शामिल है.
    • "hard". आम तौर पर, इससे पता चलता है कि हार्डवेयर की स्थिति रीसेट हो गई है और ramoops को लगातार कॉन्टेंट बनाए रखना चाहिए.
    • "warm". आम तौर पर, इससे पता चलता है कि मेमोरी और डिवाइस, कुछ स्टेट को बनाए रखते हैं. साथ ही, ramoops (कर्नेल में pstore ड्राइवर देखें) बैकिंग स्टोर में परसिस्टेंट कॉन्टेंट होता है.
    • "shutdown"
    • "reboot". आम तौर पर इसका मतलब है कि ramoops की स्थिति के बारे में जानकारी नहीं है और हार्डवेयर की स्थिति के बारे में भी जानकारी नहीं है. यह वैल्यू कैचल है, क्योंकि cold, hard, और warm वैल्यू से डिवाइस के रीसेट होने की जानकारी मिलती है.

बूटलोडर को कर्नल सेट या ब्लंट सेट reason देना होगा. साथ ही, अगर subreason का पता लगाया जा सकता है, तो बूटलोडर को 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 और Android सोर्स रिपॉज़िटरी में इससे जुड़े git के बदलाव के इतिहास को देखें.

बूट होने की वजहों की रिपोर्ट करना

बूटलोडर से मिली या कैननिकल बूट की वजह से रिकॉर्ड की गई, बूट से जुड़ी सभी वजहों को kBootReasonMap सेक्शन में रिकॉर्ड किया जाना चाहिए. यह सेक्शन system/core/bootstat/bootstat.cpp में मौजूद होता है. kBootReasonMap सूची में, नीति का पालन करने और नीति का पालन न करने की पुरानी वजहों का मिक्सचर है. बूटलोडर डेवलपर को सिर्फ़ नीति का पालन करने वाले नए कारणों को यहां रजिस्टर करना चाहिए. साथ ही, उन्हें नीति का पालन न करने वाले कारणों को तब तक रजिस्टर नहीं करना चाहिए, जब तक कि प्रॉडक्ट पहले ही शिप न हो गया हो और उसमें बदलाव न किया जा सकता हो.

हमारा सुझाव है कि system/core/bootstat/bootstat.cpp में, नीति का पालन करने वाली मौजूदा एंट्री का इस्तेमाल करें. साथ ही, नीति का पालन न करने वाली स्ट्रिंग का इस्तेमाल करने से पहले, सोच-विचार करें. दिशा-निर्देश के तौर पर, यह:

  • बूटलोडर से "kernel_panic" की रिपोर्ट करने के लिए ठीक है, क्योंकि bootstat, kernel_panic signatures के लिए ramoops की जांच कर सकता है, ताकि उप-वजहों को कैननिकल system_boot_reason_prop में बदला जा सके.
  • ठीक नहीं है कि kBootReasonMap में नीति का पालन न करने वाली स्ट्रिंग की शिकायत की जाए. जैसे, बूटलोडर से "panic"). ऐसा इसलिए, क्योंकि इससे reason को बेहतर बनाने की सुविधा काम नहीं करेगी.

उदाहरण के लिए, अगर kBootReasonMap में "wdog_bark" शामिल है, तो बूटलोडर डेवलपर को यह काम करना चाहिए:

  • "watchdog,bark" में बदलें और kBootReasonMap में सूची में जोड़ें.
  • सोचें कि जिन लोगों को इस टेक्नोलॉजी के बारे में जानकारी नहीं है उनके लिए "bark" का क्या मतलब है. साथ ही, यह तय करें कि क्या ज़्यादा काम का subreason उपलब्ध है.

बूट करने की वजह की पुष्टि करना

फ़िलहाल, Android ऐसा चालू सीटीएस टेस्ट उपलब्ध नहीं कराता है जो बूटलोडर के बूट होने की सभी संभावित वजहों को सटीक तरीके से ट्रिगर या उनकी जांच कर सके. हालांकि, पार्टनर अब भी कंपैटिबिलिटी का पता लगाने के लिए, पैसिव टेस्ट चला सकते हैं.

इसलिए, बूटलोडर के नियमों का पालन करने के लिए, बूटलोडर डेवलपर को ऊपर बताए गए नियमों और दिशा-निर्देशों का पालन करना होगा. हम ऐसे डेवलपर से अनुरोध करते हैं कि वे AOSP में योगदान दें. खास तौर पर, system/core/bootstat/bootstat.cpp में योगदान दें. साथ ही, इस अवसर का इस्तेमाल बूट होने की वजह से होने वाली समस्याओं पर चर्चा करने के लिए फ़ोरम के तौर पर करें.