डिवाइस के लिए खास कोड

डिवाइस का खास कोड डालने के लिए, रिकवरी सिस्टम में कई हुक शामिल होते हैं, ताकि OTA अपडेट, Android सिस्टम के अलावा डिवाइस के दूसरे हिस्सों को भी अपडेट कर सकते हैं (उदाहरण के लिए, बेसबैंड या रेडियो प्रोसेसर).

नीचे दिए गए सेक्शन और उदाहरणों में, पसंद के मुताबिक बनाए गए टार्डिस डिवाइस पसंद के मुताबिक बनाए गए हैं. yoyodyne वेंडर के तौर पर किया जा सकता है.

पार्टिशन मैप

Android 2.3 के बाद से, यह प्लैटफ़ॉर्म eMMc फ़्लैश डिवाइस और चलने वाले ext4 फ़ाइलसिस्टम के साथ काम करता है ट्रैक करने में मदद मिलती है. यह Memory ऐसी टेक्नोलॉजी डिवाइस (MTD) फ़्लैश डिवाइसों और yaffs2 के साथ भी काम करता है फ़ाइल सिस्टम भेजा जा सकता है.

विभाजन मैप फ़ाइल TARGET_Recovery_FSTAB द्वारा तय की गई है; इस फ़ाइल का इस्तेमाल दोनों और पैकेज बनाने के टूल भी शामिल हैं. मैप फ़ाइल का नाम BoardConfig.mk में TARGET_Recovery_FSTAB.

पार्टिशन की एक सैंपल फ़ाइल, इस तरह दिख सकती है:

device/yoyodyne/tardis/recovery.fstab
# mount point       fstype  device       [device2]        [options (3.0+ only)]

/sdcard     vfat    /dev/block/mmcblk0p1 /dev/block/mmcblk0
/cache      yaffs2  cache
/misc       mtd misc
/boot       mtd boot
/recovery   emmc    /dev/block/platform/s3c-sdhci.0/by-name/recovery
/system     ext4    /dev/block/platform/s3c-sdhci.0/by-name/system length=-4096
/data       ext4    /dev/block/platform/s3c-sdhci.0/by-name/userdata

/sdcard को छोड़कर, जो ज़रूरी नहीं है. इस प्रोग्राम के सभी माउंट पॉइंट उदाहरण को परिभाषित किया जाना चाहिए (डिवाइस अतिरिक्त पार्टिशन भी जोड़ सकते हैं). पांच ऐसे गेम हैं फ़ाइल सिस्टम टाइप:

yaffs2
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है MTD फ़्लैश डिवाइस के ऊपर एक yaffs2 फ़ाइल सिस्टम. "डिवाइस" MTD विभाजन का नाम होना चाहिए और /proc/mtd में दिखना चाहिए.
एमटीडी
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है रॉ MTD पार्टीशन, जिसका इस्तेमाल बूट और रिकवरी जैसे बूट किए जा सकने वाले पार्टिशन के लिए किया जाता है. MTD नहीं है माउंट पॉइंट को असल में माउंट किया जाता है, लेकिन पार्टिशन का पता लगाने के लिए माउंट पॉइंट का इस्तेमाल कुंजी के रूप में किया जाता है. "डिवाइस" /proc/mtd में MTD विभाजन का नाम होना चाहिए.
ऐसेट
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है eMMc फ़्लैश डिवाइस के ऊपर एक ext4 फ़ाइलसिस्टम. "डिवाइस" ब्लॉक डिवाइस का पाथ होना चाहिए.
ईएमसी
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है एक रॉ eMMc ब्लॉक डिवाइस, जिसका इस्तेमाल बूट और रिकवरी जैसे बूट किए जा सकने वाले पार्टिशन के लिए किया जाता है. इसके समान mtd टाइप, eMMc को कभी भी माउंट नहीं किया जाता है. हालांकि, माउंट पॉइंट स्ट्रिंग का इस्तेमाल यह पता लगाने के लिए किया जाता है कि टेबल में डिवाइस शामिल है.
वीफ़ैट
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है ब्लॉक डिवाइस के ऊपर FAT फ़ाइल सिस्टम, आम तौर पर बाहरी स्टोरेज, जैसे कि एसडी कार्ड के लिए. कॉन्टेंट बनाने ब्लॉक डिवाइस ही है; device2 दूसरा ब्लॉक डिवाइस है, जिसे सिस्टम माउंट करने की कोशिश करता है, अगर मुख्य डिवाइस को माउंट करना विफल रहा (एसडी कार्ड के साथ काम करने के लिए जो ज़रूरी है कि डेटा को पार्टिशन टेबल के साथ फ़ॉर्मैट किया जाता है).

सभी सेगमेंट, रूट डायरेक्ट्री में माउंट किए जाने चाहिए. इसका मतलब है कि माउंट पॉइंट की वैल्यू को स्लैश से शुरू करें और कोई अन्य स्लैश न रखें). यह पाबंदी सिर्फ़ डिवाइस को माउंट करने पर लागू होती है रिकवरी में मौजूद फ़ाइल सिस्टम; मुख्य सिस्टम उन्हें कहीं भी माउंट कर सकता है. डायरेक्ट्री /boot, /recovery, और /misc रॉ टाइप होने चाहिए (mtd या emmc), जबकि डायरेक्ट्री /system, /data, /cache और /sdcard (अगर उपलब्ध हो) फ़ाइल सिस्टम टाइप होने चाहिए (yaffs2, ext4 या vfat)

Android 3.0 से शुरू होने वाले, Recovery.fstab फ़ाइल को एक अतिरिक्त वैकल्पिक फ़ील्ड, विकल्प उपलब्ध हैं. फ़िलहाल, सिर्फ़ length ही तय किया गया विकल्प है. इससे आपको साफ़ तौर पर विभाजन की लंबाई तय करें. इस लंबाई का इस्तेमाल सेगमेंट को फिर से फ़ॉर्मैट करते समय किया जाता है (उदाहरण के लिए, डेटा वाइप/फ़ैक्ट्री रीसेट करने की कार्रवाई के दौरान, उपयोगकर्ता के डेटा के बंटवारे के लिए या पूरे ओटीए पैकेज को इंस्टॉल करने के दौरान सिस्टम पार्टिशन). अगर लंबाई की वैल्यू नेगेटिव है, तो तो फ़ॉर्मैट में साइज़ लिया जाता है. इसके लिए, सेगमेंट के सही साइज़ में लंबाई की वैल्यू जोड़ी जाती है. इसके लिए उदाहरण के लिए, "length=-16384" सेटिंग का मतलब है कि उस विभाजन का अंतिम 16k ऐसा नहीं होगा ओवरराइट कर दिया जाता है. यह के एन्क्रिप्शन जैसी सुविधाओं का इस्तेमाल करती है उपयोगकर्ता डेटा का पार्टीशन (जहां एन्क्रिप्शन मेटाडेटा को उस पार्टिशन के आखिर में स्टोर किया जाता है जिसमें ओवरराइट नहीं किया जाना चाहिए).

ध्यान दें: device2 और विकल्प फ़ील्ड वैकल्पिक हैं. इनका इस्तेमाल करके, पार्स करने में अस्पष्टता. अगर लाइन पर चौथे फ़ील्ड में एंट्री ‘/' से शुरू होती है तो इसे device2 एंट्री माना जाता है; अगर एंट्री ‘/' से शुरू नहीं होती है वर्ण का इस्तेमाल करते हैं, तो इसे विकल्प फ़ील्ड माना जाता है.

बूट ऐनिमेशन

डिवाइस बनाने वाली कंपनियां, Android डिवाइस के दिखने पर दिखने वाले ऐनिमेशन को अपनी पसंद के मुताबिक बना सकती हैं चालू हो रहा है. ऐसा करने के लिए, एक .zip फ़ाइल बनाएं और उसे में स्पेसिफ़िकेशन बूटानीमेशन फ़ॉर्मैट में होना चाहिए.

इसके लिए Android Things डिवाइस, ज़िप की गई फ़ाइल को Android Things कंसोल में अपलोड करें, ताकि उसमें इमेज शामिल की जा सकें चुना गया प्रॉडक्ट.

ध्यान दें: इन इमेज को Android ब्रैंड के दिशा-निर्देशों का पालन करना होगा. ब्रैंड के दिशा-निर्देशों के लिए, ज़्यादा जानकारी के लिए, पार्टनर मार्केटिंग Hub.

खाता वापस पाने के लिए यूज़र इंटरफ़ेस (यूआई)

