इस पेज पर, AOSP में किए गए बदलावों के बारे में बताया गया है. इन बदलावों की मदद से, बिल्ड के बीच फ़ाइल में होने वाले ग़ैर-ज़रूरी बदलावों को कम किया जा सकता है. डिवाइस इंप्लीमेंटर, अपने बिल्ड सिस्टम को मैनेज करते हैं. वे इस जानकारी का इस्तेमाल, ओवर-द-एयर (ओटीए) अपडेट के साइज़ को कम करने के लिए, गाइड के तौर पर कर सकते हैं.
Android ओटीए अपडेट में कभी-कभी ऐसी फ़ाइलें शामिल होती हैं जिनमें बदलाव किए गए हैं, लेकिन वे कोड में किए गए बदलावों से मेल नहीं खाती हैं. ये सिस्टम आर्टफ़ैक्ट बनाते हैं. ऐसा तब हो सकता है, जब एक ही कोड को अलग-अलग समय पर, अलग-अलग डायरेक्ट्री से या अलग-अलग मशीनों पर बनाया गया हो और उससे बदली गई बड़ी संख्या में फ़ाइलें जनरेट हुई हों. ऐसी अतिरिक्त फ़ाइलों की वजह से, ओटीए पैच का साइज़ बढ़ जाता है. साथ ही, यह पता लगाना मुश्किल हो जाता है कि कौनसा कोड बदला गया है.
ओटीए के कॉन्टेंट को ज़्यादा पारदर्शी बनाने के लिए, AOSP में बिल्ड सिस्टम में बदलाव किए गए हैं. इन बदलावों को, ओटीए पैच का साइज़ कम करने के लिए डिज़ाइन किया गया है. बिल्ड के बीच फ़ाइल में किए गए ग़ैर-ज़रूरी बदलावों को हटा दिया गया है. साथ ही, ओटीए अपडेट में सिर्फ़ पैच से जुड़ी फ़ाइलें शामिल की गई हैं. AOSP में एक बिल्ड डिफ़रेंस टूल भी शामिल है. यह बिल्ड से जुड़ी फ़ाइल में होने वाले सामान्य बदलावों को फ़िल्टर करता है, ताकि बिल्ड फ़ाइल में हुए बदलावों को साफ़ तौर पर देखा जा सके. साथ ही, इसमें एक ब्लॉक मैपिंग टूल भी शामिल है. इससे, ब्लॉक के ऐलोकेशन को एक जैसा बनाए रखने में मदद मिलती है.
बिल्ड सिस्टम कई तरीकों से, बेवजह बड़े पैच बना सकता है. इसे कम करने के लिए, Android 8.0 और उसके बाद के वर्शन में, नई सुविधाएं लागू की गईं. इनकी मदद से, हर फ़ाइल के अंतर के लिए पैच का साइज़ कम किया जा सकता है. ओटीए अपडेट पैकेज के साइज़ को कम करने वाले सुधारों में ये शामिल हैं:
-
ZSTD का इस्तेमाल. यह A/B डिवाइस अपडेट के अलावा, पूरी इमेज के लिए, सामान्य काम के लिए इस्तेमाल होने वाला, बिना डेटा हानि वाला कंप्रेशन एल्गोरिदम है. ZSTD को कंप्रेशन लेवल बढ़ाकर, ज़्यादा कंप्रेशन रेशियो के लिए पसंद के मुताबिक बनाया जा सकता है. कॉम्प्रेस करने का लेवल, OTA जनरेशन के समय सेट किया जाता है. इसे फ़्लैग
--vabc_compression_param=zstd,$COMPRESSION_LEVEL
पास करके सेट किया जा सकता है -
ओटीए के दौरान इस्तेमाल की जाने वाली कंप्रेसन विंडो का साइज़ बढ़ाना. डिवाइस की
.mk
फ़ाइल में, बिल्ड पैरामीटर को पसंद के मुताबिक बनाकर, कंप्रेस करने की विंडो का ज़्यादा से ज़्यादा साइज़ सेट किया जा सकता है. यह वैरिएबल,PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
के तौर पर सेट होता है - Puffin के रीकंप्रेसन का इस्तेमाल. यह टूल, डिफ़लेट स्ट्रीम के लिए, डिटरमिनिस्टिक पैचिंग टूल है. यह A/B ओटीए अपडेट जनरेशन के लिए, कंप्रेसन और डिफ़रेंस फ़ंक्शन को मैनेज करता है.
-
डेल्टा जनरेशन टूल के इस्तेमाल में बदलाव. जैसे, पैच को कंप्रेस करने के लिए,
bsdiff
लाइब्रेरी का इस्तेमाल कैसे किया जाता है. Android 9 और उसके बाद के वर्शन में,bsdiff
टूल, पैच के लिए सबसे अच्छा कंप्रेसन एल्गोरिदम चुनता है. -
update_engine
में किए गए सुधारों की वजह से, डिवाइस के A/B अपडेट के लिए पैच लागू करने पर, कम मेमोरी का इस्तेमाल होता है.
यहां दिए गए सेक्शन में, ओटीए अपडेट के साइज़ पर असर डालने वाली अलग-अलग समस्याओं, उनके समाधानों, और AOSP में लागू करने के उदाहरणों के बारे में बताया गया है.
फ़ाइल का क्रम
समस्या: किसी डायरेक्ट्री में मौजूद फ़ाइलों की सूची मांगने पर, फ़ाइल सिस्टम यह गारंटी नहीं देते कि फ़ाइलों का क्रम एक जैसा रहेगा. हालांकि, आम तौर पर एक ही चेकआउट के लिए फ़ाइलों का क्रम एक जैसा ही रहता है. 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 बिल्ड में ज़्यादातर पाथ रिलेटिव पाथ होते हैं, इसलिए C/C++ में __FILE__
कोई समस्या नहीं है. हालांकि, डिबग सिंबल डिफ़ॉल्ट रूप से पूरे पाथनेम को कोड में बदल देते हैं. साथ ही, .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 हेडर से बिल्ड-आईडी पढ़ें.
-
ओएस कब बनाया गया था, यह जानने के लिए
ro.build.date
पढ़ें. यह जानकारी, इंक्रीमेंटल बिल्ड को छोड़कर, सभी के लिए काम करती है. ऐसा हो सकता है कि इंक्रीमेंटल बिल्ड के लिए यह तारीख अपडेट न हो. उदाहरण के लिए, https://android.googlesource.com/platform/external/libchrome/+/8b7977eccc94f6b3a3896cd13b4aeacbfa1e0f84 पर जाएं.
संग्रह (zip, jar) में एम्बेड किए गए टाइमस्टैंप
Android 7.0 में, zip
कमांड के सभी इस्तेमाल में -X
जोड़कर, ज़िप संग्रह में एम्बेड किए गए टाइमस्टैंप की समस्या को ठीक किया गया है. इससे, ZIP फ़ाइल से बिल्डर का UID/GID और एक्सटेंडेड यूनिक्स टाइमस्टैंप हट गया.
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 चालू है, तो ओटीए टूल आपके पुष्टि करने की सुविधा के कॉन्फ़िगरेशन को अपने-आप चुन लेते हैं और डिवाइस पर पुष्टि करने की सुविधा चालू कर देते हैं. इससे, ओटीए पैकेज में रॉ बाइट के तौर पर सेव किए जाने के बजाय, पुष्टि करने वाले ब्लॉक को Android डिवाइसों पर कैलकुलेट किया जा सकता है. Verity ब्लॉक, 2 जीबी के partition के लिए करीब 16 एमबी का इस्तेमाल कर सकते हैं.
हालांकि, डिवाइस पर पुष्टि करने में काफ़ी समय लग सकता है. खास तौर पर, गड़बड़ी ठीक करने वाले फ़ॉरवर्ड कोड को लागू होने में काफ़ी समय लग सकता है. Pixel डिवाइसों पर, इसमें 10 मिनट तक का समय लग सकता है. कम कीमत वाले डिवाइसों पर, इसमें ज़्यादा समय लग सकता है. अगर आपको डिवाइस पर पुष्टि करने की प्रोसेस को बंद करना है, लेकिन dm-verity को चालू रखना है, तो ओटीए अपडेट जनरेट करते समय, ota_from_target_files
टूल में --disable_fec_computation
को पास करें. यह फ़्लैग, ओटीए अपडेट के दौरान डिवाइस पर पुष्टि करने की सुविधा बंद कर देता है.
इससे, OTA इंस्टॉलेशन का समय कम हो जाता है, लेकिन OTA पैकेज का साइज़ बढ़ जाता है. अगर आपके डिवाइस पर
dm-verity की सुविधा चालू नहीं है, तो इस फ़्लैग को पास करने से कोई असर नहीं पड़ेगा.
एक जैसे बिल्ड टूल
समस्या: इंस्टॉल की गई फ़ाइलें जनरेट करने वाले टूल एक जैसे होने चाहिए. इसका मतलब है कि किसी दिए गए इनपुट से हमेशा एक ही आउटपुट मिलना चाहिए.
समाधान/उदाहरण: इन बिल्ड टूल में बदलाव करना ज़रूरी था:
- फ़ाइल बनाने वाले को सूचना दें. सूचना फ़ाइल बनाने वाले टूल को बदला गया है, ताकि फिर से इस्तेमाल किए जा सकने वाले सूचना कलेक्शन बनाए जा सकें. CL देखें: https://android.googlesource.com/platform/build/+/8ae4984c2c8009e7a08e2a76b1762c2837ad4f64.
- Java Android कंपाइलर किट (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. - ऐप्लिकेशन की pre-dexopt (.odex) फ़ाइलें. pre-dexopt (.odex) फ़ाइलों में, 64-बिट सिस्टम पर बिना शुरू किए गए पैडिंग शामिल थे. इसे ठीक कर दिया गया है: https://android.googlesource.com/platform/art/+/34ed3afc41820c72a3c0ab9770be66b6668aa029.
बिल्ड डिफ़रेंस टूल का इस्तेमाल करना
जिन मामलों में बिल्ड से जुड़ी फ़ाइल में हुए बदलावों को हटाया नहीं जा सकता, उनके लिए AOSP में एक ऐसा टूल शामिल है जो दो फ़ाइल पैकेज की तुलना करने के लिए इस्तेमाल किया जाता है. इसे target_files_diff.py
के तौर पर जाना जाता है. यह टूल, दो बिल्ड के बीच बार-बार अंतर का पता लगाता है. हालांकि, इसमें बिल्ड से जुड़े फ़ाइल में हुए सामान्य बदलाव शामिल नहीं होते. जैसे,
- बिल्ड आउटपुट में होने वाले बदलाव (उदाहरण के लिए, बिल्ड नंबर में बदलाव की वजह से).
- मौजूदा बिल्ड सिस्टम में मौजूद समस्याओं की वजह से किए गए बदलाव.
बिल्ड डिफ़रेंस टूल का इस्तेमाल करने के लिए, यह कमांड चलाएं:
target_files_diff.py dir1 dir2
dir1
और dir2
, बुनियादी डायरेक्ट्री हैं. इनमें हर बिल्ड के लिए, टारगेट फ़ाइलें होती हैं.
ब्लॉक का ऐलोकेशन एक जैसा रखना
किसी फ़ाइल के लिए, उसके कॉन्टेंट में दो बिल्ड के बीच कोई बदलाव नहीं होता. हालांकि, डेटा को सेव करने वाले असल ब्लॉक में बदलाव हो सकता है. इस वजह से, ओटीए अपडेट के लिए ब्लॉक को एक जगह से दूसरी जगह ले जाने के लिए, अपडेटर को ज़रूरत से ज़्यादा I/O करना पड़ता है.
वर्चुअल A/B ओटीए अपडेट में, ज़रूरत से ज़्यादा I/O की वजह से, लिखते समय कॉपी करने की सुविधा वाले स्नैपशॉट को सेव करने के लिए, स्टोरेज की ज़रूरत बहुत ज़्यादा बढ़ सकती है. A/B ओटीए अपडेट के अलावा, किसी अन्य ओटीए अपडेट के लिए ब्लॉक को एक जगह से दूसरी जगह ले जाने पर, अपडेट में लगने वाला समय बढ़ जाता है. ऐसा इसलिए होता है, क्योंकि ब्लॉक को एक जगह से दूसरी जगह ले जाने पर, ज़्यादा I/O होता है.
इस समस्या को हल करने के लिए, Google ने Android 7.0 में 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 अपडेट के लिए, ओटीए लागू करने के लिए ज़रूरी स्टोरेज की मात्रा काफ़ी कम हो जाती है.
ऐप्लिकेशन अपडेट न करना
बिल्ड में अंतर को कम करने के अलावा, ओटीए अपडेट के साइज़ को भी कम किया जा सकता है. इसके लिए, उन ऐप्लिकेशन के अपडेट को बाहर रखें जो ऐप्लिकेशन स्टोर से अपडेट पाते हैं. अक्सर, किसी डिवाइस के अलग-अलग सेगमेंट में APK का एक बड़ा हिस्सा होता है. अगर ओटीए अपडेट में, ऐप्लिकेशन स्टोर से अपडेट होने वाले ऐप्लिकेशन के नए वर्शन शामिल किए जाते हैं, तो ओटीए पैकेज का साइज़ बहुत ज़्यादा हो सकता है. साथ ही, इससे उपयोगकर्ता को बहुत कम फ़ायदा मिलता है. जब तक उपयोगकर्ताओं को ओटीए पैकेज मिलता है, तब तक उनके पास अपडेट किया गया ऐप्लिकेशन या ऐप्लिकेशन स्टोर से सीधे तौर पर मिला नया वर्शन पहले से हो सकता है.