Android Pony EXpress (APEX) कंटेनर फ़ॉर्मैट को Android 10 में लॉन्च किया गया था. इसका इस्तेमाल, कम लेवल के सिस्टम मॉड्यूल के इंस्टॉल फ़्लो में किया जाता है. इस फ़ॉर्मैट की मदद से, उन सिस्टम कॉम्पोनेंट को अपडेट किया जा सकता है जो स्टैंडर्ड Android ऐप्लिकेशन मॉडल में फ़िट नहीं होते. उदाहरण के लिए, नेटिव सेवाएं और लाइब्रेरी, हार्डवेयर एब्स्ट्रैक्शन लेयर (HALs), रनटाइम (ART), और क्लास लाइब्रेरी.
"APEX" शब्द का इस्तेमाल, APEX फ़ाइल के लिए भी किया जा सकता है.
बैकग्राउंड
Android, पैकेज इंस्टॉलर ऐप्लिकेशन (जैसे कि Google Play Store ऐप्लिकेशन) के ज़रिए, स्टैंडर्ड ऐप्लिकेशन मॉडल (जैसे, सेवाएं, गतिविधियां) में फ़िट होने वाले मॉड्यूल के अपडेट के साथ काम करता है. हालांकि, ओएस के निचले लेवल के कॉम्पोनेंट के लिए इसी तरह के मॉडल का इस्तेमाल करने से ये समस्याएं आती हैं:
- APK पर आधारित मॉड्यूल, बूट क्रम में शुरुआती चरणों में इस्तेमाल नहीं किए जा सकते. पैकेज मैनेजर, ऐप्लिकेशन की जानकारी का मुख्य डेटाबेस होता है. इसे सिर्फ़ ऐक्टिविटी मैनेजर से शुरू किया जा सकता है. यह बूट प्रोसेस के आखिरी चरण में तैयार होता है.
- APK फ़ॉर्मैट (खास तौर पर मेनिफ़ेस्ट) को Android ऐप्लिकेशन के लिए डिज़ाइन किया गया है और सिस्टम मॉड्यूल हमेशा इसके साथ काम नहीं करते.
डिज़ाइन
इस सेक्शन में, APEX फ़ाइल फ़ॉर्मैट और APEX मैनेजर के हाई-लेवल डिज़ाइन के बारे में बताया गया है. APEX मैनेजर, APEX फ़ाइलों को मैनेज करने वाली सेवा है.
APEX के लिए इस डिज़ाइन को चुनने की वजह के बारे में ज़्यादा जानने के लिए, APEX को डेवलप करते समय, इसके विकल्पों के बारे में जानकारी देखें.
APEX फ़ॉर्मैट
यह APEX फ़ाइल का फ़ॉर्मैट है.
पहली इमेज. APEX फ़ाइल फ़ॉर्मैट
सबसे ऊपर के लेवल पर, APEX फ़ाइल एक ZIP फ़ाइल होती है. इसमें फ़ाइलें बिना कंप्रेस किए स्टोर की जाती हैं और 4 केबी की सीमाओं पर होती हैं.
APEX फ़ाइल में ये चार फ़ाइलें होती हैं:
apex_manifest.json
AndroidManifest.xml
apex_payload.img
apex_pubkey
apex_manifest.json
फ़ाइल में पैकेज का नाम और वर्शन होता है, जिससे APEX फ़ाइल की पहचान की जाती है. यह JSON फ़ॉर्मैट में एक
ApexManifest
प्रोटोकॉल बफ़र है.
AndroidManifest.xml
फ़ाइल की मदद से, APEX फ़ाइल, APK से जुड़े टूल और इन्फ़्रास्ट्रक्चर का इस्तेमाल कर सकती है. जैसे, ADB, PackageManager, और पैकेज इंस्टॉलर ऐप्लिकेशन (जैसे, Play Store). उदाहरण के लिए, APEX फ़ाइल में मौजूद मेटाडेटा की जांच करने के लिए, aapt
जैसे किसी मौजूदा टूल का इस्तेमाल किया जा सकता है. इस फ़ाइल में पैकेज का नाम और वर्शन की जानकारी होती है. आम तौर पर, यह जानकारी apex_manifest.json
में भी उपलब्ध होती है.
APEX के साथ काम करने वाले नए कोड और सिस्टम के लिए, AndroidManifest.xml
के बजाय apex_manifest.json
का सुझाव दिया जाता है. AndroidManifest.xml
में टारगेटिंग से जुड़ी ऐसी जानकारी हो सकती है जिसका इस्तेमाल, ऐप्लिकेशन पब्लिश करने वाले मौजूदा टूल कर सकते हैं.
apex_payload.img
, dm-verity की मदद से बैक अप ली गई ext4 फ़ाइल सिस्टम इमेज है. इमेज को रनटाइम के दौरान, लूपबैक डिवाइस के ज़रिए माउंट किया जाता है. खास तौर पर, हैश ट्री और मेटाडेटा ब्लॉक को libavb
लाइब्रेरी का इस्तेमाल करके बनाया जाता है. फ़ाइल सिस्टम के पेलोड को पार्स नहीं किया जाता, क्योंकि इमेज को जगह पर माउंट किया जाना चाहिए. सामान्य फ़ाइलें, apex_payload.img
फ़ाइल में शामिल होती हैं.
apex_pubkey
, फ़ाइल सिस्टम इमेज को साइन करने के लिए इस्तेमाल की जाने वाली सार्वजनिक कुंजी है. रनटाइम के दौरान, यह कुंजी यह पक्का करती है कि डाउनलोड किए गए APEX पर उसी इकाई से हस्ताक्षर किया गया हो जिसने पहले से मौजूद पार्टीशन में उसी APEX पर हस्ताक्षर किया है.
APEX को नाम देने के लिए दिशा-निर्देश
प्लैटफ़ॉर्म के बेहतर होने के साथ-साथ, नए APEX के नामों में होने वाली गड़बड़ियों से बचने के लिए, नाम तय करने के लिए दिए गए इन दिशा-निर्देशों का पालन करें:
com.android.*
- AOSP APEX के लिए रिज़र्व है. यह किसी कंपनी या डिवाइस के लिए खास नहीं होता.
com.<companyname>.*
- किसी कंपनी के लिए रिज़र्व है. उस कंपनी के कई डिवाइसों का इस्तेमाल किया जा सकता है.
com.<companyname>.<devicename>.*
- किसी खास डिवाइस (या डिवाइसों के सबसेट) के लिए यूनीक APEX के लिए रिज़र्व है.
APEX मैनेजर
APEX मैनेजर (या apexd
) एक स्टैंडअलोन नेटिव प्रोसेस है. यह APEX फ़ाइलों की पुष्टि करने, उन्हें इंस्टॉल करने, और अनइंस्टॉल करने के लिए ज़िम्मेदार है. यह प्रोसेस, बूट करने के क्रम में शुरू होती है और जल्दी तैयार हो जाती है. आम तौर पर, APEX फ़ाइलें डिवाइस पर /system/apex
में पहले से इंस्टॉल होती हैं. अगर कोई अपडेट उपलब्ध नहीं है, तो APEX मैनेजर डिफ़ॉल्ट रूप से इन पैकेज का इस्तेमाल करता है.
किसी APEX के अपडेट का क्रम, PackageManager क्लास का इस्तेमाल करता है. यह क्रम इस तरह का होता है.
- APEX फ़ाइल को पैकेज इंस्टॉलर ऐप्लिकेशन, ADB या किसी अन्य सोर्स से डाउनलोड किया जाता है.
- पैकेज मैनेजर, इंस्टॉल करने की प्रोसेस शुरू करता है. फ़ाइल के APEX होने का पता चलने पर, पैकेज मैनेजर कंट्रोल को APEX मैनेजर को ट्रांसफ़र कर देता है.
- APEX मैनेजर, APEX फ़ाइल की पुष्टि करता है.
- APEX फ़ाइल की पुष्टि होने पर, APEX मैनेजर का इंटरनल डेटाबेस अपडेट किया जाता है, ताकि यह पता चल सके कि अगले बूट पर APEX फ़ाइल चालू हो जाएगी.
- पैकेज की पुष्टि होने पर, इंस्टॉल करने का अनुरोध करने वाले व्यक्ति को ब्रॉडकास्ट मिलता है.
- इंस्टॉलेशन जारी रखने के लिए, सिस्टम को रीबूट करना होगा.
अगले बूट पर, APEX मैनेजर शुरू होता है, इंटरनल डेटाबेस को पढ़ता है, और सूची में मौजूद हर APEX फ़ाइल के लिए ये काम करता है:
- APEX फ़ाइल की पुष्टि करता है.
- APEX फ़ाइल से लूपबैक डिवाइस बनाता है.
- यह लूपबैक डिवाइस के ऊपर, डिवाइस मैपर ब्लॉक डिवाइस बनाता है.
- डिवाइस मैपर ब्लॉक डिवाइस को किसी यूनीक पाथ (उदाहरण के लिए,
/apex/name@ver
) पर माउंट करता है.
जब इंटरनल डेटाबेस में दी गई सभी APEX फ़ाइलें माउंट हो जाती हैं, तो APEX मैनेजर, सिस्टम के अन्य कॉम्पोनेंट के लिए बाइंडर सेवा उपलब्ध कराता है. इससे, इंस्टॉल की गई APEX फ़ाइलों के बारे में जानकारी पाने के लिए क्वेरी की जा सकती है. उदाहरण के लिए, सिस्टम के अन्य कॉम्पोनेंट, डिवाइस में इंस्टॉल की गई APEX फ़ाइलों की सूची के बारे में क्वेरी कर सकते हैं. इसके अलावा, वे उस पाथ के बारे में भी क्वेरी कर सकते हैं जहां कोई खास APEX माउंट किया गया है, ताकि फ़ाइलों को ऐक्सेस किया जा सके.
APEX फ़ाइलें, APK फ़ाइलें होती हैं
APEX फ़ाइलें मान्य APK फ़ाइलें होती हैं, क्योंकि ये AndroidManifest.xml
फ़ाइल वाले, साइन किए गए ZIP संग्रह होते हैं. इनमें APK सिग्नेचर स्कीम का इस्तेमाल किया जाता है. इससे APEX फ़ाइलों को APK फ़ाइलों के लिए इन्फ़्रास्ट्रक्चर का इस्तेमाल करने में मदद मिलती है. जैसे, पैकेज इंस्टॉलर ऐप्लिकेशन, साइनिंग की सुविधा, और पैकेज मैनेजर.
APEX फ़ाइल में मौजूद AndroidManifest.xml
फ़ाइल बहुत छोटी होती है. इसमें पैकेज name
, versionCode
, और बेहतर टारगेटिंग के लिए targetSdkVersion
, minSdkVersion
, और maxSdkVersion
शामिल होते हैं. हालांकि, ये पैकेज ज़रूरी नहीं हैं. इस जानकारी की मदद से, पैकेज इंस्टॉलर ऐप्लिकेशन और ADB जैसे मौजूदा चैनलों से APEX फ़ाइलें डिलीवर की जा सकती हैं.
इस्तेमाल किए जा सकने वाले फ़ाइल टाइप
APEX फ़ॉर्मैट में ये फ़ाइल टाइप इस्तेमाल किए जा सकते हैं:
- नेटिव शेयर की गई लाइब्रेरी
- नेटिव एक्ज़ीक्यूटेबल
- JAR फ़ाइलें
- डेटा फ़ाइलें
- कॉन्फ़िगरेशन फ़ाइलें
इसका मतलब यह नहीं है कि APEX इन सभी फ़ाइल टाइप को अपडेट कर सकता है. किसी फ़ाइल टाइप को अपडेट किया जा सकता है या नहीं, यह इस बात पर निर्भर करता है कि प्लैटफ़ॉर्म क्या है और फ़ाइल टाइप के इंटरफ़ेस की परिभाषाएं कितनी स्थिर हैं.
हस्ताक्षर करने के विकल्प
APEX फ़ाइलों पर दो तरीकों से हस्ताक्षर किए जाते हैं. सबसे पहले, apex_payload.img
(खास तौर पर, apex_payload.img
में जोड़ा गया vbmeta डिस्क्रिप्टर) फ़ाइल को किसी कुंजी से साइन किया जाता है.
इसके बाद, पूरे APEX को APK सिग्नेचर स्कीम v3 का इस्तेमाल करके साइन किया जाता है. इस प्रोसेस में दो अलग-अलग बटन का इस्तेमाल किया जाता है.
डिवाइस पर, vbmeta डिस्क्रिप्टर पर हस्ताक्षर करने के लिए इस्तेमाल की गई निजी कुंजी से जुड़ी सार्वजनिक कुंजी इंस्टॉल की जाती है. APEX मैनेजर, इंस्टॉल किए जाने के लिए अनुरोध किए गए APEX की पुष्टि करने के लिए, सार्वजनिक पासकोड का इस्तेमाल करता है. हर APEX को अलग-अलग कुंजियों से साइन किया जाना चाहिए. साथ ही, इसे बिल्ड के समय और रनटाइम, दोनों पर लागू किया जाता है.
पहले से मौजूद पार्टीशन में APEX
APEX फ़ाइलें, /system
जैसे पहले से मौजूद पार्टीशन में मौजूद हो सकती हैं. डिवाइस का यह partition, पहले से ही dm-verity पर है. इसलिए, APEX फ़ाइलें सीधे तौर पर लूपबैक डिवाइस पर माउंट की जाती हैं.
अगर कोई APEX, पहले से मौजूद पार्टीशन में मौजूद है, तो APEX को अपडेट किया जा सकता है. इसके लिए, एक ही पैकेज के नाम वाला APEX पैकेज दें. साथ ही, यह भी ज़रूरी है कि पैकेज का वर्शन कोड, मौजूदा वर्शन कोड से बड़ा या उसके बराबर हो. नया APEX, /data
में सेव होता है. APK की तरह ही, इंस्टॉल किया गया नया वर्शन, पहले से मौजूद वर्शन की जगह ले लेता है. हालांकि, APK के उलट, APEX का नया वर्शन सिर्फ़ रीबूट करने के बाद चालू होता है.
Kernel से जुड़ी ज़रूरी शर्तें
Android डिवाइस पर APEX के मुख्य मॉड्यूल इस्तेमाल करने के लिए, Linux kernel की ये सुविधाएं ज़रूरी हैं: लूपबैक ड्राइवर और dm-verity. लूपबैक ड्राइवर, फ़ाइल सिस्टम इमेज को APEX मॉड्यूल में माउंट करता है और dm-verity, APEX मॉड्यूल की पुष्टि करता है.
APEX मॉड्यूल का इस्तेमाल करते समय, सिस्टम की परफ़ॉर्मेंस को बेहतर बनाने के लिए, लूपबैक ड्राइवर और dm-verity की परफ़ॉर्मेंस का ध्यान रखना ज़रूरी है.
कर्नेल के इस्तेमाल किए जा सकने वाले वर्शन
APEX के मुख्य मॉड्यूल, कर्नेल के 4.4 या इससे बाद के वर्शन वाले डिवाइसों पर काम करते हैं. APEX मॉड्यूल के साथ काम करने के लिए, Android 10 या इसके बाद के वर्शन के साथ लॉन्च होने वाले नए डिवाइसों में, कर्नेल का 4.9 या इसके बाद का वर्शन होना चाहिए.
ज़रूरी कर्नेल पैच
APEX मॉड्यूल के साथ काम करने के लिए ज़रूरी कर्नेल पैच, Android के सामान्य ट्री में शामिल होते हैं. APEX के साथ काम करने वाले पैच पाने के लिए, Android के सामान्य ट्री के नए वर्शन का इस्तेमाल करें.
Kernel वर्शन 4.4
यह वर्शन सिर्फ़ उन डिवाइसों के लिए उपलब्ध है जिन्हें Android 9 से Android 10 पर अपग्रेड किया गया है और जिन्हें APEX मॉड्यूल के साथ काम करना है. ज़रूरी पैच पाने के लिए, android-4.4
शाखा से डाउन-मर्ज करने का सुझाव दिया जाता है. यहां, कर्नेल वर्शन 4.4 के लिए ज़रूरी अलग-अलग पैच की सूची दी गई है.
- अपस्ट्रीम: loop: लॉजिकल ब्लॉक साइज़ बदलने के लिए ioctl जोड़ें (4.4)
- BACKPORT: block/loop: set hw_sectors (4.4)
- अपस्ट्रीम: loop: compat ioctl में LOOP_SET_BLOCK_SIZE जोड़ें (4.4)
- ANDROID: mnt: next_descendent को ठीक करना (4.4)
- ANDROID: mnt: remount should propagate to slaves of slaves (4.4)
- ANDROID: mnt: Propagate remount correctly (4.4)
- "ANDROID: dm verity: add minimum prefetch size" को पहले जैसा करें (4.4)
- अपस्ट्रीम: loop: offset या block_size में बदलाव होने पर कैश मेमोरी हटाएं (4.4)
कर्नेल वर्शन 4.9/4.14/4.19
कर्नेल के वर्शन 4.9/4.14/4.19 के लिए ज़रूरी पैच पाने के लिए, android-common
शाखा से डाउन-मर्ज करें.
कर्नेल कॉन्फ़िगरेशन के ज़रूरी विकल्प
इस सूची में, Android 10 में लॉन्च किए गए APEX मॉड्यूल के साथ काम करने के लिए, बेस कॉन्फ़िगरेशन की ज़रूरी शर्तें बताई गई हैं. जिन आइटम पर तारे का निशान (*) लगा है वे Android 9 और उससे पहले के वर्शन के लिए ज़रूरी शर्तें हैं.
(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support
कर्नेल कमांड-लाइन पैरामीटर की ज़रूरी शर्तें
APEX के साथ काम करने के लिए, पक्का करें कि कर्नेल कमांड-लाइन पैरामीटर इन ज़रूरी शर्तों को पूरा करते हों:
loop.max_loop
को सेट नहीं किया जाना चाहिएloop.max_part
की वैल्यू 8 से ज़्यादा नहीं होनी चाहिए
APEX बनाना
इस सेक्शन में, Android बिल्ड सिस्टम का इस्तेमाल करके APEX बनाने का तरीका बताया गया है.
यहां apex.test
नाम वाले APEX के लिए Android.bp
का उदाहरण दिया गया है.
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
// libc.so and libcutils.so are included in the apex
native_shared_libs: ["libc", "libcutils"],
binaries: ["vold"],
java_libs: ["core-all"],
prebuilts: ["my_prebuilt"],
compile_multilib: "both",
key: "apex.test.key",
certificate: "platform",
}
apex_manifest.json
उदाहरण:
{
"name": "com.android.example.apex",
"version": 1
}
file_contexts
उदाहरण:
(/.*)? u:object_r:system_file:s0
/sub(/.*)? u:object_r:sub_file:s0
/sub/file3 u:object_r:file3_file:s0
APEX में फ़ाइल टाइप और जगहें
फ़ाइल टाइप | APEX में जगह की जानकारी |
---|---|
शेयर की गई लाइब्रेरी | /lib और /lib64 (x86 में अनुवाद किए गए arm के लिए /lib/arm ) |
एक्ज़ीक्यूटेबल | /bin |
Java लाइब्रेरी | /javalib |
पहले से बने टेंप्लेट | /etc |
ट्रांसिटिव डिपेंडेंसी
APEX फ़ाइलों में, नेटिव शेयर की गई लाइब्रेरी या एक्सीक्यूटेबल की ट्रांज़िशन डिपेंडेंसी अपने-आप शामिल हो जाती हैं. उदाहरण के लिए, अगर libFoo
, libBar
पर निर्भर करता है, तो दोनों लाइब्रेरी तब शामिल की जाती हैं, जब native_shared_libs
प्रॉपर्टी में सिर्फ़ libFoo
शामिल हो.
एक से ज़्यादा एबीआई मैनेज करना
डिवाइस के प्राइमरी और सेकंडरी ऐप्लिकेशन बाइनरी इंटरफ़ेस (एबीआई) के लिए, native_shared_libs
प्रॉपर्टी इंस्टॉल करें. अगर कोई APEX, सिर्फ़ एक एबीआई (यानी सिर्फ़ 32 बिट या सिर्फ़ 64 बिट) वाले डिवाइसों को टारगेट करता है, तो उससे जुड़ी एबीआई वाली लाइब्रेरी ही इंस्टॉल की जाती हैं.
binaries
प्रॉपर्टी को सिर्फ़ डिवाइस के मुख्य एबीआई के लिए इंस्टॉल करें, जैसा कि यहां बताया गया है:
- अगर डिवाइस सिर्फ़ 32-बिट है, तो बाइनरी का सिर्फ़ 32-बिट वैरिएंट इंस्टॉल किया जाता है.
- अगर डिवाइस सिर्फ़ 64 बिट है, तो बाइनरी का सिर्फ़ 64-बिट वर्शन इंस्टॉल किया जाता है.
नेटिव लाइब्रेरी और बाइनरी के एबीआई पर बेहतर तरीके से कंट्रोल करने के लिए,
multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries]
प्रॉपर्टी का इस्तेमाल करें.
first
: यह डिवाइस के प्राइमरी एबीआई से मेल खाता है. यह बिनेरी के लिए डिफ़ॉल्ट है.lib32
: अगर डिवाइस पर 32-बिट एबीआई काम करता है, तो यह उससे मेल खाता है.lib64
: यह डिवाइस के 64-बिट एबीआई से मेल खाता है.prefer32
: अगर डिवाइस पर 32-बिट एबीआई काम करता है, तो यह उससे मेल खाता है. अगर 32-बिट एबीआई काम नहीं करता है, तो 64-बिट एबीआई से मैच करता है.both
: दोनों एबीआई से मैच करता है. यहnative_shared_libraries
के लिए डिफ़ॉल्ट तौर पर लागू होता है.
java
, libraries
, और prebuilts
प्रॉपर्टी, एबीआई पर निर्भर नहीं करती हैं.
यह उदाहरण ऐसे डिवाइस के लिए है जो 32/64 पर काम करता है और 32 को प्राथमिकता नहीं देता:
apex {
// other properties are omitted
native_shared_libs: ["libFoo"], // installed for 32 and 64
binaries: ["exec1"], // installed for 64, but not for 32
multilib: {
first: {
native_shared_libs: ["libBar"], // installed for 64, but not for 32
binaries: ["exec2"], // same as binaries without multilib.first
},
both: {
native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
binaries: ["exec3"], // installed for 32 and 64
},
prefer32: {
native_shared_libs: ["libX"], // installed for 32, but not for 64
},
lib64: {
native_shared_libs: ["libY"], // installed for 64, but not for 32
},
},
}
vbmeta साइनिंग
हर APEX को अलग-अलग कुंजियों से साइन करें. जब नई कुंजी की ज़रूरत हो, तो सार्वजनिक-निजी कुंजी का जोड़ा बनाएं और apex_key
मॉड्यूल बनाएं. पासकोड का इस्तेमाल करके APEX को हस्ताक्षर करने के लिए, key
प्रॉपर्टी का इस्तेमाल करें. सार्वजनिक पासकोड, avb_pubkey
नाम के साथ APEX में अपने-आप शामिल हो जाता है.
# create an rsa key pairopenssl genrsa -out foo.pem 4096
# extract the public key from the key pairavbtool extract_public_key --key foo.pem --output foo.avbpubkey
# in Android.bpapex_key { name: "apex.test.key", public_key: "foo.avbpubkey", private_key: "foo.pem", }
ऊपर दिए गए उदाहरण में, सार्वजनिक कुंजी (foo
) का नाम, कुंजी का आईडी बन जाता है. किसी APEX पर हस्ताक्षर करने के लिए इस्तेमाल की गई कुंजी का आईडी, APEX में लिखा होता है. रनटाइम के दौरान,
apexd
डिवाइस में मौजूद उसी आईडी की मदद से, सार्वजनिक पासकोड का इस्तेमाल करके APEX की पुष्टि करता है.
APEX साइनिंग
APKs पर जिस तरह से हस्ताक्षर किया जाता है उसी तरह से APEXs पर भी हस्ताक्षर करें. APEX को दो बार साइन करें. पहला, मिनिम फ़ाइल सिस्टम (apex_payload.img
फ़ाइल) के लिए और दूसरा, पूरी फ़ाइल के लिए.
फ़ाइल-लेवल पर किसी APEX में साइन करने के लिए, certificate
प्रॉपर्टी को इन तीन तरीकों में से किसी एक में सेट करें:
- सेट नहीं है: अगर कोई वैल्यू सेट नहीं की जाती है, तो APEX पर
PRODUCT_DEFAULT_DEV_CERTIFICATE
में मौजूद सर्टिफ़िकेट से हस्ताक्षर किया जाता है. अगर कोई फ़्लैग सेट नहीं किया गया है, तो पाथ डिफ़ॉल्ट रूप सेbuild/target/product/security/testkey
पर सेट हो जाता है. <name>
: APEX कोPRODUCT_DEFAULT_DEV_CERTIFICATE
की डायरेक्ट्री में मौजूद<name>
सर्टिफ़िकेट से हस्ताक्षर किया गया है.:<name>
: APEX को उस सर्टिफ़िकेट से साइन किया गया है जिसे<name>
नाम के Soong मॉड्यूल से तय किया गया है. सर्टिफ़िकेट मॉड्यूल को इस तरह से परिभाषित किया जा सकता है.
android_app_certificate {
name: "my_key_name",
certificate: "dir/cert",
// this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}
APEX इंस्टॉल करना
APEX इंस्टॉल करने के लिए, ADB का इस्तेमाल करें.
adb install apex_file_name
adb reboot
अगर apex_manifest.json
में supportsRebootlessUpdate
को true
पर सेट किया गया है और फ़िलहाल इंस्टॉल किया गया APEX इस्तेमाल नहीं किया जा रहा है (उदाहरण के लिए, इसमें मौजूद सभी सेवाएं बंद कर दी गई हैं), तो --force-non-staged
फ़्लैग की मदद से, रीबूट किए बिना नया APEX इंस्टॉल किया जा सकता है.
adb install --force-non-staged apex_file_name
APEX का इस्तेमाल करना
रीबूट होने के बाद, APEX को /apex/<apex_name>@<version>
directory में माउंट किया जाता है. एक ही APEX के कई वर्शन एक ही समय पर माउंट किए जा सकते हैं.
माउंट पाथ में से, सबसे नए वर्शन से जुड़ा पाथ, /apex/<apex_name>
पर बंधा-माउंट किया गया है.
क्लाइंट, APEX से फ़ाइलें पढ़ने या उन्हें चलाने के लिए, बाइंड-माउंटेड पाथ का इस्तेमाल कर सकते हैं.
आम तौर पर, APEX का इस्तेमाल इस तरह किया जाता है:
- डिवाइस शिप होने पर, OEM या ODM,
/system/apex
में APEX को पहले से लोड करता है. - APEX में मौजूद फ़ाइलों को
/apex/<apex_name>/
पाथ से ऐक्सेस किया जाता है. - जब
/data/apex
में APEX का अपडेट किया गया वर्शन इंस्टॉल किया जाता है, तो रीबूट करने के बाद पाथ, नए APEX पर ले जाता है.
APEX की मदद से किसी सेवा को अपडेट करना
APEX का इस्तेमाल करके किसी सेवा को अपडेट करने के लिए:
सिस्टम पार्टीशन में सेवा को 'अपडेट किया जा सकता है' के तौर पर मार्क करें. सेवा की परिभाषा में विकल्प
updatable
जोड़ें./system/etc/init/myservice.rc: service myservice /system/bin/myservice class core user system ... updatable
अपडेट की गई सेवा के लिए, एक नई
.rc
फ़ाइल बनाएं. मौजूदा सेवा को फिर से तय करने के लिए,override
विकल्प का इस्तेमाल करें./apex/my.apex/etc/init.rc: service myservice /apex/my.apex/bin/myservice class core user system ... override
सेवा की परिभाषाएं सिर्फ़ APEX की .rc
फ़ाइल में तय की जा सकती हैं. ऐक्शन ट्रिगर, APEX में काम नहीं करते.
अगर अपडेट की जा सकने वाली सेवा, एपीईक्स के चालू होने से पहले शुरू हो जाती है, तो एपीईक्स के चालू होने तक सेवा शुरू नहीं होती.
APEX अपडेट के साथ काम करने के लिए सिस्टम को कॉन्फ़िगर करना
APEX फ़ाइल अपडेट के साथ काम करने के लिए, नीचे दी गई सिस्टम प्रॉपर्टी को true
पर सेट करें.
<device.mk>:
PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true
BoardConfig.mk:
TARGET_FLATTEN_APEX := false
या सिर्फ़
<device.mk>:
$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
फ़्लैट किया गया APEX
लेगसी डिवाइसों के लिए, APEX के साथ पूरी तरह काम करने के लिए, पुराने कोर को अपडेट करना कभी-कभी असंभव या मुश्किल हो जाता है. उदाहरण के लिए, हो सकता है कि कर्नेल को CONFIG_BLK_DEV_LOOP=Y
के बिना बनाया गया हो. यह APEX में फ़ाइल सिस्टम इमेज को माउंट करने के लिए ज़रूरी है.
फ़्लैट किए गए APEX को खास तौर पर बनाया गया है. इसे लेगसी कर्नेल वाले डिवाइसों पर चालू किया जा सकता है. फ़्लैट किए गए APEX में मौजूद फ़ाइलें, सीधे तौर पर पहले से मौजूद पार्टीशन में मौजूद डायरेक्ट्री में इंस्टॉल होती हैं. उदाहरण के लिए, फ़्लैट किए गए APEX में lib/libFoo.so
, my.apex
में इंस्टॉल किया जाता है./system/apex/my.apex/lib/libFoo.so
फ़्लैट किए गए APEX को चालू करने के लिए, लूप डिवाइस की ज़रूरत नहीं होती. पूरी डायरेक्ट्री /system/apex/my.apex
, सीधे तौर पर /apex/name@ver
से बाइंड-माउंट की जाती है.
नेटवर्क से APEX के अपडेट किए गए वर्शन डाउनलोड करके, फ़्लैट किए गए APEX को अपडेट नहीं किया जा सकता. इसकी वजह यह है कि डाउनलोड किए गए APEX को फ़्लैट नहीं किया जा सकता. फ़्लैट किए गए APEX को सिर्फ़ सामान्य ओटीए (ओवर-द-एयर) के ज़रिए अपडेट किया जा सकता है.
फ़्लैट किया गया APEX, डिफ़ॉल्ट कॉन्फ़िगरेशन होता है. इसका मतलब है कि सभी APEX डिफ़ॉल्ट रूप से फ़्लैट होते हैं. हालांकि, अगर आपने APEX अपडेट के साथ काम करने के लिए, अपने डिवाइस को फ़्लैट किए गए APEX बनाने के लिए साफ़ तौर पर कॉन्फ़िगर किया है, तो ऐसा नहीं होगा. इस बारे में ऊपर बताया गया है.
किसी डिवाइस में, फ़्लैट किए गए और फ़्लैट नहीं किए गए APEX को एक साथ इस्तेमाल नहीं किया जा सकता. किसी डिवाइस में सभी APEX, फ़्लैट किए गए होने चाहिए या सभी फ़्लैट नहीं होने चाहिए.
यह खास तौर पर तब ज़रूरी होता है, जब Mainline जैसे प्रोजेक्ट के लिए, पहले से हस्ताक्षर किए गए APEX प्रीबिल्ट शिप किए जा रहे हों. जिन APEX को पहले से साइन नहीं किया गया है (यानी सोर्स से बनाए गए हैं) उन्हें भी फ़्लैट नहीं किया जाना चाहिए. साथ ही, उन पर सही कुंजियों से हस्ताक्षर किए जाने चाहिए. डिवाइस को updatable_apex.mk
से इनहेरिट करना चाहिए, जैसा कि एपीईएक्स की मदद से सेवा को अपडेट करने में बताया गया है.
कंप्रेस किए गए APEX
Android 12 और उसके बाद के वर्शन में, अपडेट किए जा सकने वाले APEX पैकेज के स्टोरेज पर पड़ने वाले असर को कम करने के लिए, APEX कंप्रेसन की सुविधा उपलब्ध है. APEX के अपडेट को इंस्टॉल करने के बाद, पहले से इंस्टॉल किए गए वर्शन का इस्तेमाल नहीं किया जाता. हालांकि, वह अब भी उतना ही जगह लेता है. वह स्पेस उपलब्ध नहीं रहेगा.
APEX कंप्रेस करने की सुविधा, रीड-ओनली वाले पार्टीशन (जैसे कि /system
पार्टीशन) पर, APEX फ़ाइलों के ज़्यादा कंप्रेस किए गए सेट का इस्तेमाल करके, स्टोरेज पर पड़ने वाले असर को कम करती है. Android 12 और उसके बाद के वर्शन, DEFLATE zip कंप्रेसन एल्गोरिदम का इस्तेमाल करते हैं.
कंप्रेस करने से, इनके लिए ऑप्टिमाइज़ेशन नहीं मिलता:
बूटस्ट्रैप APEX, जिन्हें बूट करने के क्रम में बहुत पहले माउंट करना ज़रूरी है.
ऐसे APEX जो अपडेट नहीं किए जा सकते. डेटा को कंप्रेस करने का फ़ायदा सिर्फ़ तब मिलता है, जब
/data
पार्टीशन पर APEX का अपडेट किया गया वर्शन इंस्टॉल हो. अपडेट किए जा सकने वाले APEX की पूरी सूची, मॉड्यूलर सिस्टम कॉम्पोनेंट पेज पर उपलब्ध है.डाइनैमिक शेयर किए गए लाइब्रेरी APEX.
apexd
, ऐसे APEX के दोनों वर्शन (पहले से इंस्टॉल और अपग्रेड किए गए) को हमेशा चालू रखता है. इसलिए, उन्हें कंप्रेस करने से कोई फ़ायदा नहीं होता.
कंप्रेस किया गया APEX फ़ाइल फ़ॉर्मैट
यह कंप्रेस की गई APEX फ़ाइल का फ़ॉर्मैट है.
दूसरी इमेज. कंप्रेस किया गया APEX फ़ाइल फ़ॉर्मैट
सबसे ऊपर के लेवल पर, कंप्रेस की गई APEX फ़ाइल एक ZIP फ़ाइल होती है. इसमें, मूल APEX फ़ाइल को 9 के कंप्रेस लेवल के साथ, डिफ़लेट किए गए फ़ॉर्म में रखा जाता है. साथ ही, अन्य फ़ाइलों को बिना कंप्रेस किए सेव किया जाता है.
APEX फ़ाइल में चार फ़ाइलें होती हैं:
original_apex
: 9 के कंप्रेस लेवल के साथ डिफ़लेट की गई यह ओरिजनल, बिना कंप्रेस की गई APEX फ़ाइल है.apex_manifest.pb
: सिर्फ़ सेव किया गयाAndroidManifest.xml
: सिर्फ़ सेव किया गयाapex_pubkey
: सिर्फ़ सेव किया गया
apex_manifest.pb
, AndroidManifest.xml
, और apex_pubkey
फ़ाइलें, original_apex
में मौजूद फ़ाइलों की कॉपी हैं.
कंप्रेस किया गया APEX बनाना
system/apex/tools
पर मौजूद apex_compression_tool.py
टूल का इस्तेमाल करके, कंप्रेस किया गया APEX बनाया जा सकता है.
बिल्ड सिस्टम में, APEX कंप्रेसन से जुड़े कई पैरामीटर उपलब्ध हैं.
Android.bp
में, किसी APEX फ़ाइल को कंप्रेस किया जा सकता है या नहीं, यह compressible
प्रॉपर्टी से कंट्रोल किया जाता है:
apex {
name: "apex.test",
manifest: "apex_manifest.json",
file_contexts: "file_contexts",
compressible: true,
}
PRODUCT_COMPRESSED_APEX
प्रॉडक्ट फ़्लैग से यह कंट्रोल होता है कि सोर्स से बनाई गई सिस्टम इमेज में, कंप्रेस की गई APEX फ़ाइलें होनी चाहिए या नहीं.
स्थानीय एक्सपेरिमेंट के लिए, OVERRIDE_PRODUCT_COMPRESSED_APEX=
को true
पर सेट करके, APEX को कंप्रेस करने के लिए बिल्ड को फ़ोर्स किया जा सकता है.
बिल्ड सिस्टम से जनरेट की गई कंप्रेस की गई APEX फ़ाइलों में .capex
एक्सटेंशन होता है.
इस एक्सटेंशन की मदद से, APEX फ़ाइल के कंप्रेस किए गए और कंप्रेस नहीं किए गए वर्शन के बीच आसानी से अंतर किया जा सकता है.
काम करने वाले कंप्रेस करने के एल्गोरिदम
Android 12 पर सिर्फ़ deflate-zip कंप्रेसन काम करता है.
बूट के दौरान, कंप्रेस की गई APEX फ़ाइल को चालू करना
किसी कंप्रेस किए गए APEX को चालू करने से पहले, उसमें मौजूद original_apex
फ़ाइल को /data/apex/decompressed
डायरेक्ट्री में डिकंप्रेस किया जाता है. इस प्रोसेस के बाद, डिकंप्रेस की गई APEX फ़ाइल को /data/apex/active
डायरेक्ट्री से हार्ड-लिंक किया जाता है.
ऊपर बताई गई प्रोसेस को समझने के लिए, नीचे दिया गया उदाहरण देखें.
/system/apex/com.android.foo.capex
को एक कॉम्प्रेस किए गए APEX के तौर पर लें, जिसे वर्शन कोड 37 के साथ चालू किया जा रहा है.
/system/apex/com.android.foo.capex
में मौजूदoriginal_apex
फ़ाइल को/data/apex/decompressed/com.android.foo@37.apex
में डिकंप्रेस किया जाता है.restorecon /data/apex/decompressed/com.android.foo@37.apex
की पुष्टि करने के लिए किया जाता है कि उसमें सही SELinux लेबल है./data/apex/decompressed/com.android.foo@37.apex
की पुष्टि करने के लिए, इसकी जांच की जाती है:apexd
,/data/apex/decompressed/com.android.foo@37.apex
में बंडल की गई सार्वजनिक कुंजी की जांच करता है, ताकि यह पुष्टि की जा सके कि वह/system/apex/com.android.foo.capex
में बंडल की गई कुंजी से मेल खाती है./data/apex/decompressed/com.android.foo@37.apex
फ़ाइल को/data/apex/active/com.android.foo@37.apex
डायरेक्ट्री से हार्ड-लिंक किया गया है.- कंप्रेस नहीं की गई APEX फ़ाइलों के लिए, नियमित तौर पर चालू करने का लॉजिक
/data/apex/active/com.android.foo@37.apex
पर लागू होता है.
ओटीए के साथ इंटरैक्शन
कंप्रेस की गई APEX फ़ाइलों का असर, ओटीए डिलीवरी और ऐप्लिकेशन पर पड़ता है. ओटीए अपडेट में, संपीड़ित APEX फ़ाइल हो सकती है. यह फ़ाइल, डिवाइस पर चालू वर्शन से ज़्यादा वर्शन लेवल वाली हो सकती है. इसलिए, ओटीए अपडेट लागू करने के लिए, डिवाइस को रीबूट करने से पहले कुछ खाली जगह सुरक्षित रखी जानी चाहिए.
ओटीए सिस्टम के साथ काम करने के लिए, apexd
ये दो बाइंडर एपीआई एक्सपोज़र करता है:
calculateSizeForCompressedApex
- किसी OTA पैकेज में APEX फ़ाइलों को डिकंप्रेस करने के लिए ज़रूरी साइज़ का हिसाब लगाता है. इसका इस्तेमाल यह पुष्टि करने के लिए किया जा सकता है कि ओटीए डाउनलोड होने से पहले, डिवाइस में ज़रूरत के मुताबिक जगह है या नहीं.reserveSpaceForCompressedApex
- आने वाले समय में इस्तेमाल करने के लिए, डिस्क पर जगह रिज़र्व करता है.apexd
इसका इस्तेमाल, ओटीए पैकेज में मौजूद कंप्रेस की गई APEX फ़ाइलों को डिकंप्रेस करने के लिए करता है.
A/B ओटीए अपडेट के मामले में, apexd
, पोस्ट-इंस्टॉल ओटीए रूटीन के हिस्से के तौर पर, बैकग्राउंड में डेटा को डिकंप्रेस करने की कोशिश करता है. अगर डिकंप्रेस नहीं हो पाता है, तो apexd
, ओटीए अपडेट लागू करने के दौरान डिकंप्रेस करता है.
APEX डेवलप करते समय, इन विकल्पों पर विचार किया गया
AOSP ने APEX फ़ाइल फ़ॉर्मैट डिज़ाइन करते समय, इन विकल्पों पर विचार किया था. साथ ही, यह भी बताया है कि इन विकल्पों को शामिल या बाहर क्यों किया गया.
सामान्य पैकेज मैनेजमेंट सिस्टम
Linux डिस्ट्रिब्यूशन में dpkg
और rpm
जैसे पैकेज मैनेजमेंट सिस्टम होते हैं. ये सिस्टम बेहतर, मज़बूत, और भरोसेमंद होते हैं. हालांकि, इन्हें APEX के लिए इस्तेमाल नहीं किया गया, क्योंकि ये इंस्टॉल होने के बाद पैकेज को सुरक्षित नहीं रख सकते. पुष्टि सिर्फ़ तब की जाती है, जब पैकेज इंस्टॉल किए जा रहे हों.
हमलावर, इंस्टॉल किए गए पैकेज की पूरी सुरक्षा को बिना किसी की जानकारी के तोड़ सकते हैं. यह Android के लिए एक रिग्रेशन है, जहां सिस्टम के सभी कॉम्पोनेंट, सिर्फ़ पढ़ने के लिए उपलब्ध फ़ाइल सिस्टम में सेव किए गए थे. इनकी पूरी सुरक्षा, हर I/O के लिए dm-verity की मदद से की जाती थी. सिस्टम कॉम्पोनेंट में किसी भी तरह का बदलाव करने पर पाबंदी होनी चाहिए या उसे पता लगाया जा सकता हो, ताकि डिवाइस को बूट होने से रोका जा सके.
डेटा को सुरक्षित रखने के लिए dm-crypt
APEX कंटेनर में मौजूद फ़ाइलें, पहले से मौजूद सेगमेंट (उदाहरण के लिए, /system
सेगमेंट) से होती हैं. ये dm-verity की मदद से सुरक्षित होती हैं. इन सेगमेंट के माउंट होने के बाद भी, इन फ़ाइलों में कोई बदलाव नहीं किया जा सकता. फ़ाइलों को एक ही लेवल की सुरक्षा देने के लिए, APEX में मौजूद सभी फ़ाइलों को फ़ाइल सिस्टम इमेज में सेव किया जाता है. यह इमेज, हैश ट्री और vbmeta डिस्क्रिप्टर के साथ जोड़ी जाती है. dm-verity के बिना, /data
पार्टीशन में मौजूद APEX में अनचाहे बदलाव हो सकते हैं. ये बदलाव, पुष्टि और इंस्टॉल होने के बाद किए जाते हैं.
असल में, /data
पार्टिशन को एन्क्रिप्शन लेयर से भी सुरक्षित किया जाता है. जैसे, dm-crypt. हालांकि, इससे डेटा में छेड़छाड़ होने से कुछ हद तक सुरक्षा मिलती है, लेकिन इसका मुख्य मकसद निजता बनाए रखना है, न कि डेटा की सुरक्षा करना. जब कोई हमलावर /data
partition का ऐक्सेस हासिल कर लेता है, तो उसे और सुरक्षा नहीं दी जा सकती. यह /system
partition में मौजूद सिस्टम के हर कॉम्पोनेंट की तुलना में फिर से एक कदम पीछे है.
dm-verity के साथ-साथ APEX फ़ाइल में मौजूद हैश ट्री, कॉन्टेंट को एक ही लेवल पर सुरक्षित रखता है.
/system से /apex पर पाथ रीडायरेक्ट करना
APEX में पैकेज की गई सिस्टम कॉम्पोनेंट फ़ाइलों को /apex/<name>/lib/libfoo.so
जैसे नए पाथ से ऐक्सेस किया जा सकता है. जब फ़ाइलें /system
पार्टिशन का हिस्सा थीं, तब उन्हें /system/lib/libfoo.so
जैसे पाथ से ऐक्सेस किया जा सकता था. किसी APEX फ़ाइल (अन्य APEX फ़ाइलों या प्लैटफ़ॉर्म) के क्लाइंट को नए पाथ का इस्तेमाल करना होगा. पाथ में बदलाव होने की वजह से, आपको मौजूदा कोड को अपडेट करना पड़ सकता है.
पाथ में बदलाव से बचने का एक तरीका यह है कि /system
पार्टीशन पर, APEX फ़ाइल में मौजूद फ़ाइल कॉन्टेंट को ओवरले किया जाए. हालांकि, Android टीम ने /system
पार्टीशन पर फ़ाइलों को ओवरले नहीं करने का फ़ैसला लिया है. ऐसा इसलिए किया गया है, क्योंकि ओवरले की जा रही फ़ाइलों की संख्या बढ़ने पर, परफ़ॉर्मेंस पर असर पड़ सकता है. ऐसा हो सकता है कि फ़ाइलें एक के बाद एक स्टैक की गई हों.
फ़ाइल ऐक्सेस करने वाले फ़ंक्शन, जैसे कि open
, stat
, और readlink
को हाइजैक करने का भी विकल्प था. इससे /system
से शुरू होने वाले पाथ, /apex
में मौजूद उनके संबंधित पाथ पर रीडायरेक्ट हो जाते थे. Android टीम ने इस विकल्प को अस्वीकार कर दिया है, क्योंकि पाथ स्वीकार करने वाले सभी फ़ंक्शन को बदलना मुमकिन नहीं है.
उदाहरण के लिए, कुछ ऐप्लिकेशन Bionic को स्टैटिक तौर पर लिंक करते हैं, जो फ़ंक्शन लागू करता है.
ऐसे मामलों में, उन ऐप्लिकेशन को रीडायरेक्ट नहीं किया जाता.