अलग-अलग हार्डवेयर (फ़िज़िकल बटन, एलईडी, स्क्रीन वगैरह) वाले डिवाइसों के लिए सहायता उपलब्ध कराने के लिए, रिकवरी इंटरफ़ेस को अपनी ज़रूरत के हिसाब से बदला जा सकता है, ताकि स्टेटस दिखाया जा सके और मैन्युअल तरीके से ऐक्सेस किया जा सके छिपी हुई सुविधाएं शामिल हैं.

आपका लक्ष्य C++ ऑब्जेक्ट के साथ एक छोटी स्टैटिक लाइब्रेरी बनाना है, खास तौर पर किसी डिवाइस के काम करने के तरीके. फ़ाइल bootable/recovery/default_device.cpp का इस्तेमाल डिफ़ॉल्ट रूप से किया जाता है और यह बेहतर है आपके डिवाइस के लिए इस फ़ाइल का वर्शन लिखते समय, कॉपी करने के लिए शुरुआती पॉइंट.

ध्यान दें: आपको यहां कोई निर्देश नहीं देने वाला मैसेज दिख सकता है. टॉगल करने के लिए टेक्स्ट के लिए, आवाज़ तेज़ करने वाले बटन को दबाने के दौरान पावर बटन को दबाकर रखें. अगर आपके डिवाइस में ये मौजूद नहीं हैं दोनों बटन, टेक्स्ट को टॉगल करने के लिए किसी भी बटन को देर तक दबाकर रखें.

device/yoyodyne/tardis/recovery/recovery_ui.cpp
#include <linux/input.h>

#include "common.h"
#include "device.h"
#include "screen_ui.h"

हेडर और आइटम फ़ंक्शन

डिवाइस क्लास को रिटर्न हेडर और आइटम के लिए फ़ंक्शन की ज़रूरत होती है जो छिपे हुए में दिखते हैं रिकवरी मेन्यू. हेडर में बताया गया है कि मेन्यू कैसे ऑपरेट किया जाता है (जैसे कि मेन्यू को बदलने/चुनने के कंट्रोल हाइलाइट किया गया आइटम).

static const char* HEADERS[] = { "Volume up/down to move highlight;",
                                 "power button to select.",
                                 "",
                                 NULL };

static const char* ITEMS[] =  {"reboot system now",
                               "apply update from ADB",
                               "wipe data/factory reset",
                               "wipe cache partition",
                               NULL };

ध्यान दें: लंबी लाइन छोटी कर दी जाती हैं (एक के बाद एक रैप नहीं किया जाता), इसलिए चौड़ाई को इतना रखें डिवाइस स्क्रीन को ध्यान में रखें.

CheckKey को पसंद के मुताबिक बनाएं

इसके बाद, अपने डिवाइस के RecoveryUI को लागू करने के बारे में बताएं. इस उदाहरण में माना जाता है कि टार्डिस डिवाइस में एक स्क्रीन होती है, ताकि आप बिल्टइन से इनहेरिट कर सकें ScreenRecoveryUI लागू करना (इसके लिए निर्देश देखें बिना स्क्रीन वाले डिवाइस.) सिर्फ़ इस फ़ंक्शन के लिए ScreenRecoveryUI से पसंद के मुताबिक बनाएं CheckKey() है, जो शुरुआत में एसिंक्रोनस कुंजी हैंडलिंग:

class TardisUI : public ScreenRecoveryUI {
  public:
    virtual KeyAction CheckKey(int key) {
        if (key == KEY_HOME) {
            return TOGGLE;
        }
        return ENQUEUE;
    }
};

मुख्य कॉन्सटेंट

KEY_* कॉन्सटेंट linux/input.h में तय किए गए हैं. CheckKey() है इसे कोई फर्क नहीं पड़ता कि शेष रिकवरी में क्या चल रहा है: जब मेनू टॉगल किया गया हो, तो यह चालू रहता है, पैकेज इंस्टॉल करने के दौरान, उपयोगकर्ता के डेटा को वाइप करने वगैरह के दौरान. यह चार में से कोई एक रिटर्न कर सकता है कॉन्सटेंट:

  • टॉगल. मेन्यू और/या टेक्स्ट लॉग के डिसप्ले को चालू या बंद करने के लिए टॉगल करें
  • रीबूट करें. डिवाइस को तुरंत फिर चालू करें
  • ध्यान न दें. इस बटन के दबाने को अनदेखा करें
  • पूछें. इस बटन को दबाने के बाद उसे सिंक्रोनस रूप से इस्तेमाल करें (यानी, रिकवरी करके) मेन्यू सिस्टम, अगर डिसप्ले चालू है)

जब भी किसी कुंजी-डाउन इवेंट के बाद कोई मुख्य-अप इवेंट होता है, तो CheckKey() को कॉल किया जाता है एक ही कुंजी. (इवेंट A-नीचे B-down B-up A-up के नतीजों का क्रम सिर्फ़ CheckKey(B) पर कॉल किया जा रहा है.) CheckKey() कॉल कर सकते हैं यह पता लगाने के लिए कि क्या कोई दूसरी चाबियां पीछे दबाकर रखी जा रही हैं, IsKeyPressed(). (ऊपर दिए गए विकल्पों में मुख्य इवेंट का क्रम, अगर CheckKey(B) ने इसे IsKeyPressed(A) कहा था 'सही' दिखाता है.)

CheckKey() अपनी क्लास में स्टेट को बनाए रख सकता है; इससे यह पता लगाने में मदद मिलती है कि के क्रम में रखें. यह उदाहरण थोड़ा ज़्यादा जटिल सेटअप दिखाता है: डिसप्ले टॉगल किया गया है पावर बटन को दबाकर रखते हुए, आवाज़ तेज़ करने वाले बटन को दबाते हैं. इससे डिवाइस को तुरंत फिर से चालू किया जा सकता है. पावर बटन को लगातार पांच बार दबाएं (इसमें कोई और बटन नहीं है):

class TardisUI : public ScreenRecoveryUI {
  private:
    int consecutive_power_keys;

  public:
    TardisUI() : consecutive_power_keys(0) {}

    virtual KeyAction CheckKey(int key) {
        if (IsKeyPressed(KEY_POWER) && key == KEY_VOLUMEUP) {
            return TOGGLE;
        }
        if (key == KEY_POWER) {
            ++consecutive_power_keys;
            if (consecutive_power_keys >= 5) {
                return REBOOT;
            }
        } else {
            consecutive_power_keys = 0;
        }
        return ENQUEUE;
    }
};

स्क्रीनरिकवरीयूआई

जब अपनी खुद की इमेज (गड़बड़ी आइकॉन, इंस्टॉलेशन ऐनिमेशन, प्रोग्रेस बार) का इस्तेमाल किया जा रहा हो ScreenRecoveryUI, आप रफ़्तार को कंट्रोल करने के लिए, वैरिएबल animation_fps को सेट कर सकते हैं ऐनिमेशन के फ़्रेम प्रति सेकंड (FPS) के हिसाब से.

ध्यान दें: मौजूदा interlace-frames.py स्क्रिप्ट की मदद से, ये काम किए जा सकते हैं animation_fps की जानकारी को इमेज में सेव करें. इसके पुराने वर्शन में Android के लिए animation_fps को खुद सेट करना ज़रूरी था.

animation_fps वैरिएबल को सेट करने के लिए, इसे बदलें आपकी सब-क्लास में ScreenRecoveryUI::Init() फ़ंक्शन का इस्तेमाल किया जाता है. मान सेट करें, फिर शुरू करने की प्रोसेस पूरी करने के लिए, parent Init() फ़ंक्शन का इस्तेमाल करें. डिफ़ॉल्ट वैल्यू (20 FPS) डिफ़ॉल्ट रिकवरी इमेज से मेल खाता हो; इन इमेज का इस्तेमाल करते समय, आपको एक Init() फ़ंक्शन. इमेज के बारे में जानकारी के लिए, इसे देखें रिकवरी यूज़र इंटरफ़ेस (यूआई) की इमेज.

डिवाइस श्रेणी

RecoveryUI लागू करने के बाद, अपना डिवाइस क्लास (इसे सब-क्लास किया गया) पहले से मौजूद डिवाइस की कैटगरी). इससे आपकी यूआई क्लास का सिंगल इंस्टेंस बनाना चाहिए और उसे GetUI() फ़ंक्शन से:

class TardisDevice : public Device {
  private:
    TardisUI* ui;

  public:
    TardisDevice() :
        ui(new TardisUI) {
    }

