वर्चुअल A/B लागू करना

किसी नए डिवाइस पर वर्चुअल ए/बी टेस्टिंग लागू करने या लॉन्च किए गए डिवाइस में इसे फिर से लागू करने के लिए, आपको डिवाइस के हिसाब से कोड में बदलाव करना होगा.

फ़्लैग बनाना

वर्चुअल A/B का इस्तेमाल करने वाले डिवाइसों को A/B डिवाइस के तौर पर कॉन्फ़िगर किया जाना चाहिए. साथ ही, उन्हें डाइनैमिक पार्टीशन के साथ लॉन्च किया जाना चाहिए.

वर्चुअल A/B के साथ लॉन्च होने वाले डिवाइसों के लिए, उन्हें वर्चुअल A/B डिवाइस के बेस कॉन्फ़िगरेशन को इनहेरिट करने के लिए सेट करें:

$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)

वर्चुअल A/B की सुविधा के साथ लॉन्च होने वाले डिवाइसों को BOARD_SUPER_PARTITION_SIZE के लिए, बोर्ड के साइज़ की सिर्फ़ आधी जगह की ज़रूरत होती है. ऐसा इसलिए, क्योंकि B स्लॉट अब सुपर में नहीं हैं. इसका मतलब है कि BOARD_SUPER_PARTITION_SIZE, अपडेट ग्रुप के साइज़ का योग + ओवरहेड से ज़्यादा या उसके बराबर होना चाहिए. साथ ही, अपडेट ग्रुप के साइज़ का योग + ओवरहेड, पार्टिशन के साइज़ का योग + ओवरहेड से ज़्यादा या उसके बराबर होना चाहिए.

Android 13 और इसके बाद के वर्शन के लिए, Virtual A/B की मदद से कंप्रेस किए गए स्नैपशॉट चालू करने के लिए, इस बेस कॉन्फ़िगरेशन को इनहेरिट करें:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk)

इससे, नो-ऑप कंप्रेस करने के तरीके का इस्तेमाल करते समय, वर्चुअल A/B के साथ यूज़रस्पेस स्नैपशॉट चालू हो जाते हैं. इसके बाद,कंप्रेस करने के तरीके को इनमें से किसी एक तरीके पर कॉन्फ़िगर किया जा सकता है:zstd और lz4. Android 15 में, डिवाइस की ज़रूरतों के हिसाब से कंप्रेस करने की सुविधा को और भी ज़्यादा पसंद के मुताबिक बनाया जा सकता है. ज़्यादा जानकारी के लिए, कंप्रेशन को बेहतर बनाना लेख पढ़ें.

PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4
PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Android 12 के लिए, Virtual A/B के साथ कंप्रेस किए गए स्नैपशॉट चालू करने के लिए, इस बुनियादी कॉन्फ़िगरेशन को इनहेरिट करें:

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
$(call inherit-product, \
    $(SRC_TARGET_DIR)/product/virtual_ab_ota/compression.mk)

XOR कंप्रेस करने की सुविधा

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

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true

XOR कंप्रेशन की सुविधा, उन डिवाइसों के लिए डिफ़ॉल्ट रूप से चालू होती है जो android_t_baseline.mk से इनहेरिट करते हैं.

Userspace merge

Virtual A/B के नए वर्शन (Android T और इसके बाद के वर्शन) में, स्नैपशॉट मर्ज करने की प्रोसेस पूरी तरह से यूज़रस्पेस में होती है. यह बदलाव snapuserd और dm-user की वजह से हुआ है. Android 13 और इसके बाद के वर्शन के साथ लॉन्च होने वाले डिवाइसों पर, userspace merge की सुविधा डिफ़ॉल्ट रूप से चालू होती है. पुराने डिवाइसों को अपग्रेड करने के लिए, इस प्रॉपर्टी को इस तरह सेट किया जा सकता है:

PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true

बूट कंट्रोल एचएएल

बूट कंट्रोल एचएएल, ओटीए क्लाइंट के लिए एक इंटरफ़ेस उपलब्ध कराता है. इसकी मदद से, बूट स्लॉट को कंट्रोल किया जा सकता है. वर्चुअल ए/बी के लिए, बूट कंट्रोल HAL के माइनर वर्शन को अपग्रेड करना ज़रूरी है. ऐसा इसलिए, क्योंकि फ़्लैश करने या फ़ैक्ट्री रीसेट करने के दौरान बूटलोडर को सुरक्षित रखने के लिए, अतिरिक्त एपीआई की ज़रूरत होती है. HAL की परिभाषा के सबसे नए वर्शन के लिए, IBootControl.hal और types.hal देखें.

