बिना डाइनैमिक पार्टीशन वाले A/B डिवाइसों के लिए OTA

Android 10 में डाइनैमिक पार्टीशन की सुविधा काम करती है. यह एक यूज़रस्पेस पार्टीशनिंग सिस्टम है. यह सिस्टम, ओवर-द-एयर (OTA) अपडेट के दौरान पार्टीशन बना सकता है, उनका साइज़ बदल सकता है, और उन्हें मिटा सकता है.

इस पेज पर बताया गया है कि अपडेट के दौरान, ओटीए क्लाइंट, ए/बी डिवाइसों के लिए डाइनैमिक पार्टीशन का साइज़ कैसे बदलते हैं. ये ऐसे डिवाइस होते हैं जिन्हें डाइनैमिक पार्टीशन की सुविधा के बिना लॉन्च किया गया था. साथ ही, यह भी बताया गया है कि ओटीए क्लाइंट, Android 10 पर कैसे अपग्रेड करते हैं.

बैकग्राउंड

डाइनैमिक पार्टिशन की सुविधा के साथ काम करने के लिए, किसी A/B डिवाइस को अपडेट करते समय, डिवाइस पर मौजूद GUID पार्टिशन टेबल (GPT) को सुरक्षित रखा जाता है. इसलिए, डिवाइस पर कोई super पार्टिशन नहीं होता. मेटाडेटा, system_a और system_b पर सेव होता है. हालांकि, BOARD_SUPER_PARTITION_METADATA_DEVICE में बदलाव करके इसे अपनी पसंद के मुताबिक बनाया जा सकता है.

हर ब्लॉक डिवाइस में, दो मेटाडेटा स्लॉट होते हैं. हर ब्लॉक डिवाइस में सिर्फ़ एक मेटाडेटा स्लॉट का इस्तेमाल किया जाता है. उदाहरण के लिए, system_a पर मौजूद मेटाडेटा 0 और system_b पर मौजूद मेटाडेटा 1, क्रमशः A और B स्लॉट पर मौजूद पार्टीशन से मेल खाता है. रनटाइम के दौरान, इससे कोई फ़र्क़ नहीं पड़ता कि कौनसा स्लॉट अपडेट किया जा रहा है.

इस पेज पर, मेटाडेटा स्लॉट को मेटाडेटा S (सोर्स) और मेटाडेटा T (टारगेट) कहा जाता है. इसी तरह, पार्टिशन को system_s, vendor_t वगैरह के तौर पर दिखाया जाता है.

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

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

किसी डिवाइस पर मेटाडेटा का उदाहरण:

  • फ़िज़िकल ब्लॉक डिवाइस system_a
    • मेटाडेटा 0
      • ग्रुप foo_a
        • लॉजिकल (डाइनैमिक) पार्टिशन system_a
        • लॉजिकल (डाइनैमिक) पार्टिशन product_services_a
        • Foo ने अन्य पार्टिशन अपडेट किए
      • ग्रुप bar_a
        • लॉजिकल (डाइनैमिक) पार्टिशन vendor_a
        • लॉजिकल (डाइनैमिक) पार्टिशन product_a
        • Bar ने अन्य पार्टीशन अपडेट किए
    • मेटाडेटा 1 (इस्तेमाल नहीं किया गया)
  • फ़िज़िकल ब्लॉक डिवाइस system_b
    • मेटाडेटा 0 (इस्तेमाल नहीं किया गया)
    • मेटाडेटा 1
      • Group foo_b
        • लॉजिकल (डाइनैमिक) पार्टिशन system_b
        • लॉजिकल (डाइनैमिक) पार्टिशन product_services_b
        • Foo ने अन्य पार्टिशन अपडेट किए
      • ग्रुप बार_b
        • लॉजिकल (डाइनैमिक) पार्टिशन vendor_b
        • लॉजिकल (डाइनैमिक) पार्टिशन product_b
        • Bar ने अन्य पार्टीशन अपडेट किए

अपने डिवाइस पर मेटाडेटा डंप करने के लिए, system/extras/partition_tools में जाकर lpdump टूल का इस्तेमाल करें. उदाहरण के लिए:

lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b