    RecoveryUI* GetUI() { return ui; }

रिकवरी शुरू करें

यूज़र इंटरफ़ेस (यूआई) के होने के बाद, StartRecovery() तरीके को रिकवरी की शुरुआत में कॉल किया जाता है को शुरू किया गया है और आर्ग्युमेंट पार्स किए जाने के बाद, लेकिन किसी कार्रवाई को लिया गया. डिफ़ॉल्ट रूप से लागू होने के लिए कुछ नहीं करना होता है, इसलिए आपको अपने सब-क्लास का इस्तेमाल करें:

   void StartRecovery() {
       // ... do something tardis-specific here, if needed ....
    }

रिकवरी मेन्यू उपलब्ध कराएं और मैनेज करें

हेडर लाइनों की सूची और आइटम की सूची पाने के लिए, सिस्टम दो तरीकों का इस्तेमाल करता है. इसमें लागू करने पर, यह फ़ाइल के सबसे ऊपर तय किए गए स्टैटिक अरे दिखाता है:

const char* const* GetMenuHeaders() { return HEADERS; }
const char* const* GetMenuItems() { return ITEMS; }

हैंडलमेन्यूकी

इसके बाद, एक HandleMenuKey() फ़ंक्शन उपलब्ध कराएं, जिसमें बटन दबाएं और मौजूदा बटन मेन्यू दिखाई दे रहा है या नहीं और यह तय किया जा सकता है कि आगे क्या कार्रवाई की जाए:

   int HandleMenuKey(int key, int visible) {
        if (visible) {
            switch (key) {
              case KEY_VOLUMEDOWN: return kHighlightDown;
              case KEY_VOLUMEUP:   return kHighlightUp;
              case KEY_POWER:      return kInvokeItem;
            }
        }
        return kNoAction;
    }

यह तरीका एक कुंजी कोड लेता है (जिसे पहले प्रोसेस किया जा चुका है और यूज़र इंटरफ़ेस (यूआई) ऑब्जेक्ट का CheckKey() तरीका) और मेन्यू/टेक्स्ट लॉग की मौजूदा स्थिति किसको दिखे. रिटर्न वैल्यू एक पूर्णांक होती है. अगर वैल्यू 0 या उससे ज़्यादा है, तो इसे किसी मेन्यू आइटम की पोज़िशन चुनें, जिसे तुरंत शुरू किया जाता है (यह देखें InvokeMenuItem() तरीका नीचे दिया गया है). अगर ऐसा नहीं है, तो इनमें से कोई एक स्थिति हो सकती है पहले से तय स्थिरांक:

  • khighlightUp पर सेट करें. मेन्यू के हाइलाइट किए गए हिस्से को पिछले आइटम पर ले जाएं
  • khighlightdown पर सेट करें. मेन्यू के हाइलाइट किए गए हिस्से को अगले आइटम पर ले जाना
  • kInvakeItem. हाल ही में हाइलाइट किए गए आइटम को शुरू करें
  • kNoAction की पहचान की जा सकती है. इस बटन को दबाकर कुछ भी न करें

जैसा कि दिखने वाले तर्क से पता चलता है, HandleMenuKey() को कॉल किया जाता है, भले ही मेन्यू नहीं दिखेगा. CheckKey() के उलट, रिकवरी के दौरान इसे कॉल नहीं किया जाता जैसे कुछ और और इनपुट का इंतज़ार कर रहे हैं.

ट्रैकबॉल के तरीके

अगर आपके डिवाइस में ट्रैकबॉल जैसा कोई इनपुट सिस्टम है (यह EV_REL टाइप वाले इनपुट इवेंट जनरेट करता है और कोड REL_Y), तो रिकवरी ट्रैकबॉल जैसा इनपुट डिवाइस Y ऐक्सिस में हलचल की रिपोर्ट करता है. आपको बस KEY_UP और मैप करना है मेनू कार्रवाइयों पर KEY_DOWN इवेंट. यह मैपिंग इनके लिए नहीं होती है CheckKey() है, इसलिए आप रीबूट करने के लिए ट्रिगर के रूप में ट्रैकबॉल मोशन का उपयोग नहीं कर सकते या टॉगल कर रहा हूँ.

कार्रवाई बदलने वाली कुंजियां

यह देखने के लिए कि बटन को कार्रवाई बदलने वाली कुंजी के तौर पर दबाकर रखा गया है या नहीं, IsKeyPressed() तरीके को कॉल करें भी बनाई जा सकती है. उदाहरण के लिए, कुछ डिवाइसों पर, रिकवरी सेवा में Alt-W दबाने से डेटा वाइप करने की अनुमति दें, चाहे मेन्यू दिख रहा हो या नहीं. YOu इस तरह से लागू कर सकते हैं:

   int HandleMenuKey(int key, int visible) {
        if (ui->IsKeyPressed(KEY_LEFTALT) && key == KEY_W) {
            return 2;  // position of the "wipe data" item in the menu
        }
        ...
    }

ध्यान दें: अगर दिख रहा है गलत है, तो खास वैल्यू को लौटाने का कोई मतलब नहीं है वे वैल्यू जो मेन्यू में बदलाव करती हैं (हाइलाइट को दूसरी जगह ले जाना, हाइलाइट किए गए आइटम को शुरू करना). ऐसा इसलिए, क्योंकि उपयोगकर्ता ये काम नहीं कर सकता हाइलाइट देखें. हालांकि, अगर आप चाहें, तो वैल्यू दिखा सकते हैं.

शुरू करेंमेन्यू आइटम

इसके बाद, एक ऐसा InvokeMenuItem() तरीका दें जो अरे में पूर्णांक की स्थिति को मैप करता हो GetMenuItems() से कार्रवाइयों के लिए लौटाए गए आइटम. आइटम के कलेक्शन के लिए टार्डिस उदाहरण, इसका इस्तेमाल करें:

   BuiltinAction InvokeMenuItem(int menu_position) {
        switch (menu_position) {
          case 0: return REBOOT;
          case 1: return APPLY_ADB_SIDELOAD;
          case 2: return WIPE_DATA;
          case 3: return WIPE_CACHE;
          default: return NO_ACTION;
        }
    }

इस तरीके से, BuildinAction enum का कोई भी सदस्य, सिस्टम को वह कार्रवाई करने के लिए कह सकता है कार्रवाई (या यदि आप चाहते हैं कि सिस्टम कुछ न करे, तो NO_ACTION सदस्य). यह वह जगह है सिस्टम में मौजूद जानकारी से ज़्यादा, खाता वापस पाने की अतिरिक्त सुविधा देना: इसके लिए कोई आइटम जोड़ें अपना मेन्यू खोलें, तो उस मेन्यू आइटम के शुरू होने पर उसे यहां चलाएं, और NO_ACTION दिखाएं, ताकि सिस्टम कुछ नहीं करता.

createdinAction में ये वैल्यू शामिल की गई हैं:

  • NO_ACTION. कुछ न करें.
  • रीबूट करें. रिकवरी से बाहर निकलें और डिवाइस को सामान्य रूप से फिर से चालू करें.
  • लागू_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD. अलग-अलग प्लैटफ़ॉर्म से कोई अपडेट पैकेज इंस्टॉल करें जगहें. ज़्यादा जानकारी के लिए, साइडलोडिंग देखें.
  • WIPE_CACHE. सिर्फ़ कैश मेमोरी वाले हिस्से को फिर से फ़ॉर्मैट करें. इसकी पुष्टि करने की ज़रूरत नहीं है अन्य चीज़ों से कोई नुकसान नहीं होता है.
  • WIPE_DATA. उपयोगकर्ता के डेटा और कैश मेमोरी के पार्टिशन को फिर से फ़ॉर्मैट करना. इसे फ़ैक्ट्री डेटा भी कहा जाता है रीसेट करें. आगे बढ़ने से पहले, उपयोगकर्ता से इस कार्रवाई की पुष्टि करने के लिए कहा जाता है.

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

