इस पेज पर, AOSP में किए गए बदलावों के बारे में बताया गया है. इन बदलावों की मदद से, बिल्ड के बीच फ़ाइलों में होने वाले गैर-ज़रूरी बदलावों को कम किया जा सकता है. डिवाइस बनाने वाली कंपनियां, अपने बिल्ड सिस्टम को बनाए रखती हैं. वे इस जानकारी का इस्तेमाल, ओवर-द-एयर (OTA) अपडेट का साइज़ कम करने के लिए गाइड के तौर पर कर सकती हैं.
Android के ओटीए अपडेट में कभी-कभी ऐसी बदली हुई फ़ाइलें शामिल होती हैं जो कोड में किए गए बदलावों से मेल नहीं खातीं. ये असल में, बिल्ड सिस्टम के आर्टफ़ैक्ट होते हैं. ऐसा तब हो सकता है, जब एक ही कोड को अलग-अलग समय पर, अलग-अलग डायरेक्ट्री से या अलग-अलग मशीनों पर बनाया गया हो और उससे बड़ी संख्या में बदली गई फ़ाइलें जनरेट हुई हों. इस तरह की अतिरिक्त फ़ाइलों से, ओटीए पैच का साइज़ बढ़ जाता है. साथ ही, यह पता लगाना मुश्किल हो जाता है कि कौनसे कोड में बदलाव किया गया है.
OTA के कॉन्टेंट को ज़्यादा पारदर्शी बनाने के लिए, AOSP में बिल्ड सिस्टम में बदलाव किए गए हैं. इन्हें OTA पैच का साइज़ कम करने के लिए डिज़ाइन किया गया है. बिल्ड के बीच फ़ाइल में किए गए गैर-ज़रूरी बदलावों को हटा दिया गया है. साथ ही, ओटीए अपडेट में सिर्फ़ पैच से जुड़ी फ़ाइलें शामिल हैं. AOSP में बिल्ड डिफ़ टूल भी शामिल है. यह टूल, बिल्ड से जुड़े फ़ाइल में हुए सामान्य बदलावों को फ़िल्टर करके, बिल्ड फ़ाइल में हुए बदलावों को बेहतर तरीके से दिखाता है. साथ ही, इसमें ब्लॉक मैपिंग टूल भी शामिल है. यह टूल, ब्लॉक के असाइनमेंट को एक जैसा बनाए रखने में आपकी मदद करता है.
बिल्ड सिस्टम, कई तरीकों से बेवजह बड़े पैच बना सकता है. इस समस्या को कम करने के लिए, Android 8.0 और इसके बाद के वर्शन में नई सुविधाएं लागू की गई हैं. इनकी मदद से, हर फ़ाइल के अंतर के लिए पैच का साइज़ कम किया जा सकता है. ओटीए-अपडेट पैकेज के साइज़ को कम करने के लिए, ये सुधार किए गए हैं:
-
ZSTD का इस्तेमाल किया जाता है. यह एक सामान्य मकसद वाला, बिना डेटा खोए कंप्रेस करने वाला एल्गोरिदम है. इसका इस्तेमाल, नॉन-ए/बी डिवाइसों पर अपडेट की गई पूरी इमेज के लिए किया जाता है. ZSTD को ज़्यादा कंप्रेशन अनुपात के लिए पसंद के मुताबिक बनाया जा सकता है. इसके लिए, कंप्रेशन लेवल को बढ़ाना होगा. कंप्रेशन लेवल, ओटीए जनरेट करने के दौरान सेट किया जाता है. इसे
--vabc_compression_param=zstd,$COMPRESSION_LEVEL
फ़्लैग पास करके सेट किया जा सकता है -
ओटीए के दौरान इस्तेमाल की गई कंप्रेस करने की विंडो का साइज़ बढ़ाना. ज़्यादा से ज़्यादा कंप्रेस करने की विंडो का साइज़, डिवाइस की
.mk
फ़ाइल में बिल्ड पैरामीटर को पसंद के मुताबिक बनाकर सेट किया जा सकता है. इस वैरिएबल कोPRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
के तौर पर सेट किया जाता है - Puffin रीकंप्रेशन का इस्तेमाल किया जाता है. यह डिफ़्लेट स्ट्रीम के लिए, पैच करने वाला एक टूल है. यह A/B OTA अपडेट जनरेट करने के लिए, कंप्रेशन और अंतर वाले फ़ंक्शन को मैनेज करता है.
-
डेल्टा जनरेशन टूल के इस्तेमाल में बदलाव. जैसे, पैच को कंप्रेस करने के लिए
bsdiff
लाइब्रेरी का इस्तेमाल कैसे किया जाता है. Android 9 और इसके बाद के वर्शन में,bsdiff
टूल, कंप्रेस करने के लिए ऐसे एल्गोरिदम को चुनता है जो पैच को सबसे अच्छी तरह से कंप्रेस कर सके. -
update_engine
में किए गए सुधारों की वजह से, A/B डिवाइस अपडेट के लिए पैच लागू करते समय कम मेमोरी इस्तेमाल होती है.
यहां दिए गए सेक्शन में, ओटीए अपडेट के साइज़ पर असर डालने वाली अलग-अलग समस्याओं के बारे में बताया गया है. साथ ही, उनके समाधान और एओएसपी में लागू करने के उदाहरण दिए गए हैं.
फ़ाइल का क्रम
समस्या: फ़ाइल सिस्टम, किसी डायरेक्ट्री में मौजूद फ़ाइलों की सूची का अनुरोध करने पर, फ़ाइलों के क्रम की गारंटी नहीं देते. हालांकि, आम तौर पर एक ही चेकआउट के लिए यह क्रम एक जैसा होता है. ls
जैसे टूल, डिफ़ॉल्ट रूप से नतीजों को क्रम से लगाते हैं. हालांकि, find
और make
जैसी कमांड में इस्तेमाल होने वाला वाइल्डकार्ड फ़ंक्शन, नतीजों को क्रम से नहीं लगाता. इन टूल का इस्तेमाल करने से पहले, आपको आउटपुट को क्रम से लगाना होगा.
समाधान: वाइल्डकार्ड फ़ंक्शन के साथ find
और make
जैसे टूल इस्तेमाल करते समय, इन कमांड के आउटपुट को इस्तेमाल करने से पहले क्रम से लगाएं. Android.mk
फ़ाइलों में $(wildcard)
या $(shell find)
का इस्तेमाल करते समय, उन्हें भी क्रम से लगाएं. कुछ टूल, जैसे कि Java, इनपुट को क्रम से लगाते हैं. इसलिए, फ़ाइलों को क्रम से लगाने से पहले, पुष्टि करें कि इस्तेमाल किया जा रहा टूल पहले से ऐसा नहीं कर रहा है.
उदाहरण: कोर बिल्ड सिस्टम में कई इंस्टेंस को ठीक किया गया. इसके लिए, बिल्ट-इन all-*-files-under
मैक्रो का इस्तेमाल किया गया. इसमें all-cpp-files-under
शामिल है, क्योंकि कई परिभाषाएं अन्य मेकफ़ाइल में फैली हुई थीं.
ज़्यादा जानकारी के लिए, यहां जाएं:
- https://android.googlesource.com/platform/build/+/4d66adfd0e6d599d8502007e4ea9aaf82e95569f
- https://android.googlesource.com/platform/build/+/379f9f9cec4fe1c66b6d60a6c19fecb81b9eb410
- https://android.googlesource.com/platform/build/+/7c3e3f8314eec2c053012dd97d2ae649ebeb5653
- https://android.googlesource.com/platform/build/+/5c64b4e81c1331cab56d8a8c201f26bb263b630c
बिल्ड डायरेक्ट्री
समस्या: जिस डायरेक्ट्री में चीज़ें बनाई जाती हैं उसे बदलने से, बाइनरी अलग-अलग हो सकती हैं. Android बिल्ड में ज़्यादातर पाथ, रिलेटिव पाथ होते हैं. इसलिए, __FILE__
में C/C++ का इस्तेमाल करने में कोई समस्या नहीं होती. हालांकि, डिबग सिंबल डिफ़ॉल्ट रूप से पूरे पाथनेम को एन्कोड करते हैं. साथ ही, .note.gnu.build-id
को स्ट्रिप किए गए बाइनरी को हैश करके जनरेट किया जाता है. इसलिए, डिबग सिंबल बदलने पर यह भी बदल जाएगा.
समस्या का हल: AOSP अब डीबग पाथ को रेलेटिव बनाता है. ज़्यादा जानकारी के लिए, इस CL को देखें: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02.
टाइमस्टैंप
समस्या: बिल्ड आउटपुट में मौजूद टाइमस्टैंप की वजह से, फ़ाइल में गैर-ज़रूरी बदलाव होते हैं. इन जगहों पर ऐसा हो सकता है:
__DATE__/__TIME__/__TIMESTAMP__
C या C++ कोड में मैक्रो.- ज़िप फ़ॉर्मैट वाले संग्रहों में एम्बेड किए गए टाइमस्टैंप.
समाधान/उदाहरण: बिल्ड आउटपुट से टाइमस्टैंप हटाने के लिए, यहां दिए गए निर्देशों का पालन करें: C/C++ में __DATE__/__TIME__/__TIMESTAMP__ और संग्रह में एम्बेड किए गए टाइमस्टैंप.
C/C++ में __DATE__/__TIME__/__TIMESTAMP__
ये मैक्रो, अलग-अलग बिल्ड के लिए हमेशा अलग-अलग आउटपुट जनरेट करते हैं. इसलिए, इनका इस्तेमाल न करें. इन मैक्रो को हटाने के लिए, यहां कुछ विकल्प दिए गए हैं:
- उन्हें हटा दें. उदाहरण के लिए, https://android.googlesource.com/platform/system/core/+/30622bbb209db187f6851e4cf0cdaa147c2fca9f पर जाएं.
- चल रहे बाइनरी की खास पहचान करने के लिए, ELF हेडर से build-id पढ़ें.
-
ओएस कब बनाया गया था, यह जानने के लिए
ro.build.date
पढ़ें. यह जानकारी, इंक्रीमेंटल बिल्ड को छोड़कर सभी के लिए काम करती है. इंक्रीमेंटल बिल्ड के लिए, यह तारीख अपडेट नहीं हो सकती. उदाहरण के लिए, https://android.googlesource.com/platform/external/libchrome/+/8b7977eccc94f6b3a3896cd13b4aeacbfa1e0f84 पर जाएं.
संग्रहों (zip, jar) में एम्बेड किए गए टाइमस्टैंप
Android 7.0 में, ज़िप संग्रहों में एम्बेड किए गए टाइमस्टैंप की समस्या को ठीक किया गया है. इसके लिए, zip
कमांड के सभी इस्तेमाल में -X
जोड़ा गया है. इससे, बिल्डर का यूआईडी/जीआईडी और ZIP फ़ाइल से बढ़ाया गया यूनिक्स टाइमस्टैंप हट गया.
ziptime
(/platform/build/+/android16-release/tools/ziptime/
में मौजूद) नाम का नया टूल, ज़िप हेडर में मौजूद सामान्य टाइमस्टैंप को रीसेट करता है. ज़्यादा जानकारी के लिए, README फ़ाइल देखें.
signapk
टूल, APK फ़ाइलों के लिए टाइमस्टैंप सेट करता है. ये टाइमस्टैंप, सर्वर के टाइमज़ोन के हिसाब से अलग-अलग हो सकते हैं. ज़्यादा जानकारी के लिए, CL
https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 पर जाएं.
signapk
टूल, APK फ़ाइलों के लिए टाइमस्टैंप सेट करता है. ये टाइमस्टैंप, सर्वर के टाइमज़ोन के हिसाब से अलग-अलग हो सकते हैं. ज़्यादा जानकारी के लिए, CL
https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 पर जाएं.
वर्शन स्ट्रिंग
समस्या: APK वर्शन स्ट्रिंग में अक्सर BUILD_NUMBER
जोड़ा जाता था. अगर किसी APK में कोई और बदलाव नहीं किया गया है, तो भी APK अलग होगा.
समाधान: APK वर्शन स्ट्रिंग से बिल्ड नंबर हटाएं.
उदाहरण:
- https://android.googlesource.com/platform/packages/apps/Camera2/+/5e0f4cf699a4c7c95e2c38ae3babe6f20c258d27
- https://android.googlesource.com/platform/build/+/d75d893da8f97a5c7781142aaa7a16cf1dbb669c
डिवाइस पर ही पुष्टि करने की सुविधा चालू करना
अगर आपके डिवाइस पर dm-verity चालू है, तो OTA टूल आपके verity कॉन्फ़िगरेशन को अपने-आप चुन लेते हैं. साथ ही, डिवाइस पर verity कंप्यूटेशन की सुविधा चालू कर देते हैं. इससे, वेरिटी ब्लॉक को Android डिवाइसों पर कैलकुलेट किया जा सकता है. इसके बजाय, इन्हें आपके ओटीए पैकेज में रॉ बाइट के तौर पर सेव किया जाता है. Verity ब्लॉक, 2 जीबी के पार्टीशन के लिए करीब 16 एमबी का इस्तेमाल कर सकते हैं.
हालांकि, डिवाइस पर ही पुष्टि करने में ज़्यादा समय लग सकता है. खास तौर पर, फ़ॉरवर्ड
एरर-करेक्शन कोड में ज़्यादा समय लग सकता है. Pixel डिवाइसों पर, इसमें 10 मिनट तक लग सकते हैं. कम सुविधाओं वाले डिवाइसों पर, इसमें ज़्यादा समय लग सकता है. अगर आपको डिवाइस पर वेरिटी कंप्यूटेशन की सुविधा बंद करनी है, लेकिन dm-verity की सुविधा चालू रखनी है, तो ओटीए अपडेट जनरेट करते समय ota_from_target_files
टूल को --disable_fec_computation
पास करके ऐसा किया जा सकता है. यह फ़्लैग, ओटीए अपडेट के दौरान डिवाइस पर पुष्टि करने की सुविधा को बंद कर देता है.
इससे ओटीए इंस्टॉल करने में लगने वाला समय कम हो जाता है. हालांकि, ओटीए पैकेज का साइज़ बढ़ जाता है. अगर आपके डिवाइस पर dm-verity चालू नहीं है, तो इस फ़्लैग को पास करने से कोई फ़र्क़ नहीं पड़ता.
एक जैसे बिल्ड टूल
समस्या: इंस्टॉल की गई फ़ाइलें जनरेट करने वाले टूल एक जैसे होने चाहिए. इसका मतलब है कि किसी इनपुट के लिए हमेशा एक ही आउटपुट मिलना चाहिए.
समाधान/उदाहरण: इन बिल्ड टूल में बदलाव करना ज़रूरी था:
- NOTICE फ़ाइल बनाने वाला. NOTICE फ़ाइल बनाने वाले व्यक्ति को बदल दिया गया है, ताकि NOTICE के ऐसे कलेक्शन बनाए जा सकें जिन्हें फिर से बनाया जा सकता है. सीएल देखें: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64.
- Java Android Compiler Kit (Jack). Jack टूलचेन को अपडेट करने की ज़रूरत थी, ताकि जनरेट किए गए कंस्ट्रक्टर के क्रम में कभी-कभी होने वाले बदलावों को मैनेज किया जा सके. टूलचेन में कंस्ट्रक्टर के लिए, डिटरमिनिस्टिक ऐक्सेसर जोड़े गए: https://android.googlesource.com/toolchain/jack/+/056a5425b3ef57935206c19ecb198a89221ca64b.
- ART AOT कंपाइलर (dex2oat). ART कंपाइलर बाइनरी को अपडेट किया गया है. इससे, एक ऐसी इमेज बनाने का विकल्प जोड़ा गया है जो हर बार एक जैसी होती है: https://android.googlesource.com/platform/art/+/ace0dc1dd5480ad458e622085e51583653853fb9.
-
libpac.so फ़ाइल (V8). हर बिल्ड, एक अलग
/system/lib/libpac.so
फ़ाइल बनाता है, क्योंकि हर बिल्ड के लिए V8 स्नैपशॉट बदलता है. इस समस्या को हल करने के लिए, स्नैपशॉट को हटा दिया गया है: https://android.googlesource.com/platform/external/v8/+/e537f38c36600fd0f3026adba6b3f4cbcee1fb29. - ऐप्लिकेशन की प्री-डेक्सऑप्ट (.odex) फ़ाइलें. प्री-डेक्सऑप्ट (.odex) फ़ाइलों में, 64-बिट सिस्टम पर अनइनिशियलाइज़्ड पैडिंग मौजूद थी. इसे ठीक कर दिया गया है: https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029.
डिफ़रेंस चेकर टूल का इस्तेमाल करना
अगर बिल्ड से जुड़ी फ़ाइलों में बदलावों को हटाना मुमकिन नहीं है, तो AOSP में बिल्ड डिफ़ टूल शामिल है. target_files_diff.py
इसका इस्तेमाल दो फ़ाइल पैकेज की तुलना करने के लिए किया जाता है. यह टूल, दो बिल्ड के बीच रिकर्सिव डिफ़ करता है. इसमें, बिल्ड से जुड़ी फ़ाइलों में हुए सामान्य बदलावों को शामिल नहीं किया जाता. जैसे,
- बिल्ड आउटपुट में होने वाले संभावित बदलाव (उदाहरण के लिए, बिल्ड नंबर में बदलाव की वजह से).
- मौजूदा बिल्ड सिस्टम में मौजूद समस्याओं की वजह से बदलाव किए गए हैं.
बिल्ड की तुलना करने वाले टूल का इस्तेमाल करने के लिए, यह कमांड चलाएं:
target_files_diff.py dir1 dir2
dir1
और dir2
, बेस डायरेक्ट्री हैं. इनमें हर बिल्ड के लिए, निकाली गई टारगेट फ़ाइलें होती हैं.
ब्लॉक के लिए एक जैसा समय तय करना
किसी फ़ाइल के लिए, दो बिल्ड के बीच उसका कॉन्टेंट एक जैसा रहता है. हालांकि, डेटा रखने वाले असल ब्लॉक बदल सकते हैं. इस वजह से, अपडेटर को ओटीए अपडेट के लिए, ब्लॉक को इधर-उधर ले जाने के लिए गैर-ज़रूरी I/O करना पड़ता है.
वर्चुअल ए/बी ओटीए अपडेट में, गैर-ज़रूरी I/O की वजह से, कॉपी-ऑन-राइट स्नैपशॉट को सेव करने के लिए ज़रूरी स्टोरेज स्पेस काफ़ी बढ़ सकता है. नॉन-ए/बी ओटीए अपडेट में, ओटीए अपडेट के लिए ब्लॉक को इधर-उधर ले जाने से अपडेट होने में ज़्यादा समय लगता है. ऐसा इसलिए होता है, क्योंकि ब्लॉक को इधर-उधर ले जाने की वजह से ज़्यादा I/O होता है.
इस समस्या को हल करने के लिए, Android 7.0 में Google ने make_ext4fs
टूल को
बढ़ाया है, ताकि सभी बिल्ड में ब्लॉक का बंटवारा एक जैसा रहे. make_ext4fs
टूल, -d base_fs
फ़्लैग को स्वीकार करता है. यह फ़्लैग, ext4
इमेज जनरेट करते समय फ़ाइलों को एक ही ब्लॉक में असाइन करने की कोशिश करता है. हालांकि, यह फ़्लैग इस्तेमाल करना ज़रूरी नहीं है. पिछले बिल्ड की टारगेट फ़ाइलों की zip फ़ाइल से, ब्लॉक मैपिंग फ़ाइलें (जैसे कि base_fs
मैप फ़ाइलें) निकाली जा सकती हैं. हर ext4
पार्टीशन के लिए, IMAGES
डायरेक्ट्री में एक .map
फ़ाइल होती है. उदाहरण के लिए, IMAGES/system.map
, system
पार्टीशन से मेल खाता है. इसके बाद, इन base_fs
फ़ाइलों को चेक-इन किया जा सकता है और PRODUCT_<partition>_BASE_FS_PATH
के ज़रिए तय किया जा सकता है. जैसे, इस उदाहरण में दिखाया गया है:
PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map
इससे, ओटीए पैकेज का कुल साइज़ कम नहीं होता. हालांकि, इससे ओटीए अपडेट की परफ़ॉर्मेंस बेहतर होती है, क्योंकि इससे I/O की मात्रा कम हो जाती है. वर्चुअल A/B अपडेट के लिए, इससे OTA को लागू करने के लिए ज़रूरी स्टोरेज स्पेस में काफ़ी कमी आती है.
ऐप्लिकेशन अपडेट करने से बचें
बिल्ड के अंतर को कम करने के साथ-साथ, ऐप्लिकेशन स्टोर से अपडेट पाने वाले ऐप्लिकेशन के लिए, अपडेट को छोड़कर ओटीए अपडेट के साइज़ को कम किया जा सकता है. डिवाइस के अलग-अलग पार्टीशन में, अक्सर APK का अहम हिस्सा होता है. ओटीए अपडेट में, ऐप्लिकेशन स्टोर से अपडेट किए गए ऐप्लिकेशन के नए वर्शन शामिल करने से, ओटीए पैकेज का साइज़ बढ़ सकता है. साथ ही, इससे उपयोगकर्ताओं को कम फ़ायदा मिल सकता है. ऐसा हो सकता है कि उपयोगकर्ताओं को ओटीए पैकेज मिलने से पहले ही, अपडेट किया गया ऐप्लिकेशन या उससे भी नया वर्शन मिल चुका हो. यह वर्शन उन्हें सीधे तौर पर ऐप्लिकेशन स्टोर से मिला हो.