// hardware/interfaces/boot/1.1/types.hal
enum MergeStatus : uint8_t {
    NONE, UNKNOWN, SNAPSHOTTED, MERGING, CANCELLED };

// hardware/interfaces/boot/1.1/IBootControl.hal
package android.hardware.boot@1.1;
interface IBootControl extends @1.0::IBootControl {
    setSnapshotMergeStatus(MergeStatus status)
        generates (bool success);
    getSnapshotMergeStatus()
        generates (MergeStatus status);
}
// Recommended implementation

Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus v) {
    // Write value to persistent storage
    // e.g. misc partition (using libbootloader_message)
    // bootloader rejects wipe when status is SNAPSHOTTED
    // or MERGING
}

Fstab में बदलाव

बूट प्रोसेस के लिए, मेटाडेटा पार्टिशन की इंटिग्रिटी ज़रूरी है. खास तौर पर, ओटीए अपडेट लागू होने के तुरंत बाद. इसलिए, first_stage_init के मेटाडेटा को माउंट करने से पहले, उसकी जांच की जानी चाहिए. इसके लिए, /metadata की एंट्री में check fs_mgr फ़्लैग जोड़ें. यहां एक उदाहरण दिया गया है:

/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount,check

कर्नेल से जुड़ी ज़रूरी शर्तें

स्नैपशॉट लेने की सुविधा चालू करने के लिए, CONFIG_DM_SNAPSHOT को true पर सेट करें.

F2FS का इस्तेमाल करने वाले डिवाइसों के लिए, f2fs: export FS_NOCOW_FL flag to user कर्नल पैच शामिल करें, ताकि फ़ाइल पिन करने की समस्या को ठीक किया जा सके. f2fs: support aligned pinned file कर्नल पैच भी शामिल करें.

वर्चुअल A/B, कर्नल के वर्शन 4.3 में जोड़ी गई सुविधाओं पर निर्भर करता है: snapshot और snapshot-merge टारगेट में ओवरफ़्लो स्टेटस बिट. Android 9 और इसके बाद के वर्शन के साथ लॉन्च होने वाले सभी डिवाइसों में, कर्नेल का वर्शन 4.4 या इसके बाद का होना चाहिए.

कंप्रेस किए गए स्नैपशॉट की सुविधा चालू करने के लिए, कर्नेल का कम से कम 4.19 वर्शन होना ज़रूरी है. CONFIG_DM_USER=m या CONFIG_DM_USER=y पर सेट करें. अगर पहले तरीके (मॉड्यूल) का इस्तेमाल किया जा रहा है, तो मॉड्यूल को पहले चरण के रैमडिस्क में लोड किया जाना चाहिए. इसके लिए, डिवाइस की Makefile में यह लाइन जोड़ें:

BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD := dm-user.ko

फ़ास्टबूट टूलिंग में बदलाव

Android 11 में, फ़ास्टबूट प्रोटोकॉल में ये बदलाव किए गए हैं:

  • getvar snapshot-update-status — यह बूट कंट्रोल HAL से बूटलोडर को मिली वैल्यू दिखाता है:
    • अगर स्थिति MERGING है, तो बूटलोडर को merging वैल्यू रिटर्न करनी होगी.
    • अगर स्थिति SNAPSHOTTED है, तो बूटलोडर को snapshotted वैल्यू रिटर्न करनी होगी.
    • अगर ऐसा नहीं है, तो बूटलोडर को none दिखाना होगा.
  • snapshot-update merge — इससे मर्ज करने की प्रोसेस पूरी होती है. अगर ज़रूरी हो, तो डिवाइस को रिकवरी/फ़ास्टबूट मोड में बूट किया जाता है. यह कमांड सिर्फ़ तब मान्य होती है, जब snapshot-update-status को merging पर सेट किया गया हो. साथ ही, यह सिर्फ़ fastbootd में काम करती है.
  • snapshot-update cancel — इससे बूट कंट्रोल HAL के मर्ज स्टेटस को CANCELLED पर सेट किया जाता है. डिवाइस लॉक होने पर, इस कमांड का इस्तेमाल नहीं किया जा सकता.
  • erase या wipemetadata, userdata या बूट कंट्रोल HAL के लिए मर्ज स्टेटस रखने वाले पार्टीशन का erase या wipe, स्नैपशॉट मर्ज स्टेटस की जांच करेगा. अगर स्थिति MERGING या SNAPSHOTTED है, तो डिवाइस को कार्रवाई बंद कर देनी चाहिए.
  • set_active — चालू स्लॉट को बदलने वाली set_active कमांड को स्नैपशॉट मर्ज करने की स्थिति की जांच करनी चाहिए. अगर स्थिति MERGING है, तो डिवाइस को कार्रवाई बंद कर देनी चाहिए. स्लॉट को SNAPSHOTTED स्थिति में सुरक्षित तरीके से बदला जा सकता है.