   int WipeData() {
       // ... do something tardis-specific here, if needed ....
       return 0;
    }

डिवाइस बनाएं

आखिर में, Recovery_ui.cpp फ़ाइल के अंत में कुछ बॉयलरप्लेट शामिल करें make_device() फ़ंक्शन, जो आपके डिवाइस की क्लास का इंस्टेंस बनाता और दिखाता है:

class TardisDevice : public Device {
   // ... all the above methods ...
};

Device* make_device() {
    return new TardisDevice();
}

delivery_ui.cpp फ़ाइल को पूरा करने के बाद, उसे बनाकर अपने डिवाइस पर उसे वापस पाने से लिंक करें. तय सीमा में Android.mk, ऐसी स्थैतिक लाइब्रेरी बनाएं जिसमें केवल यह C++ फ़ाइल हो:

device/yoyodyne/tardis/recovery/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_SRC_FILES := recovery_ui.cpp

# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
LOCAL_MODULE := librecovery_ui_tardis

include $(BUILD_STATIC_LIBRARY)

फिर, इस डिवाइस के लिए बोर्ड कॉन्फ़िगरेशन में, अपनी स्टैटिक लाइब्रेरी को TARGET_Recovery_UI_LIB.

device/yoyodyne/tardis/BoardConfig.mk
 [...]

# device-specific extensions to the recovery UI
TARGET_RECOVERY_UI_LIB := librecovery_ui_tardis

खाता वापस पाने के लिए यूज़र इंटरफ़ेस (यूआई) इमेज

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

सिर्फ़ इमेज के लिए बना इंटरफ़ेस, स्थानीय भाषा के अनुसार लिखने की ज़रूरत नहीं है. हालांकि, Android 5.0 के बाद से, अपडेट, इमेज के साथ टेक्स्ट की स्ट्रिंग (जैसे कि "सिस्टम अपडेट इंस्टॉल कर रहा है...") दिखा सकता है. ज़्यादा जानकारी के लिए, खाता वापस पाने के लिए स्थानीय भाषा में लिखा गया टेक्स्ट देखें.

Android 5.0 और उसके बाद के वर्शन

Android 5.0 और उसके बाद वाले वर्शन का रिकवरी यूज़र इंटरफ़ेस (यूआई), मुख्य रूप से दो इमेज का इस्तेमाल करता है: गड़बड़ी वाली इमेज और इंस्टॉल करने में दिखने वाला ऐनिमेशन.

OTA गड़बड़ी के दौरान इमेज दिखाई गई

पहली इमेज. icon_error.png

ota इंस्टॉल के दौरान दिखने वाली इमेज

दूसरी इमेज. icon_installing.png

इंस्टॉल करते समय होने वाले ऐनिमेशन को एक PNG इमेज के रूप में दिखाया जाता है, जिसमें इमेज के अलग-अलग फ़्रेम ऐनिमेशन, पंक्ति के हिसाब से इंटरलेस किया गया है (इस वजह से, दूसरी इमेज भी बनाई गई है). उदाहरण के लिए, सात फ़्रेम वाले 200x200 के ऐनिमेशन के साथ, 200x1400 की एक सिंगल इमेज बनाएं, जिसमें पहली फ़्रेम लाइन 0, 7, 14, 21, ...; दूसरा फ़्रेम है, पंक्ति 1, 8, 15, 22, ...; वगैरह. कंबाइंड इमेज में टेक्स्ट डेटा समूह, जो ऐनिमेशन फ़्रेम की संख्या और हर सेकंड में फ़्रेम की संख्या दिखाता है (एफ़पीएस). bootable/recovery/interlace-frames.py टूल, इनपुट फ़्रेम का सेट लेता है और उन्हें रिकवरी के लिए इस्तेमाल की जाने वाली ज़रूरी कंपोज़िट इमेज में जोड़ देता है.

डिफ़ॉल्ट इमेज अलग-अलग डेंसिटी में उपलब्ध होती हैं और bootable/recovery/res-$DENSITY/images (उदाहरण के लिए, bootable/recovery/res-hdpi/images). इंस्टॉलेशन के दौरान स्टैटिक इमेज का इस्तेमाल करने के लिए, आपको सिर्फ़ icon_installing.png चित्र देना होगा और फ़्रेम की संख्या सेट करनी होगी ऐनिमेशन को 0 पर सेट करें (गड़बड़ी वाले आइकॉन को ऐनिमेट नहीं किया जाता; यह हमेशा एक स्टैटिक इमेज होती है).

Android 4.x और इससे पहले के वर्शन

Android 4.x और उससे पहले के रिकवरी यूज़र इंटरफ़ेस (यूआई) में, गड़बड़ी वाली इमेज (ऊपर दिखाई गई है) और ऐनिमेशन और कई ओवरले इमेज इंस्टॉल करना:

ota इंस्टॉल के दौरान दिखने वाली इमेज

तीसरी इमेज. icon_installing.png

इमेज को पहले दिखाया गया
ओवरले

चौथी इमेज. icon-installing_overlay01.png

चित्र को सातवें रूप में दिखाया गया है
ओवरले

पांचवी इमेज. icon_installing_overlay07.png

इंस्टॉल करने के दौरान, ऑन-स्क्रीन डिसप्ले में icon_installing.png का चित्र जोड़कर बनाया गया हो फिर उसके ऊपर एक ओवरले फ़्रेम बनाएं. यहाँ, लाल बॉक्स को हाइलाइट करने के लिए सुपरइंपोज़ किया गया है, ताकि यह हाइलाइट किया जा सके कि बेस इमेज के ऊपर ओवरले कहां रखा गया है:

इसकी मिश्रित इमेज
इंस्टॉल और फ़र्स्ट ओवरले

छठी इमेज. ऐनिमेशन फ़्रेम 1 (icon_installing.png +) इंस्टॉल किया जा रहा है icon_installing_overlay01.png)

इसकी मिश्रित इमेज
इंस्टॉल और सातवां ओवरले

सातवीं इमेज. ऐनिमेशन फ़्रेम 7 इंस्टॉल हो रहा है (icon_installing.png + icon_installing_overlay07.png)

बाद में दिखाए जाने वाले फ़्रेम, सिर्फ़ अगले ओवरले इमेज के ऊपर ड्रॉइंग करके दिखाए जाते हैं वहाँ पहले से मौजूद है; बेस इमेज को फिर से नहीं बनाया गया है.

ऐनिमेशन में फ़्रेम की संख्या, पसंदीदा स्पीड, और ओवरले के x- और y-ऑफ़सेट बेस के हिसाब से, ScreenRecoveryUI क्लास के मेंबर वैरिएबल से सेट किए जाते हैं. इसका इस्तेमाल करते समय डिफ़ॉल्ट छवियों के बजाय कस्टम छवियों का उपयोग करके, अपने ब्राउज़र में Init() सब-क्लास का इस्तेमाल करके, अपनी पसंद की इमेज की इन वैल्यू को बदलें. ज़्यादा जानकारी के लिए, ScreenRecoveryUI). स्क्रिप्ट bootable/recovery/make-overlay.py , इमेज फ़्रेम के सेट को बदलने में मदद कर सकता है को "बेस इमेज + ओवरले इमेज" के बगल में जोड़ा जाता है रिकवरी के लिए ज़रूरी फ़ॉर्म, जिसमें ज़रूरत ऑफ़सेट न करें.

bootable/recovery/res/images में डिफ़ॉल्ट इमेज मौजूद हैं. स्टैटिक इमेज का इस्तेमाल करने के लिए इंस्टॉलेशन के दौरान, आपको केवल icon_installing.png चित्र प्रदान करना होगा और ऐनिमेशन में 0 पर सेट किया जाता है (गड़बड़ी वाले आइकॉन को ऐनिमेट नहीं किया जाता; यह हमेशा एक स्टैटिक इमेज होती है).

खाता वापस पाने के लिए स्थानीय भाषा में दिया गया टेक्स्ट

Android 5.x पर, टेक्स्ट की स्ट्रिंग दिखती है (जैसे, "सिस्टम अपडेट इंस्टॉल किया जा रहा है...") के साथ इमेज. जब मुख्य सिस्टम रिकवरी के लिए चालू होता है, तो यह उपयोगकर्ता की मौजूदा जगह को वापस लाने के लिए कमांड-लाइन विकल्प. हर मैसेज को दिखाने के लिए, रिकवरी की अवधि में एक सेकंड शामिल होता है हर स्थान-भाषा में, उस मैसेज के लिए पहले से रेंडर की गई टेक्स्ट स्ट्रिंग के साथ एक कंपोज़िट इमेज.

रिकवरी टेक्स्ट स्ट्रिंग की सैंपल इमेज:

रिकवरी टेक्स्ट की इमेज

आठवीं इमेज. रिकवरी मैसेज के लिए स्थानीय जगह के अनुसार मैसेज

खाता वापस पाने के लिए दिए गए टेक्स्ट में ये मैसेज दिख सकते हैं:

  • सिस्टम अपडेट इंस्टॉल हो रहा है...
  • गड़बड़ी!
  • मिटाया जा रहा है... (डेटा वाइप/फ़ैक्ट्री रीसेट करते समय)
  • कोई निर्देश नहीं (जब कोई उपयोगकर्ता मैन्युअल तरीके से रिकवरी चालू करता है)

