ए/बी अपडेट लागू करना

OEM और SoC विक्रेता जो A/B सिस्टम अपडेट को लागू करना चाहते हैं, उन्हें यह सुनिश्चित करना चाहिए कि उनका बूटलोडर boot_control HAL को लागू करता है और कर्नेल को सही पैरामीटर पास करता है।

बूट नियंत्रण को लागू करना HAL

A/B-सक्षम बूटलोडर्स को hardware/libhardware/include/hardware/boot_control.h पर boot_control HAL को लागू करना चाहिए। आप system/extras/bootctl उपयोगिता और system/extras/tests/bootloader/ का उपयोग करके कार्यान्वयन का परीक्षण कर सकते हैं।

आपको नीचे दिखाए गए राज्य मशीन को भी लागू करना होगा:

चित्रा 1. बूटलोडर राज्य मशीन

कर्नेल की स्थापना

A/B सिस्टम अपडेट लागू करने के लिए:

  1. चेरीपिक निम्नलिखित कर्नेल पैच श्रृंखला (यदि आवश्यक हो):
  2. सुनिश्चित करें कि कर्नेल कमांड लाइन तर्क में निम्नलिखित अतिरिक्त तर्क शामिल हैं:
    skip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"
    ... जहां <public-key-id> मान सार्वजनिक कुंजी की आईडी है जिसका उपयोग सत्यता तालिका हस्ताक्षर को सत्यापित करने के लिए किया जाता है (विवरण के लिए, dm-verity देखें) .
  3. सिस्टम कीरिंग में सार्वजनिक कुंजी वाले .X509 प्रमाणपत्र जोड़ें:
    1. .der स्वरूप में स्वरूपित .X509 प्रमाणपत्र को kernel निर्देशिका के मूल में कॉपी करें। यदि .X509 प्रमाणपत्र को .pem फ़ाइल के रूप में स्वरूपित किया गया है, तो .der .pem में कनवर्ट करने के लिए निम्न openssl कमांड का उपयोग करें:
      openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
    2. प्रमाणपत्र को सिस्टम कीरिंग के भाग के रूप में शामिल करने के लिए zImage बनाएँ। सत्यापित करने के लिए, procfs प्रविष्टि की जाँच करें (सक्षम होने के लिए KEYS_CONFIG_DEBUG_PROC_KEYS की आवश्यकता है):
      angler:/# cat /proc/keys
      
      1c8a217e I------     1 perm 1f010000     0     0 asymmetri
      Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f []
      2d454e3e I------     1 perm 1f030000     0     0 keyring
      .system_keyring: 1/4
      .X509 प्रमाणपत्र का सफल समावेश सिस्टम कीरिंग में सार्वजनिक कुंजी की उपस्थिति को इंगित करता है (हाइलाइट सार्वजनिक कुंजी आईडी को दर्शाता है)।
    3. स्पेस को # से बदलें और इसे कर्नेल कमांड लाइन में <public-key-id> के रूप में पास करें। उदाहरण के लिए, <public-key-id> के स्थान पर Android:#7e4333f9bba00adfe0ede979e28ed1920492b40f पास करें।

बिल्ड वैरिएबल सेट करना

ए/बी-सक्षम बूटलोडर्स को निम्नलिखित बिल्ड वैरिएबल मानदंडों को पूरा करना चाहिए:

A/B लक्ष्य के लिए निश्चित होना चाहिए
  • AB_OTA_UPDATER := true
  • AB_OTA_PARTITIONS := \
    boot \
    system \
    vendor
    और अन्य विभाजन update_engine (रेडियो, बूटलोडर, आदि) के माध्यम से अद्यतन किए गए हैं।
  • PRODUCT_PACKAGES += \
    update_engine \
    update_verifier
