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

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 देने का सुझाव दिया जाता है. उदाहरण के लिए, पावर बटन को लंबे समय तक दबाने पर डिवाइस के बूट होने की वजह "reboot,longkey" होती है. हालांकि, ऐसा हो सकता है कि इस वजह का ramoops बैकअप न हो.

कोई भी फ़र्स्ट-स्पैन 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) में योगदान दें. साथ ही, इस अवसर का इस्तेमाल बूट होने की वजह से होने वाली समस्याओं पर चर्चा करने के लिए फ़ोरम के तौर पर करें.