bootable/recovery/tools/recovery_l10n/ में Android ऐप्लिकेशन, स्थानीय भाषा के अनुसार अनुवाद करता है और एक कंपोज़िट इमेज बनाता है. इस ऐप्लिकेशन को इस्तेमाल करने के बारे में जानने के लिए, यहां जाएं: में टिप्पणियां bootable/recovery/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java.

जब कोई उपयोगकर्ता मैन्युअल रूप से रिकवरी चालू करता है, तो हो सकता है कि स्थान-भाषा उपलब्ध न हो और कोई टेक्स्ट न हो दिखाया जाएगा. खाता वापस पाने की प्रक्रिया के लिए, मैसेज को ज़रूरी न बनाएं.

ध्यान दें: छिपा हुआ इंटरफ़ेस, जो लॉग मैसेज दिखाता है. साथ ही, इसकी मदद से उपयोगकर्ता इन कामों को कर सकते हैं मेन्यू से चुनिंदा कार्रवाइयां सिर्फ़ अंग्रेज़ी में उपलब्ध हैं.

प्रोग्रेस बार

प्रोग्रेस बार, मुख्य इमेज (या ऐनिमेशन) के नीचे दिख सकते हैं. प्रोग्रेस बार को इन्होंने बनाया दो इनपुट इमेज को आपस में मिलाएं, जो एक ही साइज़ की होनी चाहिए:

खाली प्रोग्रेस बार

नौवीं इमेज.progress_खाली.png

पूरा प्रोग्रेस बार

10 इमेज.progress_fill.png

फ़िल इमेज का बायां सिरा प्रोग्रेस बार बनाने के लिए, खाली इमेज डालें. दोनों के बीच सीमा की स्थिति प्रोग्रेस दिखाने के लिए इमेज में बदलाव किया गया है. उदाहरण के लिए, इनपुट इमेज के ऊपर दिए गए जोड़े के साथ, डिसप्ले:

प्रोग्रेस बार 1% है

11वीं इमेज. 1% पर प्रोग्रेस बार>

प्रोग्रेस बार 10% है

12वीं इमेज. 10% पर प्रोग्रेस बार

50% पर प्रोग्रेस बार

13वीं इमेज. 50% पर प्रोग्रेस बार

आप इन इमेज के किसी खास डिवाइस के हिसाब से इन्हें बनाए रख सकते हैं. इसके लिए, आपको इमेज में (इमेज में) उदाहरण) device/yoyodyne/tardis/recovery/res/images को अपनाएं. फ़ाइलों के नाम, ऊपर दिए गए नामों से मेल खाने चाहिए; जब उस डायरेक्ट्री में कोई फ़ाइल मिलती है, बिल्ड सिस्टम इसका इस्तेमाल, डिफ़ॉल्ट इमेज के बजाय डिफ़ॉल्ट इमेज के तौर पर करता है. सिर्फ़ आरजीबी में PNG या 8-बिट कलर डेप्थ वाले आरजीबीए फ़ॉर्मैट काम करते हैं.

ध्यान दें: Android 5.x में, अगर स्थान-भाषा को रिकवरी के लिए जाना जाता है और दाईं से बाईं ओर (RTL) भाषा (ऐरेबिक, हिब्रू वगैरह) में, प्रोग्रेस बार दाईं से बाईं ओर भर जाता है बाएं.

बिना स्क्रीन वाले डिवाइस

सभी Android डिवाइसों में स्क्रीन नहीं होती हैं. अगर आपके डिवाइस में बिना ग्राफ़िक यूज़र इंटरफ़ेस वाला उपकरण है या उसमें सिर्फ़-ऑडियो वाले इंटरफ़ेस के लिए, आपको रिकवरी यूज़र इंटरफ़ेस (यूआई) में ज़्यादा बदलाव करने की ज़रूरत पड़ सकती है. इसके बजाय की एक सब-क्लास बनाने के लिए, उसकी पैरंट क्लास RecoveryUI को सीधे सब-क्लास करती है.

RecoveryUI में निचले-लेवल के यूज़र इंटरफ़ेस (यूआई) की कार्रवाइयों को मैनेज करने के तरीके हैं. जैसे, "डिसप्ले को टॉगल करें", "प्रोग्रेस बार को अपडेट करो" "मेन्यू दिखाओ," "मेन्यू को बदलने का तरीका बदलें," वगैरह को बदला जा सकता है. इनसे आपको डिवाइस के लिए सही इंटरफ़ेस मिलता है. ऐसा हो सकता है कि आपके डिवाइस में एलईडी लाइट हों गेम की स्थिति बताने के लिए, अलग-अलग रंगों या पैटर्न का इस्तेमाल किया जा सकता है या फिर यह गेम कभी भी खेला जा सकता है ऑडियो. (शायद आपको किसी मेन्यू या "टेक्स्ट डिसप्ले" मोड का इस्तेमाल करना ही न हो; आपके पास CheckKey() की मदद से उन्हें ऐक्सेस न करें और HandleMenuKey() लागू करने की सुविधा, जो डिसप्ले को कभी भी चालू नहीं करती या किसी मेन्यू को नहीं चुनती आइटम. इस स्थिति में, आपके लिए ज़रूरी RecoveryUI के कई तरीके खाली रह सकते हैं स्टब.)

RecoveryUI का एलान करने के लिए, bootable/recovery/ui.h पर जाएं और देखें कि उसमें कौनसे तरीके इस्तेमाल किए गए हैं का समर्थन करना होगा. RecoveryUI ऐब्स्ट्रैक्ट है—कुछ मेथड पूरी तरह वर्चुअल हैं और इन्हें सब-क्लास—हालांकि, उनमें मुख्य इनपुट की प्रोसेसिंग करने वाला कोड शामिल होता है. आप उसे ओवरराइड कर सकते हैं भी, अगर आपके डिवाइस में कुंजियां नहीं हैं या आपको उन्हें अलग तरीके से प्रोसेस करना है.

अपडेटर

अपडेट पैकेज को इंस्टॉल करने के लिए, डिवाइस के हिसाब से खास कोड का इस्तेमाल किया जा सकता है. इसके लिए, अपडेटर स्क्रिप्ट में से कॉल किए जा सकते हैं. यहां एक सैंपल दिया गया है टार्डिस डिवाइस के लिए फ़ंक्शन:

device/yoyodyne/tardis/recovery/recovery_updater.c
#include <stdlib.h>
#include <string.h>

#include "edify/expr.h"

हर एक्सटेंशन फ़ंक्शन का हस्ताक्षर एक ही होता है. आर्ग्युमेंट वह नाम होता है जिससे फ़ंक्शन को कॉल किया गया, एक State* कुकी, आने वाले आर्ग्युमेंट की संख्या, और आर्ग्युमेंट दिखाने वाले Expr* पॉइंटर का अरे. रिटर्न वैल्यू नए असाइन किए गए Value*.

Value* ReprogramTardisFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc != 2) {
        return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
    }