उदाहरण के लिए, /device/google/marlin/+/android-7.1.0_r1/device-common.mk देखें। आप वैकल्पिक रूप से संकलन में वर्णित पोस्ट-इंस्टॉल (लेकिन पूर्व-रिबूट) dex2oat चरण का संचालन कर सकते हैं।
A/B लक्ष्य के लिए पुरज़ोर अनुशंसा की जाती है
  • TARGET_NO_RECOVERY := true
  • BOARD_USES_RECOVERY_AS_BOOT := true
  • BOARD_RECOVERYIMAGE_PARTITION_SIZE परिभाषित न करें
A/B लक्ष्य के लिए परिभाषित नहीं किया जा सकता
  • BOARD_CACHEIMAGE_PARTITION_SIZE
  • BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
डिबग बिल्ड के लिए वैकल्पिक PRODUCT_PACKAGES_DEBUG += update_engine_client

विभाजन (स्लॉट) सेट करना

A/B उपकरणों को पुनर्प्राप्ति विभाजन या कैश विभाजन की आवश्यकता नहीं है क्योंकि Android अब इन विभाजनों का उपयोग नहीं करता है। डेटा विभाजन अब डाउनलोड किए गए OTA पैकेज के लिए उपयोग किया जाता है, और पुनर्प्राप्ति छवि कोड बूट विभाजन पर है। ए/बी-एड वाले सभी विभाजनों को इस प्रकार नामित किया जाना चाहिए (स्लॉट्स को हमेशा a , b , आदि नाम दिया जाता है): boot_a , boot_b , system_a , system_b , विक्रेता_a , vendor_a vendor_b

कैश

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

वसूली

पुनर्प्राप्ति RAM डिस्क अब boot.img फ़ाइल में समाहित है। पुनर्प्राप्ति में जाने पर, बूटलोडर कर्नेल कमांड लाइन पर skip_initramfs विकल्प नहीं डाल सकता है।