इन बदलावों को इसलिए डिज़ाइन किया गया है, ताकि डिवाइस को बूट न किया जा सके. हालांकि, ये बदलाव ऑटोमेटेड टूलिंग में रुकावट डाल सकते हैं. जब सभी पार्टीशन को फ़्लैश करने के कॉम्पोनेंट के तौर पर कमांड का इस्तेमाल किया जाता है, जैसे कि fastboot flashall चलाना, तो हमारा सुझाव है कि आप यह तरीका अपनाएं:

  1. क्वेरी getvar snapshot-update-status.
  2. अगर merging या snapshotted, तो snapshot-update cancel जारी करें.
  3. फ़्लैश करने की प्रोसेस जारी रखें.

स्टोरेज की ज़रूरत को कम करना

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

ओटीए कंप्रेस करने के एल्गोरिदम

ओटीए पैकेज को अलग-अलग परफ़ॉर्मेंस मेट्रिक के लिए ट्यून किया जा सकता है. Android, कंप्रेस करने के कई तरीके (lz4, zstd, और none) उपलब्ध कराता है. इनमें इंस्टॉल होने में लगने वाला समय, सीओडब्ल्यू स्पेस का इस्तेमाल, बूट होने में लगने वाला समय, और स्नैपशॉट मर्ज होने में लगने वाले समय के बीच समझौता किया जाता है. कंप्रेशन के साथ वर्चुअल अब के लिए, डिफ़ॉल्ट रूप से lz4 compression method विकल्प चालू होता है.

कंप्रेशन को फ़ाइन ट्यून करना

कॉन्टेंट को कंप्रेस करने वाले एल्गोरिदम को दो तरीकों से और भी ज़्यादा पसंद के मुताबिक बनाया जा सकता है: (कंप्रेशन लेवल) (स्पीड के बदले में हासिल किया गया कंप्रेशन) और (कंप्रेशन फ़ैक्टर) (कंप्रेस की जा सकने वाली विंडो का ज़्यादा से ज़्यादा साइज़). कॉन्टेंट को कंप्रेस करने का लेवल, कुछ एल्गोरिदम के लिए उपलब्ध होता है. जैसे, zstd. लेवल बदलने पर, स्पीड और कंप्रेशन अनुपात के बीच समझौता करना पड़ता है. कंप्रेशन फ़ैक्टर से पता चलता है कि ओटीए इंस्टॉलेशन के दौरान, कंप्रेस करने के लिए इस्तेमाल की गई विंडो का ज़्यादा से ज़्यादा साइज़ क्या है. डिफ़ॉल्ट रूप से, इसकी वैल्यू 64 के पर सेट होती है. हालांकि, इसे बिल्ड पैरामीटर PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR को पसंद के मुताबिक बनाकर बदला जा सकता है. 4K, 8K, 16K, 32K, 64K, 128K, और 256K के साथ काम करता है.

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Pixel 8 Pro पर इंक्रीमेंटल ओटीए

पोस्ट इंस्टॉल फ़ेज़ के बिना इंस्टॉल होने में लगा समय सीओडब्ल्यू स्पेस का इस्तेमाल ओटीए के बाद डिवाइस को चालू होने में लगने वाला समय स्नैपशॉट मर्ज करने का समय
lz4 18 मिनट 15 सेकंड 2.5 जीबी 32.7 सेकंड 98.6 सेकंड
zstd 24 मिनट 49 सेकंड 2.05 जीबी 36.3 सेकंड 133.2 सेकंड
कोई नहीं 16 मिनट 42 सेकंड 4.76 जीबी 28.7 सेकंड 76.6 सेकंड

Pixel 8 Pro पर पूरा ओटीए

पोस्ट इंस्टॉल फ़ेज़ के बिना इंस्टॉल होने में लगा समय सीओडब्ल्यू स्पेस का इस्तेमाल ओटीए के बाद डिवाइस को चालू होने में लगने वाला समय स्नैपशॉट मर्ज करने का समय
lz4 15 मिनट 11 सेकंड 4.16 जीबी 17.6 सेकंड 82.2 सेकंड
zstd 16 मिनट 19 सेकंड 3.46 जीबी 21.0 सेकंड 106.3 सेकंड
कोई नहीं 13 मिनट 33 सेकंड 6.39 जीबी 18.5 सेकंड 92.5 सेकंड