आपके फ़ंक्शन को कॉल करते समय आपके आर्ग्युमेंट की जांच नहीं की गई—आपके फ़ंक्शन का लॉजिक से यह तय होता है कि उनमें से किसका आकलन किया जाएगा और कितनी बार किया जाएगा. इसलिए, आप एक्सटेंशन का उपयोग करके फ़ंक्शन का इस्तेमाल करता है. आकलन करने के लिए Call Evaluate() एक Expr* तर्क, Value* लौटा रहा है. अगर Evaluate() शून्य को दिखाता है, तो आपको अपने पास मौजूद किसी भी संसाधन को खाली करना चाहिए और तुरंत शून्य वापस करना चाहिए (यह लागू करने से, edify स्टैक को रद्द किया जाता है. अगर ऐसा नहीं होता है, तो आपको वापस की गई वैल्यू का मालिकाना हक मिल जाता है और ख़रीदारी का फ़ैसला लेने में लोगों की मदद करने के लिए, FreeValue() हो गया है.

मान लीजिए कि फ़ंक्शन को दो आर्ग्युमेंट की ज़रूरत है: स्ट्रिंग की वैल्यू key और blob-valued image. इस तरह के आर्ग्युमेंट पढ़े जा सकते हैं:

   Value* key = EvaluateValue(state, argv[0]);
    if (key == NULL) {
        return NULL;
    }
    if (key->type != VAL_STRING) {
        ErrorAbort(state, "first arg to %s() must be string", name);
        FreeValue(key);
        return NULL;
    }
    Value* image = EvaluateValue(state, argv[1]);
    if (image == NULL) {
        FreeValue(key);    // must always free Value objects
        return NULL;
    }
    if (image->type != VAL_BLOB) {
        ErrorAbort(state, "second arg to %s() must be blob", name);
        FreeValue(key);
        FreeValue(image)
        return NULL;
    }

शून्य की जांच करना और पहले आकलन किए गए आर्ग्युमेंट को खाली करना, कई आर्ग्युमेंट. ReadValueArgs() फ़ंक्शन की मदद से इसे आसान बनाया जा सकता है. कोड के बजाय शायद आपने इसे ऊपर लिखा हो:

   Value* key;
    Value* image;
    if (ReadValueArgs(state, argv, 2, &key, &image) != 0) {
        return NULL;     // ReadValueArgs() will have set the error message
    }
    if (key->type != VAL_STRING || image->type != VAL_BLOB) {
        ErrorAbort(state, "arguments to %s() have wrong type", name);
        FreeValue(key);
        FreeValue(image)
        return NULL;
    }

ReadValueArgs(), टाइप-चेकिंग नहीं करता, इसलिए आपको यहां यह करना होगा; यह ज़्यादा है इसे एक if स्टेटमेंट से आसानी से किया जा सकता है, जिसमें प्रॉडक्ट की लागत थोड़ी कम होती है खास गड़बड़ी का मैसेज दिखाया जा सकता है. हालांकि, ReadValueArgs() इससे आपको हर तर्क के साथ-साथ, पहले से आकलन किए गए सभी आर्ग्युमेंट के इस्तेमाल को रोकने की सुविधा मिलती है. साथ ही, गड़बड़ी का मैसेज) दिखेगा. Google आपके यूआरएल पैरामीटर को कैसे इस्तेमाल करेगा, यह तय करने के लिए ReadValueVarArgs() सुविधा फ़ंक्शन, जिसकी वैरिएबल संख्या का आकलन किया जाता है आर्ग्युमेंट (यह Value* की अरे दिखाता है).

आर्ग्युमेंट का आकलन करने के बाद, फ़ंक्शन का इस्तेमाल करें:

   // key->data is a NUL-terminated string
    // image->data and image->size define a block of binary data
    //
    // ... some device-specific magic here to
    // reprogram the tardis using those two values ...

रिटर्न वैल्यू कोई Value* ऑब्जेक्ट होना चाहिए; इस ऑब्जेक्ट का मालिकाना हक इसे पास कर दिया जाएगा कॉलर है. इस Value*—खास तौर पर डेटासदस्य.

इस मामले में, सफलता दिखाने के लिए आपको सही या गलत वैल्यू दिखानी है. याद रखें यह माना जाएगा कि खाली स्ट्रिंग false है और बाकी सभी स्ट्रिंग सही हैं. आपने लोगों तक पहुंचाया मुफ़्त में रिटर्न के लिए स्थिर स्ट्रिंग की मैलोक की हुई कॉपी के साथ एक वैल्यू ऑब्जेक्ट को मैलोक करना होगा, क्योंकि कॉल करने वाले व्यक्ति को free() . इस नंबर पर FreeValue() को कॉल करना न भूलें: इसके लिए, आपके आर्ग्युमेंट का आकलन किया जाता है!

   FreeValue(key);
    FreeValue(image);

    Value* result = malloc(sizeof(Value));
    result->type = VAL_STRING;
    result->data = strdup(successful ? "t" : "");
    result->size = strlen(result->data);
    return result;
}

सुविधा फ़ंक्शन StringValue(), स्ट्रिंग को नए वैल्यू ऑब्जेक्ट में रैप करता है. ऊपर दिए गए कोड को ज़्यादा सटीक तरीके से लिखने के लिए, इसका इस्तेमाल करें:

   FreeValue(key);
    FreeValue(image);

    return StringValue(strdup(successful ? "t" : ""));
}

इस अनुवादक में, फलन को हुक करने के लिए, फलन के बारे में बताएं Register_foo जहां foo उस स्टैटिक लाइब्रेरी का नाम है जिसमें शामिल है डालें. हर एक्सटेंशन फ़ंक्शन को रजिस्टर करने के लिए, RegisterFunction() पर कॉल करें. इन्होंने बदलाव किया है कन्वेंशन, डिवाइस के हिसाब से बने फ़ंक्शन को नाम दें device.whatever, ताकि आप इनका इस्तेमाल न करें भविष्य में जोड़े जाने वाले बिल्ट-इन फ़ंक्शन के साथ विरोध करता है.

void Register_librecovery_updater_tardis() {
    RegisterFunction("tardis.reprogram", ReprogramTardisFn);
}

अब अपने कोड से स्टैटिक लाइब्रेरी बनाने के लिए, Makefile को कॉन्फ़िगर किया जा सकता है. (यह पहले जैसा ही है पिछले सेक्शन में, रिकवरी यूज़र इंटरफ़ेस (यूआई) को पसंद के मुताबिक बनाने के लिए इस्तेमाल किया जाने वाला Makefile; आपके डिवाइस में दोनों हो सकता है स्टैटिक लाइब्रेरी यहां बताई गई हैं.)

device/yoyodyne/tardis/recovery/Android.mk
include $(CLEAR_VARS)
LOCAL_SRC_FILES := recovery_updater.c
LOCAL_C_INCLUDES += bootable/recovery

स्टैटिक लाइब्रेरी का नाम Register_libname फ़ंक्शन में मौजूद.

LOCAL_MODULE := librecovery_updater_tardis
include $(BUILD_STATIC_LIBRARY)

आखिर में, अपनी लाइब्रेरी को वापस लाने के लिए बिल्ड कॉन्फ़िगर करें. अपनी लाइब्रेरी इसमें जोड़ें TARGET_Recovery_UPDATER_LIBS (जिसमें एक से ज़्यादा लाइब्रेरी हो सकती हैं, वे सभी रजिस्टर हो जाती हैं). अगर आपका कोड ऐसी दूसरी स्टैटिक लाइब्रेरी पर निर्भर है जो अपने-आप एक्सटेंशन में बदलाव नहीं करती (जैसे, इनमें Register_libname फ़ंक्शन नहीं होता है), तो उन्हें उनके कॉल किए बिना, उन्हें अपडेटर से लिंक करने के लिए TARGET_Recovery_UPDATER_ ऐप्स (गैर-मौजूद) पंजीकरण फ़ंक्शन. उदाहरण के लिए, अगर आपको डिवाइस के हिसाब से बने कोड का इस्तेमाल करना था, zlib, डेटा को डिकंप्रेस करना है, तो आपको libz को यहाँ शामिल करना होगा.

device/yoyodyne/tardis/BoardConfig.mk
 [...]

# add device-specific extensions to the updater binary
TARGET_RECOVERY_UPDATER_LIBS += librecovery_updater_tardis
TARGET_RECOVERY_UPDATER_EXTRA_LIBS +=

आपके ओटीए पैकेज में मौजूद अपडेटर स्क्रिप्ट, अब आपके फ़ंक्शन को किसी अन्य फ़ंक्शन की तरह कॉल कर सकती हैं. फिर से प्रोग्राम करने के लिए अपडेट स्क्रिप्ट में ये शामिल हो सकते हैं: tardis.reprogram("the-key", package_extract_file("tardis-image.dat")) . यह पहले से मौजूद फ़ंक्शन package_extract_file() का सिंगल-अर्ग्यूमेंट वर्शन, यह अपडेट पैकेज से निकाली गई फ़ाइल के कॉन्टेंट को BLOB के तौर पर दिखाता है का दूसरा तर्क जोड़ा जा सकता है.

OTA पैकेज जनरेट करना

आखिरी कॉम्पोनेंट में, आपको OTA पैकेज जनरेट करने के टूल के बारे में जानकारी देनी होगी. डिवाइस से जुड़े डेटा को इकट्ठा करने और अपडेटर स्क्रिप्ट जनरेट करने के लिए किया जाता है. इन स्क्रिप्ट में, आपके एक्सटेंशन फ़ंक्शन में इस्तेमाल होने वाले कॉल शामिल होते हैं.

सबसे पहले, बिल्ड सिस्टम को किसी खास डिवाइस के हिसाब से डेटा के ब्लॉब के बारे में बताएं. डेटा देखना फ़ाइल device/yoyodyne/tardis/tardis.dat में है, तो अपने डिवाइस का AndroidBoard.mk:

device/yoyodyne/tardis/AndroidBoard.mk
  [...]

$(call add-radio-file,tardis.dat)