गैर-ए/बी अद्यतनों के लिए, पुनर्प्राप्ति विभाजन में अद्यतनों को लागू करने के लिए प्रयुक्त कोड होता है। A/B अद्यतन नियमित बूट सिस्टम छवि में चल रहे update_engine द्वारा लागू किए जाते हैं। फ़ैक्टरी डेटा रीसेट और अद्यतन पैकेजों के साइडलोडिंग को लागू करने के लिए अभी भी एक पुनर्प्राप्ति मोड का उपयोग किया जाता है (जहां से "रिकवरी" नाम आया था)। पुनर्प्राप्ति मोड के लिए कोड और डेटा रैमडिस्क में नियमित बूट विभाजन में संग्रहीत किया जाता है; सिस्टम छवि में बूट करने के लिए, बूटलोडर कर्नेल को रैमडिस्क को छोड़ने के लिए कहता है (अन्यथा डिवाइस पुनर्प्राप्ति मोड में बूट हो जाता है। पुनर्प्राप्ति मोड छोटा है (और इसका अधिकांश भाग पहले से ही बूट विभाजन पर था), इसलिए बूट विभाजन नहीं बढ़ता है आकार में।

Fstab

slotselect तर्क ए/बी-एड विभाजन के लिए लाइन पर होना चाहिए। उदाहरण के लिए:

<path-to-block-device>/vendor  /vendor  ext4  ro
wait,verify=<path-to-block-device>/metadata,slotselect

किसी भी विभाजन का नाम vendor नहीं होना चाहिए। इसके बजाय, vendor_a या vendor_b विभाजन का चयन किया जाएगा और /vendor आरोह बिंदु पर आरोहित किया जाएगा।

कर्नेल स्लॉट तर्क

वर्तमान स्लॉट प्रत्यय या तो एक विशिष्ट डिवाइस ट्री (डीटी) नोड ( /firmware/android/slot_suffix ) के माध्यम से या androidboot.slot_suffix कर्नेल कमांड लाइन या bootconfig तर्क के माध्यम से पारित किया जाना चाहिए।

डिफ़ॉल्ट रूप से, फास्टबूट ए/बी डिवाइस पर वर्तमान स्लॉट को फ्लैश करता है। यदि अद्यतन पैकेज में अन्य, गैर-वर्तमान स्लॉट के लिए छवियां भी हैं, तो फास्टबूट उन छवियों को भी फ्लैश करता है। उपलब्ध विकल्पों में शामिल हैं:

  • --slot SLOT । डिफ़ॉल्ट व्यवहार को ओवरराइड करें और तर्क के रूप में पारित स्लॉट को फ्लैश करने के लिए फास्टबूट को संकेत दें।
  • --set-active [ SLOT ] । स्लॉट को सक्रिय के रूप में सेट करें। यदि कोई वैकल्पिक तर्क निर्दिष्ट नहीं है, तो वर्तमान स्लॉट सक्रिय के रूप में सेट है।
  • fastboot --help . आदेशों पर विवरण प्राप्त करें।

यदि बूटलोडर फास्टबूट को लागू करता है, तो उसे कमांड का समर्थन करना चाहिए set_active <slot> जो वर्तमान सक्रिय स्लॉट को दिए गए स्लॉट पर सेट करता है (यह उस स्लॉट के लिए अनबूट करने योग्य ध्वज को भी साफ़ करना चाहिए और डिफ़ॉल्ट मानों पर पुनर्प्रयास गणना को रीसेट करना चाहिए)। बूटलोडर को निम्नलिखित चरों का भी समर्थन करना चाहिए:

  • has-slot:<partition-base-name-without-suffix> । यदि दिया गया विभाजन स्लॉट का समर्थन करता है, तो "हां" लौटाता है, अन्यथा "नहीं"।
  • current-slot । स्लॉट प्रत्यय देता है जिसे अगले से बूट किया जाएगा।
  • slot-count । उपलब्ध स्लॉट की संख्या का प्रतिनिधित्व करने वाला एक पूर्णांक देता है। वर्तमान में, दो स्लॉट समर्थित हैं इसलिए यह मान 2 है।
  • slot-successful:<slot-suffix> । यदि दिए गए स्लॉट को सफलतापूर्वक बूट करने के रूप में चिह्नित किया गया है, तो "हां" लौटाता है, अन्यथा "नहीं"।
  • slot-unbootable:<slot-suffix> । यदि दिए गए स्लॉट को बूट न ​​करने योग्य के रूप में चिह्नित किया गया है, तो "हां" लौटाता है, अन्यथा "नहीं"।
  • slot-retry-count . दिए गए स्लॉट को बूट करने के प्रयास के लिए शेष पुनर्प्रयासों की संख्या।

सभी चर देखने के लिए, fastboot getvar all चलाएँ।

ओटीए पैकेज बनाना

OTA पैकेज उपकरण गैर-A/B उपकरणों के लिए आदेशों के समान ही आदेशों का पालन करते हैं। A/B लक्ष्य के लिए बिल्ड वैरिएबल को परिभाषित करके target_files.zip फ़ाइल जनरेट की जानी चाहिए। OTA पैकेज टूल स्वचालित रूप से A/B अपडेटर के लिए प्रारूप में पैकेजों की पहचान करता है और उत्पन्न करता है।

उदाहरण:

  • एक पूर्ण ओटीए उत्पन्न करने के लिए:
    ./build/make/tools/releasetools/ota_from_target_files \
        dist_output/tardis-target_files.zip \
        ota_update.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
    

विभाजन को कॉन्फ़िगर करना

update_engine एक ही डिस्क में परिभाषित A/B विभाजन के किसी भी जोड़े को अद्यतन कर सकता है। विभाजन की एक जोड़ी में एक सामान्य उपसर्ग (जैसे system या boot ) और प्रति-स्लॉट प्रत्यय (जैसे _a ) होता है। विभाजनों की सूची जिसके लिए पेलोड जनरेटर एक अद्यतन को परिभाषित करता है, AB_OTA_PARTITIONS मेक वेरिएबल द्वारा कॉन्फ़िगर किया गया है।

उदाहरण के लिए, यदि विभाजन की एक जोड़ी bootloader_a और booloader_b शामिल हैं ( _a और _b स्लॉट प्रत्यय हैं), तो आप उत्पाद या बोर्ड कॉन्फ़िगरेशन पर निम्नलिखित निर्दिष्ट करके इन विभाजनों को अद्यतन कर सकते हैं:

AB_OTA_PARTITIONS := \
  boot \
  system \
  bootloader

update_engine द्वारा अद्यतन किए गए सभी विभाजन शेष सिस्टम द्वारा संशोधित नहीं किए जाने चाहिए। वृद्धिशील या डेल्टा अपडेट के दौरान, वर्तमान स्लॉट से बाइनरी डेटा का उपयोग नए स्लॉट में डेटा उत्पन्न करने के लिए किया जाता है। किसी भी संशोधन के कारण नया स्लॉट डेटा अद्यतन प्रक्रिया के दौरान सत्यापन विफल हो सकता है, और इसलिए अद्यतन विफल हो सकता है।

स्थापना के बाद का विन्यास

आप की-वैल्यू पेयर के सेट का उपयोग करके प्रत्येक अपडेटेड पार्टीशन के लिए पोस्ट-इंस्टॉल चरण को अलग तरीके से कॉन्फ़िगर कर सकते हैं। एक नई छवि में /system/usr/bin/postinst पर स्थित प्रोग्राम चलाने के लिए, सिस्टम विभाजन में फाइल सिस्टम के रूट के सापेक्ष पथ निर्दिष्ट करें।

उदाहरण के लिए, usr/bin/postinst system/usr/bin/postinst (यदि RAM डिस्क का उपयोग नहीं कर रहा है) है। इसके अतिरिक्त, mount(2) सिस्टम कॉल को पास करने के लिए फाइल सिस्टम प्रकार निर्दिष्ट करें। उत्पाद या डिवाइस .mk फ़ाइलों में निम्नलिखित जोड़ें (यदि लागू हो):

AB_OTA_POSTINSTALL_CONFIG += \
  RUN_POSTINSTALL_system=true \
  POSTINSTALL_PATH_system=usr/bin/postinst \
  FILESYSTEM_TYPE_system=ext4

संकलन

सुरक्षा कारणों से, system_server -इन-टाइम (JIT) संकलन का उपयोग नहीं कर सकता। इसका मतलब है कि आपको system_server और इसकी निर्भरता के लिए कम से कम समय से पहले ओडेक्स फाइलों को संकलित करना होगा; कुछ और वैकल्पिक है।

पृष्ठभूमि में ऐप्स को संकलित करने के लिए, आपको उत्पाद के डिवाइस कॉन्फ़िगरेशन (उत्पाद के device.mk में) में निम्नलिखित जोड़ना होगा:

  1. संकलन स्क्रिप्ट और बायनेरिज़ को संकलित और सिस्टम छवि में शामिल करना सुनिश्चित करने के लिए बिल्ड में मूल घटकों को शामिल करें।
      # A/B OTA dexopt package
      PRODUCT_PACKAGES += otapreopt_script
    
  2. संकलन स्क्रिप्ट को update_engine से कनेक्ट करें जैसे कि पोस्ट-इंस्टॉल चरण के रूप में चलता है।
      # A/B OTA dexopt update_engine hookup
      AB_OTA_POSTINSTALL_CONFIG += \
        RUN_POSTINSTALL_system=true \
        POSTINSTALL_PATH_system=system/bin/otapreopt_script \
        FILESYSTEM_TYPE_system=ext4 \
        POSTINSTALL_OPTIONAL_system=true
    

अप्रयुक्त दूसरे सिस्टम विभाजन में पहले से चुनी गई फाइलों को संस्थापित करने में मदद के लिए, DEX_PREOPT फाइलों के पहले बूट अधिष्ठापन का संदर्भ लें .