डाइनैमिक पार्टिशनिंग को लागू करने के लिए, Linux kernel में dm-linear डिवाइस-मैपर
मॉड्यूल का इस्तेमाल किया जाता है. super
पार्टीशन में
मेटाडेटा शामिल है, जिसमें super
में मौजूद हर डाइनैमिक पार्टीशन
के नाम और ब्लॉक रेंज की जानकारी होती है. पहले चरण के init
के दौरान, इस मेटाडेटा को पार्स करके उसकी पुष्टि की जाती है. साथ ही, हर डाइनैमिक पार्टीशन को दिखाने के लिए वर्चुअल ब्लॉक डिवाइस बनाए जाते हैं.
ओटीए लागू करने पर, डाइनैमिक पार्टिशन अपने-आप बन जाते हैं, ज़रूरत के हिसाब से उनका साइज़ बदल जाता है या उन्हें मिटा दिया जाता है. A/B डिवाइसों के लिए, मेटाडेटा की दो कॉपी होती हैं. साथ ही, बदलाव सिर्फ़ उस कॉपी पर लागू होते हैं जो टारगेट स्लॉट को दिखाती है.
डाइनैमिक पार्टीशन, यूज़रस्पेस में लागू किए जाते हैं. इसलिए, बूटलोडर के लिए ज़रूरी पार्टीशन को डाइनैमिक नहीं बनाया जा सकता. उदाहरण के लिए, boot
,
dtbo
, और vbmeta
को बूटलोडर पढ़ता है. इसलिए, इन्हें फ़िज़िकल पार्टीशन के तौर पर ही रखना चाहिए.
हर डाइनैमिक पार्टीशन, किसी अपडेट ग्रुप से जुड़ा हो सकता है. ये ग्रुप, उस ग्रुप में मौजूद पार्टीशन के लिए इस्तेमाल किए जा सकने वाले स्टोरेज की सीमा तय करते हैं.
उदाहरण के लिए, system
और vendor
, ऐसे ग्रुप के हो सकते हैं जो system
और vendor
के कुल साइज़ पर पाबंदी लगाता है.
नए डिवाइसों पर डाइनैमिक पार्टीशन लागू करना
इस सेक्शन में Android 10 और उसके बाद के वर्शन के साथ लॉन्च होने वाले नए डिवाइसों में, डाइनैमिक पार्टिशन लागू करने का तरीका बताया गया है. मौजूदा डिवाइसों को अपडेट करने के लिए, Android डिवाइसों को अपग्रेड करना लेख पढ़ें.
पार्टीशन में बदलाव
Android 10 के साथ लॉन्च होने वाले डिवाइसों के लिए, super
नाम का एक partition बनाएं. super
पार्टीशन, A/B स्लॉट को अंदरूनी तौर पर मैनेज करता है. इसलिए, A/B डिवाइसों को
अलग से super_a
और super_b
पार्टीशन की ज़रूरत नहीं होती.
रीड-ओनली AOSP वाले सभी ऐसे पार्टीशन, जिन्हें बूटलोडर इस्तेमाल नहीं करता, डाइनैमिक होने चाहिए. साथ ही, उन्हें GUID पार्टीशन टेबल (GPT) से हटा दिया जाना चाहिए.
वेंडर के हिसाब से बने पार्टीशन, डाइनैमिक होने ज़रूरी नहीं हैं. साथ ही, इन्हें जीपीटी में रखा जा सकता है.
super
के साइज़ का अनुमान लगाने के लिए, GPT से मिटाए जा रहे हिस्सों के साइज़ जोड़ें. A/B डिवाइसों के लिए, इसमें दोनों स्लॉट का साइज़ शामिल होना चाहिए. पहली इमेज में, डाइनैमिक पार्टिशन में बदलने से पहले और बाद की,
पार्टिशन टेबल का उदाहरण दिखाया गया है.
इस्तेमाल किए जा सकने वाले डाइनैमिक पार्टीशन हैं:
- सिस्टम
- वेंडर
- प्रॉडक्ट
- सिस्टम एक्सटेंशन
- ओडीएम
Android 10 के साथ लॉन्च होने वाले डिवाइसों के लिए,
कर्नल कमांड लाइन का विकल्प androidboot.super_partition
खाली होना चाहिए, ताकि कमांड sysprop
ro.boot.super_partition
खाली हो.
सेगमेंट का अलाइनमेंट
अगर super
पार्टीशन को सही तरीके से अलाइन नहीं किया गया है, तो हो सकता है कि डिवाइस-मैपर मॉड्यूल कम असरदार तरीके से काम करे. super
partition को कम से कम I/O अनुरोध के साइज़ के हिसाब से अलाइन करना ज़रूरी है. यह साइज़, ब्लॉक लेयर तय करती है. डिफ़ॉल्ट रूप से,
बिल्ड सिस्टम (lpmake
के ज़रिए, जो
super
पार्टिशन इमेज जनरेट करता है) को यह मानता है कि हर डाइनैमिक पार्टीशन के लिए
एक एमआईबी अलाइनमेंट काफ़ी होगा. हालांकि, वेंडर को यह पक्का करना चाहिए कि super
पार्टीशन सही तरीके से अलाइन हो.
sysfs
की जांच करके, ब्लॉक किए गए डिवाइस के लिए अनुरोध का कम से कम साइज़ तय किया जा सकता है. उदाहरण के लिए:
# ls -l /dev/block/by-name/super lrwxrwxrwx 1 root root 16 1970-04-05 01:41 /dev/block/by-name/super -> /dev/block/sda17 # cat /sys/block/sda/queue/minimum_io_size 786432
super
पार्टीशन के अलाइनमेंट की पुष्टि इसी तरह से की जा सकती है:
# cat /sys/block/sda/sda17/alignment_offset
अलाइनमेंट ऑफ़सेट 0 होना चाहिए.
डिवाइस कॉन्फ़िगरेशन में बदलाव
डाइनैमिक पार्टिशनिंग की सुविधा चालू करने के लिए, device.mk
में यह फ़्लैग जोड़ें:
PRODUCT_USE_DYNAMIC_PARTITIONS := true
बोर्ड के कॉन्फ़िगरेशन में बदलाव
आपको super
पार्टीशन का साइज़ सेट करना होगा:
BOARD_SUPER_PARTITION_SIZE := <size-in-bytes>
A/B डिवाइसों पर, अगर डाइनैमिक पार्टीशन इमेज का कुल साइज़, super
पार्टीशन के साइज़ के आधे से ज़्यादा है, तो बिल्ड सिस्टम गड़बड़ी का मैसेज दिखाता है.
डाइनैमिक पार्टीशन की सूची को इस तरह कॉन्फ़िगर किया जा सकता है. अपडेट ग्रुप का इस्तेमाल करने वाले डिवाइसों के लिए, BOARD_SUPER_PARTITION_GROUPS
वैरिएबल में ग्रुप की सूची बनाएं. इसके बाद, हर ग्रुप के नाम में BOARD_group_SIZE
और BOARD_group_PARTITION_LIST
वैरिएबल होता है.
A/B डिवाइसों के लिए, किसी ग्रुप का ज़्यादा से ज़्यादा साइज़ सिर्फ़ एक स्लॉट का होना चाहिए, क्योंकि ग्रुप के नाम में स्लॉट-सर्फ़िक्स शामिल होता है.
यहां एक डिवाइस का उदाहरण दिया गया है, जो सभी सेक्शन को example_dynamic_partitions
नाम के ग्रुप में रखता है:
BOARD_SUPER_PARTITION_GROUPS := example_dynamic_partitions BOARD_EXAMPLE_DYNAMIC_PARTITIONS_SIZE := 6442450944 BOARD_EXAMPLE_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product
यहां एक डिवाइस का उदाहरण दिया गया है, जिसमें सिस्टम और प्रॉडक्ट की सेवाओं को group_foo
में और vendor
, product
, और odm
को group_bar
में रखा गया है:
BOARD_SUPER_PARTITION_GROUPS := group_foo group_bar BOARD_GROUP_FOO_SIZE := 4831838208 BOARD_GROUP_FOO_PARTITION_LIST := system product_services BOARD_GROUP_BAR_SIZE := 1610612736 BOARD_GROUP_BAR_PARTITION_LIST := vendor product odm
-
वर्चुअल A/B लॉन्च डिवाइसों के लिए, सभी ग्रुप के ज़्यादा से ज़्यादा साइज़ का योग, सबसे ज़्यादा इतना होना चाहिए:
BOARD_SUPER_PARTITION_SIZE
- ओवरहेड
वर्चुअल A/B लागू करना देखें. -
A/B लॉन्च डिवाइसों के लिए, सभी ग्रुप के ज़्यादा से ज़्यादा साइज़ का योग,
यह होना चाहिए:
BOARD_SUPER_PARTITION_SIZE
/ 2 - ओवरहेड -
A/B टेस्टिंग के लिए न बनाए गए डिवाइसों और A/B टेस्टिंग के लिए बनाए गए डिवाइसों के लिए, सभी ग्रुप के ज़्यादा से ज़्यादा साइज़ का योग:
BOARD_SUPER_PARTITION_SIZE
- ओवरहेड होना चाहिए - बिल्ड के दौरान, अपडेट किए गए किसी ग्रुप में, हर सेगमेंट की इमेज का कुल साइज़, ग्रुप के साइज़ से ज़्यादा नहीं होना चाहिए.
- मेटाडेटा, अलाइनमेंट वगैरह का हिसाब लगाने के लिए, कैलकुलेशन में ओवरहेड की ज़रूरत होती है. एक उचित ओवरहेड 4 MiB का है, लेकिन डिवाइस के हिसाब से आप इससे बड़ा ओवरहेड चुन सकते हैं.
डाइनैमिक पार्टीशन का साइज़
डाइनैमिक पार्टीशन की सुविधा से पहले, पार्टीशन के साइज़ को ज़्यादा सेट किया जाता था, ताकि आने वाले समय में अपडेट करने के लिए ज़रूरत के मुताबिक जगह हो. असल साइज़ को वैसे ही लिया गया था और ज़्यादातर सिर्फ़ पढ़ने के लिए बने partition के फ़ाइल सिस्टम में कुछ जगह खाली थी. डाइनैमिक पार्टीशन में, उस खाली जगह का इस्तेमाल नहीं किया जा सकता. हालांकि, ओटीए (ओवर-द-एयर) के दौरान, पार्टीशन को बड़ा करने के लिए इसका इस्तेमाल किया जा सकता है. यह पक्का करना ज़रूरी है कि सेगमेंट में जगह को बर्बाद न करें और तय किए गए कम से कम साइज़ के लिए तय किया गया हो.
रीड-ओनली ext4 इमेज के लिए, अगर हार्डकोड किए गए पार्टिशन का कोई साइज़ तय नहीं किया गया है, तो बिल्ड सिस्टम अपने-आप कम से कम साइज़ बांट देता है. बिल्ड सिस्टम इमेज को फ़िट कर देता है, ताकि फ़ाइल सिस्टम में बची हुई जगह कम से कम इस्तेमाल हो. इससे यह पक्का होता है कि डिवाइस में ओटीए के लिए इस्तेमाल किया जा सकने वाला स्टोरेज व्यर्थ न हो.
इसके अलावा, ब्लॉक- लेवल पर डुप्लीकेट कॉपी हटाने की सुविधा चालू करके, ext4 इमेज को और भी ज़्यादा कंप्रेस किया जा सकता है. इसे चालू करने के लिए, नीचे दिए गए कॉन्फ़िगरेशन का इस्तेमाल करें:
BOARD_EXT4_SHARE_DUP_BLOCKS := true
अगर आपको पार्टीशन का कम से कम साइज़ अपने-आप तय होने की सुविधा नहीं चाहिए, तो
पार्टीशन का साइज़ कंट्रोल करने के दो तरीके हैं. BOARD_partitionIMAGE_PARTITION_RESERVED_SIZE
की मदद से, डिवाइस में कम से कम खाली जगह तय की जा सकती है. इसके अलावा, डायनैमिक पार्टिशन को किसी खास साइज़ पर सेट करने के लिए, BOARD_partitionIMAGE_PARTITION_SIZE
की वैल्यू दी जा सकती है. जब तक ज़रूरी न हो, इनमें से किसी का भी सुझाव नहीं दिया जाता.
उदाहरण के लिए:
BOARD_PRODUCTIMAGE_PARTITION_RESERVED_SIZE := 52428800
इससे product.img
में मौजूद फ़ाइल सिस्टम में,
50 एमबी का खाली स्टोरेज स्पेस होना ज़रूरी हो जाता है.
रूट के मुताबिक सिस्टम में होने वाले बदलाव
Android 10 के साथ लॉन्च होने वाले डिवाइसों को, system-as-root का इस्तेमाल नहीं करना चाहिए.
डाइनैमिक पार्टीशन वाले डिवाइसों (चाहे वे डाइनैमिक पार्टीशन के साथ लॉन्च हों या फिर बाद में उनमें डाइनैमिक पार्टीशन जोड़े गए हों) को, सिस्टम-ऐज़-रूट का इस्तेमाल नहीं करना चाहिए. Linux kernel, super
partition को समझ नहीं सकता. इसलिए, वह system
को खुद माउंट नहीं कर सकता. system
को अब
पहले चरण के init
से माउंट किया गया है, जो रैम डिस्क में मौजूद है.
BOARD_BUILD_SYSTEM_ROOT_IMAGE
को सेट न करें. Android 10 में,
BOARD_BUILD_SYSTEM_ROOT_IMAGE
फ़्लैग का इस्तेमाल सिर्फ़ यह पता लगाने के लिए किया जाता है कि सिस्टम को, कर्नल ने माउंट किया है या रामडिस्क में पहले चरण के init
ने.
BOARD_BUILD_SYSTEM_ROOT_IMAGE
को true
पर सेट करने से, बिल्ड में गड़बड़ी होती है. ऐसा तब होता है, जब
PRODUCT_USE_DYNAMIC_PARTITIONS
, true
पर भी सेट होता है.
जब BOARD_USES_RECOVERY_AS_BOOT
को 'सही है' पर सेट किया जाता है, तो रिकवरी इमेज को boot.img के तौर पर बनाया जाता है. इसमें रिकवरी की रैमडिस्क होती है. पहले, बूटलोडर यह तय करने के लिए skip_initramfs
kernel
कमांड लाइन पैरामीटर का इस्तेमाल करता था कि किस मोड में बूट करना है.
Android 10 डिवाइसों के लिए, बूटलोडर को skip_initramfs
को kernel command-line पर पास नहीं करना चाहिए. इसके बजाय, रिकवरी को छोड़ने और सामान्य Android को बूट करने के लिए, बूटलोडर को androidboot.force_normal_boot=1
पास करना चाहिए. Android 12 या उसके बाद के वर्शन वाले डिवाइसों को androidboot.force_normal_boot=1
पास करने के लिए, bootconfig का इस्तेमाल करना होगा.
एवीबी कॉन्फ़िगरेशन में बदलाव
अगर Android Verified Boot 2.0 का इस्तेमाल करते समय, डिवाइस में चेन वाले पार्टिशन डिस्क्रिप्टर का इस्तेमाल नहीं किया जा रहा है, तो कुछ भी बदलने की ज़रूरत नहीं है. हालांकि, अगर चेन वाले पार्टिशन का इस्तेमाल किया जा रहा है और पुष्टि किए गए किसी एक पार्टिशन में डाइनैमिक है, तो बदलाव ज़रूरी हैं.
यहां डिवाइस के लिए कॉन्फ़िगरेशन का एक उदाहरण दिया गया है, जो system
और
vendor
पार्टीशन के लिए
vbmeta
को चेन करता है.
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION := 1
इस कॉन्फ़िगरेशन के साथ, बूटलोडर को system
और
vendor
पार्टीशन के आखिर में vbmeta
फ़ुटर मिलना चाहिए. ये पार्टीशन, अब bootloader को नहीं दिखते (ये super
में मौजूद होते हैं), इसलिए दो बदलाव करने होंगे.
-
डिवाइस की पार्टीशन टेबल में
vbmeta_system
औरvbmeta_vendor
पार्टीशन जोड़ें. A/B डिवाइसों के लिए,vbmeta_system_a
,vbmeta_system_b
,vbmeta_vendor_a
, औरvbmeta_vendor_b
जोड़ें. अगर एक या एक से ज़्यादा सेगमेंट जोड़े जा रहे हैं, तो उनका साइज़vbmeta
सेगमेंट के साइज़ के बराबर होना चाहिए. -
VBMETA_
जोड़कर कॉन्फ़िगरेशन फ़्लैग का नाम बदलें और यह बताएं कि चेनिंग किन पार्टीशन तक फैली है:BOARD_AVB_VBMETA_SYSTEM := system BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1 BOARD_AVB_VBMETA_VENDOR := vendor BOARD_AVB_VBMETA_VENDOR_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem BOARD_AVB_VBMETA_VENDOR_ALGORITHM := SHA256_RSA2048 BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP) BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION := 1
हो सकता है कि कोई डिवाइस इनमें से किसी एक, दोनों या किसी भी पार्टीशन का इस्तेमाल न कर रहा हो. बदलावों की ज़रूरत सिर्फ़ तब होती है, जब किसी लॉजिकल पार्टीशन को चेन किया जा रहा हो.
एवीबी बूटलोडर में हुए बदलाव
अगर बूटलोडर में libavb को एम्बेड किया गया है, तो ये पैच शामिल करें:
- 818cf56740775446285466eda984acedd4baeac0 — "libavb: Only query partition GUIDs when the cmdline needs them."
- 5abd6bc2578968d24406d834471adfd995a0c2e9 — "सिस्टम पार्टीशन न होने की अनुमति दें"
- 9ba3b6613b4e5130fa01a11d984c6b5f0eb3af05 — "Fix AvbSlotVerifyData->cmdline might be NULL"
अगर चेन पार्टिशन का इस्तेमाल किया जा रहा है, तो एक और पैच शामिल करें:
- 49936b4c0109411fdd38bd4ba3a32a01c40439a9 — "libavb: Support vbmeta blobs in beginning of partition."
कर्नेल कमांड लाइन में हुए बदलाव
kernel कमांड लाइन में एक नया पैरामीटर, androidboot.boot_devices
जोड़ना ज़रूरी है. इसका इस्तेमाल init
,
/dev/block/by-name
सिमलिंक चालू करने के लिए करता है. यह, ueventd
के बनाए गए, नाम के हिसाब से लिंक किए गए डिवाइस के पाथ कॉम्पोनेंट, यानी /dev/block/platform/device-path/by-name/partition-name
से जुड़ा होना चाहिए.
Android 12 या उसके बाद के वर्शन वाले डिवाइसों को androidboot.boot_devices
को init
पर भेजने के लिए,
bootconfig का इस्तेमाल करना होगा.
उदाहरण के लिए, अगर नाम के हिसाब से सुपर पार्टीशन का लिंक /dev/block/platform/soc/100000.ufshc/by-name/super
है, तो आपके पास BoardConfig.mk फ़ाइल में कमांड लाइन पैरामीटर को इस तरह जोड़ने का विकल्प है:
BOARD_KERNEL_CMDLINE += androidboot.boot_devices=soc/100000.ufshc
BOARD_BOOTCONFIG += androidboot.boot_devices=soc/100000.ufshc
fstab में हुए बदलाव
डिवाइस ट्री और डिवाइस ट्री ओवरले में fstab की एंट्री नहीं होनी चाहिए. ऐसी fstab फ़ाइल का इस्तेमाल करें जो रैमडиск का हिस्सा होगी.
लॉजिकल पार्टीशन के लिए, fstab फ़ाइल में बदलाव करना ज़रूरी है:
-
fs_mgr flags फ़ील्ड में
logical
फ़्लैग औरfirst_stage_mount
फ़्लैग शामिल होना चाहिए.first_stage_mount
फ़्लैग को Android 10 में जोड़ा गया था. इससे पता चलता है कि पहले चरण में किसी पार्टीशन को माउंट किया जाना है. -
कोई पार्टीशन,
avb=vbmeta partition name
कोfs_mgr
फ़्लैग के तौर पर तय कर सकता है. इसके बाद, किसी भी डिवाइस को माउंट करने से पहले, तय किए गएvbmeta
पार्टीशन को पहले चरणinit
से शुरू किया जाता है. -
dev
फ़ील्ड में, पार्टीशन का नाम होना चाहिए.
ऊपर दिए गए नियमों के मुताबिक, fstab में दी गई ये एंट्री, सिस्टम, वेंडर, और प्रॉडक्ट को लॉजिकल पार्टीशन के तौर पर सेट करती हैं.
#<dev> <mnt_point> <type> <mnt_flags options> <fs_mgr_flags> system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
fstab फ़ाइल को पहले चरण के रैमडिस्क में कॉपी करें.
SELinux में हुए बदलाव
सुपर पार्टीशन ब्लॉक डिवाइस को लेबल के साथ मार्क किया जाना चाहिए
super_block_device
. उदाहरण के लिए, अगर नाम के हिसाब से सिमलिंक का सुपर पार्टीशन
/dev/block/platform/soc/100000.ufshc/by-name/super
है,
तो इस लाइन को file_contexts
में जोड़ें:
/dev/block/platform/soc/10000\.ufshc/by-name/super u:object_r:super_block_device:s0
fastbootd
बूटलोडर (या बिना यूज़रस्पेस फ़्लैशिंग वाला टूल) डाइनैमिक पार्टिशन को नहीं समझता. इसलिए, वह उन्हें फ़्लैश नहीं कर सकता. इसे ठीक करने के लिए, डिवाइसों को फ़ास्टबूट प्रोटोकॉल लागू करने के यूज़र स्पेस का इस्तेमाल करना होगा, जिसे फ़ास्टबूट प्रोटोकॉल कहा जाता है.
फ़ास्टबूट को लागू करने के तरीके के बारे में ज़्यादा जानकारी के लिए, फ़ास्टबूट को उपयोगकर्ता के स्पेस में ले जाना लेख पढ़ें.
adb remount
eng या userdebug बिल्ड का इस्तेमाल करने वाले डेवलपर के लिए, adb remount
तेज़ी से बदलाव करने के लिए काफ़ी मददगार है. डाइनैमिक पार्टीशन, adb remount
के लिए एक समस्या है, क्योंकि अब हर फ़ाइल सिस्टम में खाली जगह नहीं है. इसे ठीक करने के लिए, डिवाइस ओवरलेफ़ को चालू कर सकते हैं. जब तक सुपर पार्टीशन में खाली जगह है, तब तक
adb remount
अपने-आप एक अस्थायी डाइनैमिक
पार्टीशन बनाता है और डेटा लिखने के लिए, overlayfs का इस्तेमाल करता है. अस्थायी सेगमेंट का नाम scratch
होता है. इसलिए, इस नाम का इस्तेमाल किसी दूसरे सेगमेंट के लिए न करें.
overlayfs को चालू करने के तरीके के बारे में ज़्यादा जानने के लिए, AOSP में overlayfs के लिए README देखें.
Android डिवाइसों को अपग्रेड करना
अगर किसी डिवाइस को Android 10 पर अपग्रेड किया जाता है और आपको ओटीए में डाइनैमिक पार्टीशन की सुविधा शामिल करनी है, तो आपको डिवाइस में पहले से मौजूद पार्टीशन टेबल में बदलाव करने की ज़रूरत नहीं है. इसके लिए, कुछ अतिरिक्त कॉन्फ़िगरेशन की ज़रूरत होती है.
डिवाइस के कॉन्फ़िगरेशन में किए गए बदलाव
डाइनैमिक पार्टीशन को पहले जैसा करने के लिए, device.mk
में ये फ़्लैग जोड़ें:
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
बोर्ड के कॉन्फ़िगरेशन में बदलाव
आपको बोर्ड के लिए ये वैरिएबल सेट करने होंगे:
BOARD_SUPER_PARTITION_BLOCK_DEVICES
को ब्लॉक किए गए उन डिवाइसों की सूची पर सेट करें जिनका इस्तेमाल, डाइनैमिक पार्टीशन के एक्सटेंट को स्टोर करने के लिए किया जाता है. यह डिवाइस पर मौजूद मौजूदा फ़िज़िकल पार्टीशन के नामों की सूची है.BOARD_SUPER_PARTITION_partition_DEVICE_SIZE
कोBOARD_SUPER_PARTITION_BLOCK_DEVICES
में मौजूद हर ब्लॉक डिवाइस के साइज़ पर सेट करें. यह डिवाइस पर मौजूद मौजूदा फ़िज़िकल पार्टीशन के साइज़ की सूची है. आम तौर पर, बोर्ड के मौजूदा कॉन्फ़िगरेशन में यहBOARD_partitionIMAGE_PARTITION_SIZE
होता है.BOARD_SUPER_PARTITION_BLOCK_DEVICES
में मौजूद सभी पार्टीशन के लिए, मौजूदाBOARD_partitionIMAGE_PARTITION_SIZE
को अनसेट करें.BOARD_SUPER_PARTITION_SIZE
कोBOARD_SUPER_PARTITION_partition_DEVICE_SIZE
के योग पर सेट करें.BOARD_SUPER_PARTITION_METADATA_DEVICE
को उस ब्लॉक डिवाइस पर सेट करें जहां डाइनैमिक पार्टीशन का मेटाडेटा सेव किया जाता है. यहBOARD_SUPER_PARTITION_BLOCK_DEVICES
में से कोई एक होना चाहिए. आम तौर पर, यहsystem
पर सेट होता है.BOARD_SUPER_PARTITION_GROUPS
,BOARD_group_SIZE
, औरBOARD_group_PARTITION_LIST
को क्रमशः सेट करें. ज़्यादा जानकारी के लिए, नए डिवाइसों पर बोर्ड कॉन्फ़िगरेशन में हुए बदलाव देखें.
उदाहरण के लिए, अगर डिवाइस में पहले से ही सिस्टम और वेंडर पार्टीशन मौजूद हैं और आपको उन्हें डायनैमिक पार्टीशन में बदलना है और अपडेट के दौरान नया प्रॉडक्ट पार्टीशन जोड़ना है, तो बोर्ड का यह कॉन्फ़िगरेशन सेट करें:
BOARD_SUPER_PARTITION_BLOCK_DEVICES := system vendor BOARD_SUPER_PARTITION_METADATA_DEVICE := system # Rename BOARD_SYSTEMIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE. BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := <size-in-bytes> # Rename BOARD_VENDORIMAGE_PARTITION_SIZE to BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := <size-in-bytes> # This is BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE + BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE BOARD_SUPER_PARTITION_SIZE := <size-in-bytes> # Configuration for dynamic partitions. For example: BOARD_SUPER_PARTITION_GROUPS := group_foo BOARD_GROUP_FOO_SIZE := <size-in-bytes> BOARD_GROUP_FOO_PARTITION_LIST := system vendor product
SELinux बदलाव
सुपर पार्टिशन ब्लॉक डिवाइसों को super_block_device_type
एट्रिब्यूट के साथ मार्क करना ज़रूरी है. उदाहरण के लिए, अगर डिवाइस में पहले से ही
system
और vendor
पार्टीशन मौजूद हैं और आपको डाइनैमिक पार्टीशन के एक्सटेंट को स्टोर करने के लिए, उनका इस्तेमाल ब्लॉक डिवाइसों के तौर पर करना है, तो उनके नाम वाले सिमलिंक को system_block_device
के तौर पर मार्क करें:
/dev/block/platform/soc/10000\.ufshc/by-name/system u:object_r:system_block_device:s0 /dev/block/platform/soc/10000\.ufshc/by-name/vendor u:object_r:system_block_device:s0
इसके बाद, device.te
में यह लाइन जोड़ें:
typeattribute system_block_device super_block_device_type;
अन्य कॉन्फ़िगरेशन के लिए, नए डिवाइसों पर डाइनैमिक पार्टिशन लागू करना देखें.
रिफ़िट अपडेट के बारे में ज़्यादा जानने के लिए, डाइनैमिक पार्टिशन के बिना A/B डिवाइसों के लिए ओटीए देखें.
फ़ैक्ट्री इमेज
डाइनैमिक पार्टिशन की सुविधा के साथ लॉन्च होने वाले डिवाइस के लिए, फ़ैक्ट्री इमेज को फ़्लैश करने के लिए, यूज़रस्पेस फ़ास्टबूट का इस्तेमाल करने से बचें. ऐसा इसलिए, क्योंकि यूज़रस्पेस में बूट करना, फ़्लैश करने के अन्य तरीकों के मुकाबले धीमा होता है.
इस समस्या को हल करने के लिए, make dist
अब एक और
super.img
इमेज बनाता है. इसे सीधे सुपर
पार्टीशन में फ़्लैश किया जा सकता है. यह लॉजिकल
पार्टीशन के कॉन्टेंट को अपने-आप बंडल करता है. इसका मतलब है कि इसमें super
पार्टीशन मेटाडेटा के साथ-साथ system.img
,
vendor.img
वगैरह शामिल होते हैं. इस इमेज को सीधे super
partition में, किसी अन्य टूल या
fastbootd का इस्तेमाल किए बिना फ़्लैश किया जा सकता है. बिल्ड होने के बाद, super.img
को
${ANDROID_PRODUCT_OUT}
में रखा जाता है.
डाइनैमिक पार्टिशन के साथ लॉन्च होने वाले A/B डिवाइसों के लिए,
super.img
में A स्लॉट में इमेज होती हैं. सुपर इमेज को सीधे फ़्लैश करने के बाद, डिवाइस को रीबूट करने से पहले स्लॉट A को बूट करने लायक के तौर पर मार्क करें.
पहले से मौजूद डिवाइसों के लिए, make dist
super_*.img
इमेज का एक सेट बनाता है. इन्हें सीधे तौर पर, संबंधित फ़िज़िकल पार्टीशन में फ़्लैश किया जा सकता है. उदाहरण के लिए, जब BOARD_SUPER_PARTITION_BLOCK_DEVICES
सिस्टम वेंडर है, तो make dist
, super_system.img
और super_vendor.img
को बनाता है. ये इमेज, target_files.zip
में मौजूद OTA फ़ोल्डर में डाली जाती हैं.
डिवाइस मैपर का स्टोरेज-डिवाइस ट्यूनिंग
डाइनैमिक पार्टिशनिंग में, डिवाइस-मैपर के कई ऐसे ऑब्जेक्ट शामिल होते हैं जिनके बारे में पहले से पता नहीं होता. हो सकता है कि ये सभी उम्मीद के मुताबिक इंस्टैंशिएट न हों, इसलिए आपको सभी माउंट ट्रैक करने होंगे. साथ ही, आपको जुड़े हुए सभी पार्टिशन की Android प्रॉपर्टी को उनके स्टोरेज डिवाइस के साथ अपडेट करना होगा.
init
में मौजूद एक मशीन, माउंट को ट्रैक करती है और Android प्रॉपर्टी को सिंक किए बिना अपडेट करती है. इस प्रोसेस में लगने वाले समय की कोई गारंटी नहीं है. इसलिए, आपको सभी on property
ट्रिगर के रिएक्ट करने के लिए ज़रूरत के मुताबिक समय देना होगा. प्रॉपर्टी के तौर पर, उदाहरण के लिए, dev.mnt.blk.<partition>
का इस्तेमाल किया जाता है, जहां <partition>
की वैल्यू root
,
system
, data
या
vendor
हो सकती है. हर प्रॉपर्टी, स्टोरेज डिवाइस के नाम से जुड़ी होती है. जैसे, इन उदाहरणों में दिखाया गया है:
taimen:/ % getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [sda] [dev.mnt.blk.firmware]: [sde] [dev.mnt.blk.metadata]: [sde] [dev.mnt.blk.persist]: [sda] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.vendor]: [dm-1] blueline:/ $ getprop | grep dev.mnt.blk [dev.mnt.blk.data]: [dm-4] [dev.mnt.blk.metadata]: [sda] [dev.mnt.blk.mnt.scratch]: [sda] [dev.mnt.blk.mnt.vendor.persist]: [sdf] [dev.mnt.blk.product]: [dm-2] [dev.mnt.blk.root]: [dm-0] [dev.mnt.blk.system_ext]: [dm-3] [dev.mnt.blk.vendor]: [dm-1] [dev.mnt.blk.vendor.firmware_mnt]: [sda]
init.rc
भाषा में, Android प्रॉपर्टी को नियमों के तौर पर बड़ा किया जा सकता है. साथ ही, प्लैटफ़ॉर्म के ज़रिए स्टोरेज डिवाइसों को, इस तरह के निर्देशों की मदद से ट्यून किया जा सकता है:
write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb 128 write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb 128
दूसरे चरण में init
में निर्देश की प्रोसेसिंग शुरू होने के बाद,
epoll loop
ऐक्टिव हो जाता है और वैल्यू अपडेट होने लगती हैं. हालांकि, init
के आखिर तक प्रॉपर्टी ट्रिगर चालू नहीं होते. इसलिए, root
, system
या vendor
को मैनेज करने के लिए, उन्हें बूट के शुरुआती चरणों में इस्तेमाल नहीं किया जा सकता. जब तक init.rc
स्क्रिप्ट early-fs
में बदलाव नहीं कर सकतीं, तब तक आपको उम्मीद करनी चाहिए कि कोर के डिफ़ॉल्ट read_ahead_kb
काफ़ी होंगे. early-fs
में बदलाव तब होता है, जब अलग-अलग डेमन और सुविधाएं शुरू होती हैं. इसलिए, Google का सुझाव है कि आप कार्रवाइयों की सही अवधि तय करने और रेस से जुड़ी स्थितियों को रोकने के लिए, sys.read_ahead_kb
जैसी init.rc
कंट्रोल वाली प्रॉपर्टी के साथ-साथ on property
की सुविधा का इस्तेमाल करें, जैसा कि यहां दिए गए उदाहरण में बताया गया है:
on property:dev.mnt.blk.root=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.system=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.vendor=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.vendor}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.product=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.system_ext}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.oem=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.oem}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on property:dev.mnt.blk.data=* && property:sys.read_ahead_kb=* write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${sys.read_ahead_kb:-2048} on early-fs: setprop sys.read_ahead_kb ${ro.read_ahead_kb.boot:-2048} on property:sys.boot_completed=1 setprop sys.read_ahead_kb ${ro.read_ahead_kb.bootcomplete:-128}