इसके बजाय, इसे Android.mk में भी रखा जा सकता है. हालांकि, इसके बाद यह ज़रूरी है कि डिवाइस किसी डिवाइस से सुरक्षित हो की जांच करें, क्योंकि ट्री में सभी Android.mk फ़ाइलें लोड होती हैं, भले ही कोई भी डिवाइस बनाया. (अगर आपके ट्री में एक से ज़्यादा डिवाइस हैं, तो आपको tardis.dat फ़ाइल को सिर्फ़ तब टार्डिस डिवाइस बनाना.)

device/yoyodyne/tardis/Android.mk
  [...]

# an alternative to specifying it in AndroidBoard.mk
ifeq (($TARGET_DEVICE),tardis)
  $(call add-radio-file,tardis.dat)
endif

इन्हें ऐतिहासिक वजहों से रेडियो फ़ाइलें कहा जाता है; उनका इस जानकारी से कोई लेना-देना नहीं होगा डिवाइस रेडियो (अगर मौजूद हो). ये उस डेटा के अधूरे ब्लॉब होते हैं, जिसमें बिल्ड सिस्टम कॉपी करता है टारगेट-फ़ाइलें .zip, जिसका इस्तेमाल OTA जनरेट करने वाले टूल करते हैं. जब आप बिल्ड करते हैं, तो tardis.dat होता है इसे target-files.zip में RADIO/tardis.dat के तौर पर सेव किया जाएगा. कॉल किया जा सकता है जितनी चाहें उतनी फ़ाइलें जोड़ने के लिए, कई बार add-radio-file.

Python मॉड्यूल

रिलीज़ टूल का दायरा बढ़ाने के लिए, टूल वाला एक Python मॉड्यूल लिखें (जिसे Releasetools.py नाम दिया जाना चाहिए) अगर मौजूद है, तो में कॉल कर सकते हैं. उदाहरण:

device/yoyodyne/tardis/releasetools.py
import common