अपडेट को पहले जैसा करना

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

ओटीए जनरेटर, फ़ाइनल super.img फ़ाइल बनाता है. इसमें सभी डाइनैमिक पार्टीशन का कॉन्टेंट होता है. इसके बाद, यह इमेज को सिस्टम, वेंडर वगैरह से जुड़े फ़िज़िकल ब्लॉक डिवाइसों के साइज़ के हिसाब से कई इमेज में बांटता है. इन इमेज के नाम super_system.img, super_vendor.img वगैरह हैं. OTA क्लाइंट, इन इमेज को लॉजिकल (डाइनैमिक) पार्टीशन के बजाय, फ़िज़िकल पार्टीशन पर लागू करता है.

ओटीए क्लाइंट को डाइनैमिक पार्टीशन को मैप करने का तरीका नहीं पता होता. इसलिए, अपडेट पैकेज जनरेट होने पर, इन पार्टीशन के लिए इंस्टॉल के बाद के सभी चरण अपने-आप बंद हो जाते हैं. ज़्यादा जानकारी के लिए, ऐप्लिकेशन इंस्टॉल होने के बाद कॉन्फ़िगर करना लेख पढ़ें.

अपडेट करने का तरीका, Android 9 में इस्तेमाल किए जाने वाले तरीके जैसा ही है.

अपडेट से पहले:

ro.boot.dynamic_partitions=
ro.boot.dynamic_partitions_retrofit=

अपडेट के बाद:

ro.boot.dynamic_partitions=true
ro.boot.dynamic_partitions_retrofit=true

रेट्रोफ़िट करने के बाद आने वाले अपडेट

रेट्रोफ़िट अपडेट के बाद, OTA क्लाइंट को डाइनैमिक पार्टीशन के साथ काम करने के लिए अपडेट किया जाता है. सोर्स पार्टीशन के एक्सटेंट कभी भी टारगेट फ़िज़िकल पार्टीशन में नहीं होते.

अपडेट करने वाले सामान्य पैकेज का इस्तेमाल करके अपडेट करने की प्रोसेस

  1. super पार्टीशन के मेटाडेटा को शुरू करें.
    1. मेटाडेटा एस (सोर्स मेटाडेटा) से नया मेटाडेटा एम बनाएं. उदाहरण के लिए, अगर मेटाडेटा S, ब्लॉक किए गए डिवाइसों के तौर पर [system_s, vendor_s, product_s] का इस्तेमाल करता है, तो नया मेटाडेटा M, ब्लॉक किए गए डिवाइसों के तौर पर [system_t, vendor_t, product_t] का इस्तेमाल करता है. एम में सभी ग्रुप और पार्टीशन हटा दिए जाते हैं.
    2. अपडेट मेनिफ़ेस्ट में मौजूद dynamic_partition_metadata फ़ील्ड के हिसाब से, टारगेट ग्रुप और पार्टीशन जोड़ें. हर पार्टीशन का साइज़ new_partition_info में देखा जा सकता है.
    3. मेटाडेटा टी में एम लिखो.
    4. डिवाइस मैपर पर जोड़े गए पार्टीशन को लिखने के तौर पर मैप करें.
  2. ब्लॉक किए गए डिवाइसों पर अपडेट लागू करें.
    1. अगर ज़रूरी हो, तो डिवाइस मैपर पर सोर्स पार्टीशन को सिर्फ़ पढ़ने के लिए मैप करें. साइडलोडिंग के लिए यह ज़रूरी है, क्योंकि अपडेट से पहले सोर्स पार्टीशन मैप नहीं किए जाते.
    2. टारगेट स्लॉट पर मौजूद सभी ब्लॉक डिवाइसों पर, पूरा या डेल्टा अपडेट लागू करें.
    3. पोस्ट-इंस्टॉल स्क्रिप्ट चलाने के लिए, पार्टिशन को माउंट करें. इसके बाद, पार्टिशन को अनमाउंट करें.
  3. टारगेट किए गए पार्टीशन को अनमैप करें.

अपडेट करने वाले रेट्रोफ़िट पैकेज का इस्तेमाल करके अपडेट करने की प्रोसेस

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

