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

नए डिवाइस पर वर्चुअल 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 और इसके बाद के वर्शन वाले डिवाइसों पर, वर्चुअल 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 वाले डिवाइसों पर, वर्चुअल 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

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

यूज़रस्पेस मर्ज

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

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

बूट कंट्रोल HAL

बूट कंट्रोल HAL, OTA क्लाइंट को बूट स्लॉट कंट्रोल करने के लिए एक इंटरफ़ेस उपलब्ध कराता है. वर्चुअल A/B के लिए, बूट कंट्रोल 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 में बदलाव

मेटाडेटा पार्टिशन की इंटिग्रिटी, बूट प्रोसेस के लिए ज़रूरी है. खास तौर पर, OTA अपडेट लागू होने के तुरंत बाद. इसलिए, 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 फ़्लैग को उपयोगकर्ता कर्नेल पैच में शामिल करें. f2fs: support aligned pinned file कर्नेल पैच भी शामिल करें.

वर्चुअल A/B, कर्नेल वर्शन 4.3 में जोड़ी गई सुविधाओं पर निर्भर करता है. जैसे, overflow स्टेटस बिट 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 हो. साथ ही, यह सिर्फ़ फ़ास्टबूटड में काम करता है.
  • snapshot-update cancel — यह बूट कंट्रोल HAL के मर्ज स्टेटस को CANCELLED पर सेट करता है. डिवाइस लॉक होने पर, यह कमांड मान्य नहीं होता.
  • erase या wipemetadata, userdata को मिटाने या साफ़ करने के लिए, erase या wipe कमांड का इस्तेमाल किया जाता है. इसके अलावा, बूट कंट्रोल HAL के लिए मर्ज स्टेटस वाले पार्टिशन को मिटाने या साफ़ करने के लिए भी इन कमांड का इस्तेमाल किया जाता है. इन कमांड का इस्तेमाल करने पर, स्नैपशॉट मर्ज स्टेटस की जांच की जानी चाहिए. अगर स्टेटस MERGING या SNAPSHOTTED है, तो डिवाइस को यह कार्रवाई रोक देनी चाहिए.
  • set_activeset_active कमांड, ऐक्टिव स्लॉट को बदलता है. इस कमांड का इस्तेमाल करने पर, स्नैपशॉट मर्ज स्टेटस की जांच की जानी चाहिए. अगर स्टेटस MERGING है, तो डिवाइस को यह कार्रवाई रोक देनी चाहिए. SNAPSHOTTED स्थिति में, स्लॉट को सुरक्षित तरीके से बदला जा सकता है.

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

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

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

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

OTA कंप्रेस करने के एल्गोरिदम

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

कंप्रेस करने की सुविधा को बेहतर बनाना

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

PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 65536

Pixel 8 Pro पर, इंक्रीमेंटल OTA

पोस्ट-इंस्टॉल फ़ेज़ के बिना इंस्टॉल होने में लगने वाला समय COW स्पेस का इस्तेमाल OTA के बाद बूट होने में लगने वाला समय स्नैपशॉट मर्ज होने में लगने वाला समय
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 पर, पूरा OTA

पोस्ट-इंस्टॉल फ़ेज़ के बिना इंस्टॉल होने में लगने वाला समय COW स्पेस का इस्तेमाल OTA के बाद बूट होने में लगने वाला समय स्नैपशॉट मर्ज होने में लगने वाला समय
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 सेकंड