def FullOTA_InstallEnd(info):
  # copy the data into the package.
  tardis_dat = info.input_zip.read("RADIO/tardis.dat")
  common.ZipWriteStr(info.output_zip, "tardis.dat", tardis_dat)

  # emit the script code to install this data on the device
  info.script.AppendExtra(
      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")

इंक्रीमेंटल ओटीए पैकेज जनरेट करने के मामले को एक अलग फ़ंक्शन हैंडल करता है. इसके लिए उदाहरण के लिए, मान लें कि आपको टार्डिस को सिर्फ़ तब फिर से प्रोग्राम करना होगा, जब tardis.dat फ़ाइल बदल गई हो दो बिल्ड के बीच इस्तेमाल कर सकता है.

def IncrementalOTA_InstallEnd(info):
  # copy the data into the package.
  source_tardis_dat = info.source_zip.read("RADIO/tardis.dat")
  target_tardis_dat = info.target_zip.read("RADIO/tardis.dat")

  if source_tardis_dat == target_tardis_dat:
      # tardis.dat is unchanged from previous build; no
      # need to reprogram it
      return

  # include the new tardis.dat in the OTA package
  common.ZipWriteStr(info.output_zip, "tardis.dat", target_tardis_dat)

  # emit the script code to install this data on the device
  info.script.AppendExtra(
      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")

मॉड्यूल फ़ंक्शन

मॉड्यूल में नीचे दिए गए फ़ंक्शन दिए जा सकते हैं (सिर्फ़ वही फ़ंक्शन लागू करें जिनकी आपको ज़रूरत है).

FullOTA_Assertions()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है पूरा ओटीए जनरेट करने की शुरुआत होने वाले समय के लिए कॉल किया गया. दावे करने के लिए यह एक अच्छी जगह है डिवाइस की मौजूदा स्थिति के बारे में जानकारी. उन स्क्रिप्ट कमांड का इस्तेमाल न करें जो डिवाइस.
FullOTA_InstallBegin()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है डिवाइस की स्थिति के बारे में किए गए सभी दावों के बाद, लेकिन कोई भी बदलाव होने से पहले कॉल किया गया बनाए गए हैं. डिवाइस से जुड़े ऐसे अपडेट के लिए निर्देश भेजे जा सकते हैं जिन्हें इस तारीख से पहले चलाना ज़रूरी है डिवाइस पर मौजूद किसी भी चीज़ को बदल दिया गया है.
FullOTA_InstallEnd()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है बूट को अपडेट करने के लिए स्क्रिप्ट निर्देशों के बाद, स्क्रिप्ट जनरेशन के अंत में कॉल किया जाता है सिस्टम पार्टिशन उत्सर्जित कर दिए गए हैं. कुछ और निर्देश भी दिए जा सकते हैं, डिवाइस से जुड़े खास अपडेट.
IncrementalOTA_Assertions()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है FullOTA_Assertions() के बराबर है, लेकिन इंक्रीमेंटल जनरेट करते समय कॉल किया जाता है पैकेज अपडेट करें.
IncrementalOTA_VerifyBegin()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है डिवाइस की स्थिति के बारे में किए गए सभी दावों के पास हो जाने के बाद, लेकिन कोई भी बदलाव होने से पहले कॉल किया जाता है बनाए गए हैं. डिवाइस से जुड़े ऐसे अपडेट के लिए निर्देश भेजे जा सकते हैं जिन्हें किसी भी काम से पहले चलाया जाना चाहिए डिवाइस की अन्य सेटिंग बदल दी गई है.
IncrementalOTA_VerifyEnd()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है पुष्टि की प्रक्रिया के खत्म होने पर यह कॉल किया जाता है, क्योंकि स्क्रिप्ट से फ़ाइलों को स्पर्श करने पर अपेक्षित प्रारंभ होने वाली सामग्री होगी. फ़िलहाल, डिवाइस को बदल दिया गया है. किसी खास डिवाइस के लिए भी कोड का इस्तेमाल किया जा सकता है पुष्टि की प्रक्रिया.
IncrementalOTA_InstallBegin()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है जिन फ़ाइलों को पैच करना है उनकी पुष्टि हो जाने के बाद, उन्हें कॉल किया जाता है पहले के तौर पर सेट कर सकते हैं, लेकिन कोई भी बदलाव करने से पहले. आपके पास इनके लिए निर्देश देने का विकल्प होता है डिवाइस से जुड़े ऐसे अपडेट जिन्हें डिवाइस पर कोई भी अन्य चीज़ बदलने से पहले चलने चाहिए.
IncrementalOTA_InstallEnd()
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है इसके पूरे OTA पैकेज वाले वर्शन की तरह ही, इसे स्क्रिप्ट के आखिर में कॉल किया जाता है जेनरेशन, बूट और सिस्टम पार्टिशन को अपडेट करने के लिए स्क्रिप्ट कमांड के उत्सर्जित. डिवाइस से जुड़े अपडेट के लिए, कुछ और निर्देश भी भेजे जा सकते हैं.

ध्यान दें: अगर डिवाइस की बैटरी खत्म हो जाती है, तो ओटीए इंस्टॉलेशन शुरुआत. ऐसे डिवाइसों के साथ काम करने के लिए तैयार रहें जिन पर ये निर्देश पहले ही चलाए जा चुके हैं, पूरी तरह या कुछ हद तक.

जानकारी वाले ऑब्जेक्ट पर फ़ंक्शन पास करें

फ़ंक्शन को एक ऐसे जानकारी ऑब्जेक्ट पर पास करें जिसमें कई काम के आइटम हों:

  • info.input_zip. (सिर्फ़ पूरे ओटीए के लिए) zipfile.ZipFile ऑब्जेक्ट टारगेट-फ़ाइलें .zip इनपुट करें.
  • info.source_zip. (सिर्फ़ इंक्रीमेंटल ओटीए) इसके लिए zipfile.ZipFile ऑब्जेक्ट सोर्स टारगेट-फ़ाइलें .zip (इंक्रीमेंटल पैकेज होने पर डिवाइस पर पहले से मौजूद बिल्ड को इंस्टॉल किया जा रहा है).
  • info.target_zip. (सिर्फ़ इंक्रीमेंटल ओटीए) इसके लिए zipfile.ZipFile ऑब्जेक्ट टारगेट वाली target-फ़ाइलें .zip (बिल्ड इंक्रीमेंटल पैकेज, डिवाइस पर रखता है).
  • info.Output_zip. पैकेज बनाया जा रहा है; zipfile.ZipFile ऑब्जेक्ट खोला गया लिखने के लिए. सामान्य.ZipWriteStr(info.Output_zip, filename, data) का इस्तेमाल करके फ़ाइल को पैकेज में शामिल करना.
  • info.script. वह स्क्रिप्ट ऑब्जेक्ट जिसमें निर्देश जोड़े जा सकते हैं. कॉल करें स्क्रिप्ट में टेक्स्ट आउटपुट करने के लिए info.script.AppendExtra(script_text). पक्का करें कि आउटपुट टेक्स्ट के आखिर में सेमीकोलन हो, ताकि वह उत्सर्जित किए गए निर्देशों के मुताबिक न चले उससे बचा जा सकता है.

जानकारी वाले ऑब्जेक्ट के बारे में जानने के लिए, इसे देखें ZIP संग्रह के लिए Python सॉफ़्टवेयर फ़ाउंडेशन के दस्तावेज़.

मॉड्यूल की जगह की जानकारी दें

अपनी BoardConfig.mk फ़ाइल में, अपने डिवाइस की Releasetools.py स्क्रिप्ट की जगह की जानकारी दें:

device/yoyodyne/tardis/BoardConfig.mk
 [...]

TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis

अगर TARGET_TARGETTOOLS_EXTENSIONS सेट नहीं किया गया है, तो यह डिफ़ॉल्ट रूप से $(TARGET_DEVICE_DIR)/../common डायरेक्ट्री (device/yoyodyne/common देखें). Releasetools.py स्क्रिप्ट की जगह की जानकारी साफ़ तौर पर देना सबसे अच्छा रहता है. tardis डिवाइस बनाते समय, Releasetools.py स्क्रिप्ट को टारगेट-फ़ाइलों में शामिल किया जाता है .zip फ़ाइल (META/releasetools.py ).

जब रिलीज़ टूल इस्तेमाल किए जाते हैं (img_from_target_files या ota_from_target_files), टारगेट-फ़ाइलें.zip में Releasetools .py स्क्रिप्ट, अगर मौजूद है, तो Android सोर्स ट्री के बजाय इसे प्राथमिकता दी जाती है. साफ़ तौर पर -s (या --device_specific) विकल्प का इस्तेमाल किया जा सकता है. इससे आपको ये काम करने में मदद मिलती है गड़बड़ियां ठीक करने के साथ-साथ उसमें बदलाव करने के लिए टारगेट-फ़ाइलें.

अब, ota_from_target_files चलाने पर, यह अपने-आप target_files .zip फ़ाइल से लिया गया, डिवाइस के हिसाब से बनाया गया मॉड्यूल और ओटीए जनरेट करते समय इसका इस्तेमाल करता है पैकेज:

./build/make/tools/releasetools/ota_from_target_files \
    -i PREVIOUS-tardis-target_files.zip \
    dist_output/tardis-target_files.zip \
    incremental_ota_update.zip

इसके अलावा, जब आप दौड़ते हैं, तो आप डिवाइस के हिसाब से एक्सटेंशन तय कर सकते हैं ota_from_target_files.

./build/make/tools/releasetools/ota_from_target_files \
    -s device/yoyodyne/tardis \
    -i PREVIOUS-tardis-target_files.zip \
    dist_output/tardis-target_files.zip \
    incremental_ota_update.zip

ध्यान दें: विकल्पों की पूरी सूची देखने के लिए, इसमें ota_from_target_files टिप्पणियां: build/make/tools/releasetools/ota_from_target_files.

साइडलोडिंग मैकेनिज़्म

बिना अपडेट पैकेज को मैन्युअल तरीके से इंस्टॉल करने के लिए, रिकवरी में साइडलोडिंग का तरीका होता है इसे मुख्य सिस्टम से ओवर द एयर डाउनलोड करने के लिए किया जा सकता है. साइडलोडिंग का इस्तेमाल, डीबग करने या साइट बनाने के लिए किया जा सकता है उन डिवाइस में किए गए बदलाव जिनसे मुख्य सिस्टम चालू नहीं हो सकता.

अब तक, डिवाइस के एसडी कार्ड से पैकेज लोड करके, अलग से लोड किए जाते थे; इंच गैर-बूटिंग डिवाइस के मामले में, तो किसी अन्य उपकरण का उपयोग करके पैकेज को SD कार्ड पर रखा जा सकता है कंप्यूटर और फिर डिवाइस में डाला गया एसडी कार्ड. बिना Android डिवाइस के इस्तेमाल करने के लिए हटाए जा सकने वाला बाहरी स्टोरेज, रिकवरी टूल को अलग से लोड करने के लिए दो और तरीके अपनाए जा सकते हैं: कैश मेमोरी वाले पार्टिशन से पैकेज लोड करना और adb का इस्तेमाल करके उन्हें यूएसबी पर लोड करना.

अलग से लोड करने के हर तरीके को शुरू करने के लिए, आपके डिवाइस का Device::InvokeMenuItem() तरीका createdinAction के नीचे दिए गए मान दिखा सकते हैं:

  • लागू_EXT. किसी अपडेट पैकेज को बाहरी स्टोरेज से अलग से लोड करें ( /sdcard डायरेक्ट्री). रिकवरी.fstab को /sdcard माउंट पॉइंट के तौर पर सेट करना ज़रूरी है. यह है यह सुविधा उन डिवाइसों पर इस्तेमाल नहीं की जा सकती जो /data (या कुछ) के सिमलिंक वाले एसडी कार्ड को एम्युलेट करते हों एक ही तरह का तरीका). /data आम तौर पर, रिकवरी के लिए उपलब्ध नहीं होता, क्योंकि यह एन्क्रिप्ट किया जा सकता है. रिकवरी यूज़र इंटरफ़ेस (यूआई), /sdcard में .zip फ़ाइलों का मेन्यू दिखाता है और उपयोगकर्ता को किसी एक को चुनने की सुविधा देता है.
  • लागू_CACHE. यह /sdcard से पैकेज लोड करने के जैसा ही होता है, लेकिन इसमें /cache डायरेक्ट्री (जो रिकवरी के लिए हमेशा उपलब्ध है) का इस्तेमाल किया जाता है आज़माएं. सामान्य सिस्टम से, /cache को सिर्फ़ वे लोग लिख सकते हैं जिनके पास खास अधिकार हैं, और अगर डिवाइस बूट नहीं किया जा सकता है, तो /cache डायरेक्ट्री को बिलकुल भी (जिसकी वजह से काम करने की यह प्रक्रिया सीमित हो जाती है).
  • लागू_ADB_SIDELOAD. उपयोगकर्ता को USB केबल के ज़रिए डिवाइस में पैकेज भेजने की अनुमति देता है और एडीबी डेवलपमेंट टूल पर ध्यान देते हैं. इस तरीके को शुरू करने पर, रिकवरी का अपना मिनी शुरू हो जाता है का उपयोग कर सकते हैं, ताकि कनेक्ट किए गए होस्ट कंप्यूटर पर adb इससे बात की जा सके. यह मिनी वर्शन में सिर्फ़ एक निर्देश काम करता है: adb sideload filename. नाम वाली फ़ाइल, होस्ट मशीन से डिवाइस पर भेजी जाती है. इसके बाद, फ़ाइल की पुष्टि की जाती है और इंस्टॉल करता है, जैसे कि उसे लोकल स्टोरेज में रखा गया हो.

कुछ सावधानियां:

  • सिर्फ़ यूएसबी ट्रांसपोर्ट काम करता है.
  • अगर आपका रिकवरी टूल, adbd को सामान्य तरीके से चलाता है (आम तौर पर, userdebug और eng बिल्ड के लिए ऐसा किया जाता है), तो यह जब डिवाइस, adb अलग से लोड करने वाले मोड में होगा, तब शट डाउन हो जाएगा. साथ ही, adb के दौरान यह रीस्टार्ट हो जाएगा अलग से लोड करने के लिए, पैकेज इकट्ठा हो गया है. adb अलग से लोड करने वाले मोड में, कोई adb निर्देश नहीं sideload से ज़्यादा काम करते हैं ( logcat, reboot, push, pull, shell वगैरह.
  • इस डिवाइस पर, adb अलग से लोड करने वाले मोड से बाहर नहीं निकला जा सकता. रद्द करने के लिए, भेजा जा सकता है पैकेज के तौर पर /dev/null (या कोई और चीज़ जो मान्य पैकेज नहीं है) और तो डिवाइस इसकी पुष्टि नहीं कर पाएगा और इंस्टॉलेशन प्रक्रिया नहीं रोक देगा. RecoveryUI लागू करने का CheckKey() तरीका, कीप्रेस के लिए कॉल किया जाता रहेगा, ताकि डिवाइस को फिर से चालू करने और adb अलग से लोड करने वाले मोड में काम करने वाली कुंजी का क्रम तय किया जा सके.