उदाहरण के लिए, मान लें कि:

  • स्लॉट A चालू है.
  • system_a में स्लॉट 0 पर मौजूद चालू मेटाडेटा शामिल होता है.
  • system_a, vendor_a, और product_a का इस्तेमाल ब्लॉक डिवाइस के तौर पर किया जाता है.

जब OTA क्लाइंट को रेट्रोफ़िट अपडेट पैकेज मिलता है, तो वह इसे फ़िज़िकल system_b पर super_system.img, फ़िज़िकल vendor_b पर super_vendor.img, और फ़िज़िकल product_b पर super_product.img लागू करता है. फ़िज़िकल ब्लॉक डिवाइस system_b में सही मेटाडेटा होता है. इससे बूट होने के समय लॉजिकल system_b, vendor_b, और product_b को मैप किया जा सकता है.

अपडेट पैकेज जनरेट करना

इंक्रीमेंटल ओटीए

रेट्रोफ़िट डिवाइसों के लिए इंक्रीमेंटल ओटीए जनरेट करते समय, अपडेट इस बात पर निर्भर करते हैं कि बेस बिल्ड में PRODUCT_USE_DYNAMIC_PARTITIONS और PRODUCT_RETROFIT_DYNAMIC_PARTITIONS तय किया गया है या नहीं.

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

फ़ुल ओटीए

रेट्रोफ़िट डिवाइसों के लिए, दो फ़ुल ओटीए पैकेज जनरेट किए जाते हैं.

  • $(PRODUCT)-ota-retrofit-$(TAG).zip में हमेशा स्प्लिट super.img होता है. साथ ही, यह अपडेट को रेट्रोफ़िट करने के लिए, इंस्टॉल करने के बाद के चरण को बंद कर देता है.
    • इसे ota_from_target_files स्क्रिप्ट में --retrofit_dynamic_partitions आर्ग्युमेंट जोड़कर जनरेट किया जाता है.
    • इसे सभी बिल्ड पर लागू किया जा सकता है.
  • $(PRODUCT)-ota-$(TAG).zip में आने वाले समय के अपडेट के लिए, तार्किक इमेज शामिल हैं.
    • इसे सिर्फ़ उन बिल्ड पर लागू करें जिनमें डाइनैमिक पार्टिशन की सुविधा चालू है. इसे लागू करने के बारे में यहां जानकारी दी गई है.

पुरानी बिल्ड पर, नॉनरेट्रोफ़िट अपडेट को अस्वीकार करें

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

डिवाइस को पूरा ओटीए पैकेज स्वीकार करने से रोकने के लिए, यह ज़रूरी किया जा सकता है कि इंस्टॉल करने के बाद, डिवाइस के मौजूदा कॉन्फ़िगरेशन की जांच की जाए. उदाहरण के लिए:

device/device_name/dynamic_partitions/check_dynamic_partitions

#!/system/bin/sh
DP_PROPERTY_NAME="ro.boot.dynamic_partitions"
DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit"

DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME})
DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME})

if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then
    echo "Error: applied non-retrofit update on build without dynamic" \
         "partitions."
    echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}"
    echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}"
    exit 1
fi

device/device_name/dynamic_partitions/Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= check_dynamic_partitions
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := check_dynamic_partitions
LOCAL_PRODUCT_MODULE := true
include $(BUILD_PREBUILT)

device/device_name/device.mk

PRODUCT_PACKAGES += check_dynamic_partitions

# OPTIONAL=false so that the error in check_dynamic_partitions will be
# propagated to OTA client.
AB_OTA_POSTINSTALL_CONFIG += \
    RUN_POSTINSTALL_product=true \
    POSTINSTALL_PATH_product=bin/check_dynamic_partitions \
    FILESYSTEM_TYPE_product=ext4 \
    POSTINSTALL_OPTIONAL_product=false \

जब डाइनैमिक पार्टिशन की सुविधा के बिना किसी डिवाइस पर सामान्य OTA पैकेज लागू किया जाता है, तो OTA क्लाइंट, check_dynamic_partitions को इंस्टॉल करने के बाद के चरण के तौर पर चलाता है और अपडेट को अस्वीकार कर देता है.