एपेक्स फ़ाइल प्रारूप

एंड्रॉइड पोनी एक्सप्रेस (एपेक्स) कंटेनर प्रारूप एंड्रॉइड 10 में पेश किया गया था और इसका उपयोग निचले स्तर के सिस्टम मॉड्यूल के लिए इंस्टॉल फ्लो में किया जाता है। यह प्रारूप उन सिस्टम घटकों के अपडेट की सुविधा प्रदान करता है जो मानक एंड्रॉइड एप्लिकेशन मॉडल में फिट नहीं होते हैं। कुछ उदाहरण घटक देशी सेवाएं और पुस्तकालय, हार्डवेयर अमूर्त परतें ( एचएएल ), रनटाइम ( एआरटी ), और कक्षा पुस्तकालय हैं।

शब्द "एपेक्स" एक एपेक्स फ़ाइल को भी संदर्भित कर सकता है।

पृष्ठभूमि

हालांकि एंड्रॉइड पैकेज इंस्टॉलर ऐप (जैसे कि Google Play Store ऐप) के माध्यम से मानक ऐप मॉडल (उदाहरण के लिए, सेवाओं, गतिविधियों) के भीतर फिट होने वाले मॉड्यूल के अपडेट का समर्थन करता है, निचले स्तर के ओएस घटकों के लिए एक समान मॉडल का उपयोग करने में निम्नलिखित कमियां हैं:

  • एपीके-आधारित मॉड्यूल का उपयोग बूट अनुक्रम में जल्दी नहीं किया जा सकता है। पैकेज मैनेजर ऐप्स के बारे में जानकारी का केंद्रीय भंडार है और इसे केवल गतिविधि प्रबंधक से शुरू किया जा सकता है, जो बूट प्रक्रिया के बाद के चरण में तैयार हो जाता है।
  • एपीके प्रारूप (विशेष रूप से मेनिफेस्ट) एंड्रॉइड ऐप्स के लिए डिज़ाइन किया गया है और सिस्टम मॉड्यूल हमेशा उपयुक्त नहीं होते हैं।

डिज़ाइन

यह खंड APEX फ़ाइल स्वरूप के उच्च-स्तरीय डिज़ाइन और APEX प्रबंधक का वर्णन करता है, जो एक ऐसी सेवा है जो APEX फ़ाइलों का प्रबंधन करती है।

एपेक्स के लिए यह डिज़ाइन क्यों चुना गया था, इस बारे में अधिक जानकारी के लिए, एपेक्स विकसित करते समय विचार किए गए विकल्प देखें।

शीर्ष प्रारूप

यह एक एपेक्स फ़ाइल का प्रारूप है।

अपैक्स फ़ाइल स्वरूप

चित्र 1. एपेक्स फ़ाइल स्वरूप

शीर्ष स्तर पर, एक एपेक्स फ़ाइल एक ज़िप फ़ाइल होती है जिसमें फ़ाइलें असंपीड़ित और 4 केबी की सीमाओं पर स्थित होती हैं।

एपेक्स फाइल में चार फाइलें हैं:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

apex_manifest.json फ़ाइल में पैकेज का नाम और संस्करण होता है, जो एक एपेक्स फ़ाइल की पहचान करता है।

AndroidManifest.xml फ़ाइल APEX फ़ाइल को एपीके-संबंधित टूल और बुनियादी ढांचे जैसे ADB, PackageManager, और पैकेज इंस्टॉलर ऐप (जैसे Play Store) का उपयोग करने की अनुमति देती है। उदाहरण के लिए, एपेक्स फ़ाइल फ़ाइल से मूल मेटाडेटा का निरीक्षण करने के लिए aapt जैसे मौजूदा टूल का उपयोग कर सकती है। फ़ाइल में पैकेज का नाम और संस्करण की जानकारी है। यह जानकारी आम तौर पर apex_manifest.json में भी उपलब्ध होती है।

एपेक्स से निपटने वाले नए कोड और सिस्टम के लिए AndroidManifest.xml पर apex_manifest.json की सिफारिश की जाती है। AndroidManifest.xml में अतिरिक्त लक्ष्यीकरण जानकारी हो सकती है जिसका उपयोग मौजूदा ऐप प्रकाशन टूल द्वारा किया जा सकता है।

apex_payload.img dm-verity द्वारा समर्थित एक ext4 फ़ाइल सिस्टम छवि है। छवि को लूपबैक डिवाइस के माध्यम से रनटाइम पर माउंट किया जाता है। विशेष रूप से, हैश ट्री और मेटाडेटा ब्लॉक libavb लाइब्रेरी का उपयोग करके बनाए जाते हैं। फ़ाइल सिस्टम पेलोड को पार्स नहीं किया गया है (क्योंकि छवि जगह में माउंट करने योग्य होनी चाहिए)। apex_payload.img फ़ाइल के अंदर नियमित फ़ाइलें शामिल हैं।

apex_pubkey फ़ाइल सिस्टम छवि पर हस्ताक्षर करने के लिए उपयोग की जाने वाली सार्वजनिक कुंजी है। रनटाइम पर, यह कुंजी सुनिश्चित करती है कि डाउनलोड किए गए एपेक्स को उसी इकाई के साथ हस्ताक्षरित किया गया है जो अंतर्निहित विभाजनों में समान एपेक्स पर हस्ताक्षर करता है।

शीर्ष प्रबंधक

एपेक्स प्रबंधक (या apexd ) एपेक्स फाइलों को सत्यापित करने, स्थापित करने और अनइंस्टॉल करने के लिए जिम्मेदार एक स्टैंडअलोन मूल प्रक्रिया है। यह प्रक्रिया शुरू की गई है और बूट अनुक्रम में जल्दी तैयार है। एपेक्स फाइलें आमतौर पर डिवाइस पर /system/apex के तहत पहले से इंस्टॉल होती हैं। यदि कोई अद्यतन उपलब्ध नहीं है, तो APEX प्रबंधक इन पैकेजों का उपयोग करने में चूक करता है।

APEX का अद्यतन क्रम PackageManager वर्ग का उपयोग करता है और यह इस प्रकार है।

  1. एक एपेक्स फ़ाइल एक पैकेज इंस्टालर ऐप, एडीबी, या अन्य स्रोत के माध्यम से डाउनलोड की जाती है।
  2. पैकेज मैनेजर इंस्टॉलेशन प्रक्रिया शुरू करता है। यह पहचानने पर कि फ़ाइल एक एपेक्स है, पैकेज मैनेजर एपेक्स मैनेजर को नियंत्रण स्थानांतरित करता है।
  3. एपेक्स मैनेजर एपेक्स फाइल की पुष्टि करता है।
  4. यदि APEX फ़ाइल सत्यापित है, तो APEX प्रबंधक के आंतरिक डेटाबेस को यह दर्शाने के लिए अद्यतन किया जाता है कि APEX फ़ाइल अगले बूट पर सक्रिय हो जाती है।
  5. सफल पैकेज सत्यापन पर इंस्टॉल अनुरोधकर्ता को प्रसारण प्राप्त होता है।
  6. संस्थापन जारी रखने के लिए, सिस्टम को रिबूट किया जाना चाहिए।
  7. अगले बूट पर, एपेक्स प्रबंधक शुरू होता है, आंतरिक डेटाबेस पढ़ता है, और सूचीबद्ध प्रत्येक एपेक्स फ़ाइल के लिए निम्नलिखित करता है:

    1. एपेक्स फ़ाइल की पुष्टि करता है।
    2. एपेक्स फ़ाइल से लूपबैक डिवाइस बनाता है।
    3. लूपबैक डिवाइस के शीर्ष पर डिवाइस मैपर ब्लॉक डिवाइस बनाता है।
    4. डिवाइस मैपर ब्लॉक डिवाइस को एक अद्वितीय पथ पर माउंट करता है (उदाहरण के लिए, /apex/ name @ ver )।

जब आंतरिक डेटाबेस में सूचीबद्ध सभी एपेक्स फाइलें माउंट की जाती हैं, तो एपेक्स प्रबंधक स्थापित एपेक्स फाइलों के बारे में जानकारी पूछने के लिए अन्य सिस्टम घटकों के लिए एक बाइंडर सेवा प्रदान करता है। उदाहरण के लिए, अन्य सिस्टम घटक डिवाइस में स्थापित एपेक्स फाइलों की सूची को क्वेरी कर सकते हैं या सटीक पथ को क्वेरी कर सकते हैं जहां एक विशिष्ट एपेक्स माउंट किया गया है, ताकि फाइलों तक पहुंचा जा सके।

एपेक्स फाइलें एपीके फाइलें हैं

APEX फ़ाइलें मान्य एपीके फ़ाइलें हैं क्योंकि वे एक AndroidManifest.xml फ़ाइल वाले ज़िप संग्रह (एपीके हस्ताक्षर योजना का उपयोग करके) पर हस्ताक्षर किए हैं। यह एपेक्स फाइलों को एपीके फाइलों के लिए बुनियादी ढांचे का उपयोग करने की अनुमति देता है, जैसे कि पैकेज इंस्टॉलर ऐप, साइनिंग यूटिलिटी और पैकेज मैनेजर।

APEX फ़ाइल के अंदर AndroidManifest.xml फ़ाइल न्यूनतम होती है, जिसमें सूक्ष्म लक्ष्यीकरण के लिए पैकेज name , versionCode , और वैकल्पिक targetSdkVersion , minSdkVersion , और maxSdkVersion हैं। यह जानकारी एपेक्स फाइलों को मौजूदा चैनलों जैसे पैकेज इंस्टालर ऐप और एडीबी के माध्यम से वितरित करने की अनुमति देती है।

फ़ाइल प्रकार समर्थित

एपेक्स प्रारूप इन फ़ाइल प्रकारों का समर्थन करता है:

  • मूल निवासी साझा libs
  • मूल निष्पादन योग्य
  • जार फ़ाइलें
  • डेटा की फ़ाइलें
  • कॉन्फ़िग फ़ाइलें

इसका मतलब यह नहीं है कि एपेक्स इन सभी फ़ाइल प्रकारों को अपडेट कर सकता है। फ़ाइल प्रकार को अद्यतन किया जा सकता है या नहीं यह प्लेटफ़ॉर्म पर निर्भर करता है और फ़ाइल प्रकारों के लिए इंटरफ़ेस की परिभाषा कितनी स्थिर है।

हस्ताक्षर

एपेक्स फाइलों पर दो तरह से हस्ताक्षर किए जाते हैं। सबसे पहले, apex_payload.img (विशेष रूप से, एपेक्स_पेलोड.आईएमजी में संलग्न apex_payload.img डिस्क्रिप्टर) फ़ाइल को एक कुंजी के साथ हस्ताक्षरित किया जाता है। फिर, एपीके सिग्नेचर स्कीम v3 का उपयोग करके संपूर्ण एपेक्स पर हस्ताक्षर किए जाते हैं। इस प्रक्रिया में दो अलग-अलग कुंजियों का उपयोग किया जाता है।

डिवाइस की तरफ, vbmeta डिस्क्रिप्टर पर हस्ताक्षर करने के लिए उपयोग की जाने वाली निजी कुंजी से संबंधित एक सार्वजनिक कुंजी स्थापित है। एपेक्स प्रबंधक उन एपेक्स को सत्यापित करने के लिए सार्वजनिक कुंजी का उपयोग करता है जिन्हें स्थापित करने का अनुरोध किया जाता है। प्रत्येक एपेक्स को अलग-अलग चाबियों के साथ हस्ताक्षरित किया जाना चाहिए और निर्माण समय और रनटाइम दोनों पर लागू किया जाता है।

बिल्ट-इन पार्टिशन में एपेक्स

APEX फाइलें अंतर्निर्मित विभाजनों जैसे /system में स्थित हो सकती हैं। विभाजन पहले से ही dm-verity से अधिक है, इसलिए APEX फ़ाइलें सीधे लूपबैक डिवाइस पर माउंट की जाती हैं।

यदि एक एपेक्स एक अंतर्निर्मित विभाजन में मौजूद है, तो एपेक्स को एक ही पैकेज नाम के साथ एक एपेक्स पैकेज प्रदान करके और संस्करण कोड से अधिक या उसके बराबर अद्यतन किया जा सकता है। नया एपेक्स /data में संग्रहीत है और, एपीके के समान, नया स्थापित संस्करण अंतर्निहित विभाजन में पहले से मौजूद संस्करण को छायांकित करता है। लेकिन एपीके के विपरीत, एपेक्स का नया स्थापित संस्करण रिबूट के बाद ही सक्रिय होता है।

कर्नेल आवश्यकताएं

एंड्रॉइड डिवाइस पर एपेक्स मेनलाइन मॉड्यूल का समर्थन करने के लिए, निम्नलिखित लिनक्स कर्नेल सुविधाओं की आवश्यकता होती है: लूपबैक ड्राइवर और डीएम-वेरिटी। लूपबैक ड्राइवर फ़ाइल सिस्टम छवि को एपेक्स मॉड्यूल में माउंट करता है और डीएम-वेरिटी एपेक्स मॉड्यूल की पुष्टि करता है।

APEX मॉड्यूल का उपयोग करते समय अच्छे सिस्टम प्रदर्शन को प्राप्त करने के लिए लूपबैक ड्राइवर और dm-verity का प्रदर्शन महत्वपूर्ण है।

समर्थित कर्नेल संस्करण

एपेक्स मेनलाइन मॉड्यूल कर्नेल संस्करण 4.4 या उच्चतर का उपयोग करने वाले उपकरणों पर समर्थित हैं। एंड्रॉइड 10 या उच्चतर के साथ लॉन्च होने वाले नए उपकरणों को एपेक्स मॉड्यूल का समर्थन करने के लिए कर्नेल संस्करण 4.9 या उच्चतर का उपयोग करना चाहिए।

आवश्यक कर्नेल पैच

एपेक्स मॉड्यूल का समर्थन करने के लिए आवश्यक कर्नेल पैच एंड्रॉइड कॉमन ट्री में शामिल हैं। एपेक्स का समर्थन करने के लिए पैच प्राप्त करने के लिए, एंड्रॉइड कॉमन ट्री के नवीनतम संस्करण का उपयोग करें।

कर्नेल संस्करण 4.4

यह संस्करण केवल उन उपकरणों के लिए समर्थित है जो Android 9 से Android 10 में अपग्रेड किए गए हैं और APEX मॉड्यूल का समर्थन करना चाहते हैं। आवश्यक पैच प्राप्त करने के लिए, android-4.4 शाखा से डाउन-मर्ज की जोरदार अनुशंसा की जाती है। कर्नेल संस्करण 4.4 के लिए आवश्यक व्यक्तिगत पैच की सूची निम्नलिखित है।

  • UPSTREAM: लूप: तार्किक ब्लॉक आकार बदलने के लिए ioctl जोड़ें ( 4.4 )
  • बैकपोर्ट: ब्लॉक/लूप: सेट hw_sectors ( 4.4 )
  • UPSTREAM: लूप: LOOP_SET_BLOCK_SIZE को कॉम्पेट ioctl ( 4.4 ) में जोड़ें
  • Android: mnt: next_descendent को ठीक करें ( 4.4 )
  • ANDROID: mnt: remount को दासों के दासों को प्रचारित करना चाहिए ( 4.4 )
  • एंड्रॉइड: एमएनटी: रीमाउंट को सही ढंग से प्रचारित करें ( 4.4 )
  • "एंड्रॉइड: डीएम सत्यता: न्यूनतम प्रीफेच आकार जोड़ें" वापस लाएं ( 4.4 )
  • UPSTREAM: लूप: ऑफ़सेट या ब्लॉक_साइज़ बदलने पर कैश ड्रॉप करें ( 4.4 )

कर्नेल संस्करण 4.9/4.14/4.19

कर्नेल संस्करण 4.9 / 4.14 / 4.19 के लिए आवश्यक पैच प्राप्त करने के लिए, android-common शाखा से डाउन-मर्ज करें।

आवश्यक कर्नेल विन्यास विकल्प

निम्न सूची एंड्रॉइड 10 में पेश किए गए एपेक्स मॉड्यूल का समर्थन करने के लिए आधार कॉन्फ़िगरेशन आवश्यकताओं को दिखाती है। तारांकन (*) वाले आइटम एंड्रॉइड 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

कर्नेल कमांड-लाइन पैरामीटर आवश्यकताएँ

एपेक्स का समर्थन करने के लिए, सुनिश्चित करें कि कर्नेल कमांड-लाइन पैरामीटर निम्नलिखित आवश्यकताओं को पूरा करते हैं:

  • loop.max_loop सेट नहीं होना चाहिए
  • loop.max_part <= 8 . होना चाहिए

एक एपेक्स का निर्माण

यह खंड वर्णन करता है कि एंड्रॉइड बिल्ड सिस्टम का उपयोग करके एपेक्स कैसे बनाया जाए। निम्नलिखित एपेक्स नाम के apex.test के लिए 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

एपेक्स में फ़ाइल प्रकार और स्थान

फाइल का प्रकार एपेक्स में स्थान
साझा पुस्तकालय /lib और /lib64 ( /lib/arm x86 में अनुवादित भुजा के लिए)
निष्पादनयोग्य /bin
जावा पुस्तकालय /javalib
पूर्वनिर्मित /etc

सकर्मक निर्भरता

एपेक्स फाइलों में स्वचालित रूप से देशी साझा libs या निष्पादन योग्य की ट्रांजिटिव निर्भरताएं शामिल होती हैं। उदाहरण के लिए, यदि libFoo libBar निर्भर करता है, तो दो libs तब शामिल होते हैं जब केवल libFoo को native_shared_libs प्रॉपर्टी में सूचीबद्ध किया जाता है।

एकाधिक एबीआई को संभालना

डिवाइस के प्राइमरी और सेकेंडरी एप्लिकेशन बाइनरी इंटरफेस (एबीआई) दोनों के लिए native_shared_libs प्रॉपर्टी इंस्टॉल करें। यदि कोई एपेक्स एकल एबीआई (अर्थात, केवल 32 बिट या केवल 64 बिट) वाले उपकरणों को लक्षित करता है, तो केवल संबंधित एबीआई वाले पुस्तकालय स्थापित किए जाते हैं।

नीचे बताए अनुसार डिवाइस के केवल प्राथमिक ABI के लिए binaries प्रॉपर्टी इंस्टॉल करें:

  • यदि डिवाइस केवल 32 बिट का है, तो बाइनरी का केवल 32-बिट संस्करण स्थापित किया गया है।
  • यदि डिवाइस केवल 64 बिट का है, तो बाइनरी का केवल 64-बिट संस्करण स्थापित है।

देशी पुस्तकालयों और बायनेरिज़ के एबीआई पर बारीक नियंत्रण जोड़ने के लिए, multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] का उपयोग करें।

  • first : डिवाइस के प्राथमिक ABI से मेल खाता है। यह बायनेरिज़ के लिए डिफ़ॉल्ट है।
  • lib32 : समर्थित होने पर डिवाइस के 32-बिट ABI से मेल खाता है।
  • lib64 : डिवाइस के 64-बिट एबीआई से मेल खाता है, यह समर्थित है।
  • prefer32 32: समर्थित होने पर डिवाइस के 32-बिट एबीआई से मेल खाता है। यदि 32-बिट ABI समर्थित नहीं है, तो 64-बिट ABI से मेल खाता है।
  • 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_key मॉड्यूल बनाएं। कुंजी का उपयोग करके एपेक्स पर हस्ताक्षर करने के लिए key संपत्ति का उपयोग करें। सार्वजनिक कुंजी स्वचालित रूप से एपेक्स में avb_pubkey नाम से शामिल हो जाती है।

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

उपरोक्त उदाहरण में, सार्वजनिक कुंजी का नाम ( foo ) कुंजी की आईडी बन जाता है। एपेक्स पर हस्ताक्षर करने के लिए इस्तेमाल की जाने वाली कुंजी की आईडी एपेक्स में लिखी जाती है। रनटाइम पर, apexd डिवाइस में समान आईडी वाली सार्वजनिक कुंजी का उपयोग करके एपेक्स को सत्यापित करता है।

ज़िप हस्ताक्षर

एपेक्स पर उसी तरह हस्ताक्षर करें जैसे आप एपीके पर हस्ताक्षर करते हैं। शीर्ष पर दो बार हस्ताक्षर करें; एक बार मिनी फाइल सिस्टम के लिए ( apex_payload.img फाइल) और एक बार पूरी फाइल के लिए।

फ़ाइल-स्तर पर एक एपेक्स पर हस्ताक्षर करने के लिए, certificate संपत्ति को इन तीन तरीकों में से एक में सेट करें:

  • सेट नहीं: यदि कोई मान सेट नहीं है, तो PRODUCT_DEFAULT_DEV_CERTIFICATE पर स्थित प्रमाणपत्र के साथ शीर्ष पर हस्ताक्षर किए गए हैं। यदि कोई ध्वज सेट नहीं है, तो पथ डिफ़ॉल्ट रूप से build/target/product/security/testkey
  • <name> : APEX पर PRODUCT_DEFAULT_DEV_CERTIFICATE की ही निर्देशिका में <name> प्रमाणपत्र के साथ हस्ताक्षर किए गए हैं।
  • :<name> : एपेक्स पर उस प्रमाणपत्र के साथ हस्ताक्षर किया गया है जिसे <name> के सूंग मॉड्यूल द्वारा परिभाषित किया गया है। प्रमाणपत्र मॉड्यूल को निम्नानुसार परिभाषित किया जा सकता है।
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)
}

एक एपेक्स स्थापित करना

एपेक्स स्थापित करने के लिए, एडीबी का उपयोग करें।

adb install apex_file_name
adb reboot

एपेक्स का उपयोग करना

रिबूट के बाद, एपेक्स को /apex/<apex_name>@<version> निर्देशिका में माउंट किया जाता है। एक ही एपेक्स के कई संस्करण एक ही समय में माउंट किए जा सकते हैं। माउंट पथों में से, जो नवीनतम संस्करण से मेल खाता है वह /apex/<apex_name> पर बाइंड-माउंटेड है।

क्लाइंट एपेक्स से फाइलों को पढ़ने या निष्पादित करने के लिए बाइंड-माउंटेड पथ का उपयोग कर सकते हैं।

एपेक्स आमतौर पर निम्नानुसार उपयोग किए जाते हैं:

  1. जब डिवाइस को शिप किया जाता है तो एक ओईएम या ओडीएम एक एपेक्स को /system/apex एपेक्स के तहत प्रीलोड करता है।
  2. APEX में फ़ाइलें /apex/<apex_name>/ पथ के माध्यम से एक्सेस की जाती हैं।
  3. जब एपेक्स का एक अद्यतन संस्करण /data/apex में स्थापित होता है, तो पथ रीबूट के बाद नए एपेक्स को इंगित करता है।

एपेक्स के साथ किसी सेवा को अपडेट करना

एपेक्स का उपयोग करके किसी सेवा को अपडेट करने के लिए:

  1. सिस्टम विभाजन में सेवा को अद्यतन करने योग्य के रूप में चिह्नित करें। सेवा परिभाषा में updatable करने योग्य विकल्प जोड़ें।

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. अद्यतन सेवा के लिए एक नई .rc फ़ाइल बनाएँ। मौजूदा सेवा को फिर से परिभाषित करने के लिए override विकल्प का उपयोग करें।

    /apex/my.apex/etc/init.rc:
    
    service myservice /apex/my.apex/bin/myservice
        class core
        user system
        ...
        override
    

सेवा परिभाषाओं को केवल एपेक्स की .rc फ़ाइल में परिभाषित किया जा सकता है। एपेक्स में एक्शन ट्रिगर समर्थित नहीं हैं।

यदि एपेक्स के सक्रिय होने से पहले अद्यतन योग्य के रूप में चिह्नित सेवा शुरू होती है, तो एपेक्स की सक्रियता पूर्ण होने तक शुरुआत में देरी होती है।

एपेक्स अपडेट का समर्थन करने के लिए सिस्टम को कॉन्फ़िगर करना

एपेक्स फ़ाइल अद्यतनों का समर्थन करने के लिए निम्नलिखित सिस्टम गुण को 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)

चपटा शीर्ष

पुराने उपकरणों के लिए, एपेक्स को पूरी तरह से समर्थन देने के लिए पुराने कर्नेल को अपडेट करना कभी-कभी असंभव या अक्षम होता है। उदाहरण के लिए, कर्नेल CONFIG_BLK_DEV_LOOP=Y के बिना बनाया गया हो सकता है, जो कि एक एपेक्स के अंदर फाइल सिस्टम छवि को माउंट करने के लिए महत्वपूर्ण है।

चपटा एपेक्स एक विशेष रूप से निर्मित एपेक्स है जिसे लीगेसी कर्नेल वाले उपकरणों पर सक्रिय किया जा सकता है। एक चपटा एपेक्स में फ़ाइलें सीधे अंतर्निहित विभाजन के तहत एक निर्देशिका में स्थापित की जाती हैं। उदाहरण के लिए, lib/libFoo.so एक चपटे एपेक्स में my.apex को /system/apex/my.apex/lib/libFoo.so पर स्थापित किया गया है।

एक चपटे एपेक्स को सक्रिय करने में लूप डिवाइस शामिल नहीं है। संपूर्ण निर्देशिका /system/apex/my.apex सीधे /apex/name@ver पर बाइंड-माउंटेड है।

नेटवर्क से एपेक्स के अपडेटेड वर्जन को डाउनलोड करके फ्लैटेड एपेक्स को अपडेट नहीं किया जा सकता क्योंकि डाउनलोड किए गए एपेक्स को फ्लैट नहीं किया जा सकता है। फ्लैटेड एपेक्स को केवल एक नियमित ओटीए के माध्यम से ही अपडेट किया जा सकता है।

चपटा एपेक्स डिफ़ॉल्ट कॉन्फ़िगरेशन है। इसका मतलब यह है कि सभी एपेक्स डिफ़ॉल्ट रूप से चपटे होते हैं जब तक कि आप एपेक्स अपडेट का समर्थन करने के लिए गैर-फ्लैटेड एपेक्स बनाने के लिए अपने डिवाइस को स्पष्ट रूप से कॉन्फ़िगर नहीं करते हैं (जैसा कि ऊपर बताया गया है)।

डिवाइस में फ़्लैटेड और नॉन फ़्लैटेड एपेक्स को मिलाना समर्थित नहीं है। किसी उपकरण में शीर्ष या तो सभी गैर-चपटे या सभी चपटे होने चाहिए। यह विशेष रूप से महत्वपूर्ण है जब मेनलाइन जैसी परियोजनाओं के लिए पूर्व-हस्ताक्षरित एपेक्स प्रीबिल्ट शिपिंग करते हैं। APEXes जो निर्धारित नहीं हैं (अर्थात, स्रोत से निर्मित) भी गैर-चपटा होना चाहिए और उचित कुंजियों के साथ हस्ताक्षरित होना चाहिए। डिवाइस को updatable_apex.mk से इनहेरिट करना चाहिए जैसा कि एक एपेक्स के साथ एक सेवा को अपडेट करने में बताया गया है।

संपीडित शीर्ष

Android 12 और बाद में अद्यतन करने योग्य APEX पैकेजों के भंडारण प्रभाव को कम करने के लिए APEX संपीड़न की सुविधा है। एपेक्स के लिए एक अद्यतन स्थापित होने के बाद, हालांकि इसके पूर्व-स्थापित संस्करण का अब उपयोग नहीं किया जाता है, फिर भी यह उतना ही स्थान घेरता है। वह कब्जा किया हुआ स्थान अनुपलब्ध रहता है।

एपेक्स संपीड़न केवल-पढ़ने के लिए विभाजन (जैसे /system विभाजन) पर एपेक्स फाइलों के अत्यधिक संकुचित सेट का उपयोग करके इस भंडारण प्रभाव को कम करता है। एंड्रॉइड 12 और बाद में एक डिफलेट ज़िप संपीड़न एल्गोरिदम का उपयोग करें।

संपीड़न निम्नलिखित को अनुकूलन प्रदान नहीं करता है:

  • बूटस्ट्रैप एपेक्स जिन्हें बूट अनुक्रम में बहुत जल्दी आरोहित करने की आवश्यकता होती है।

  • अपरिवर्तनीय अपैक्स। संपीड़न केवल तभी फायदेमंद होता है जब एपेक्स का अद्यतन संस्करण /data विभाजन पर स्थापित हो। मॉड्यूलर सिस्टम कंपोनेंट्स पेज पर अपडेट करने योग्य एपेक्स की पूरी सूची उपलब्ध है।

  • गतिशील साझा libs APEXes। चूंकि apexd हमेशा ऐसे एपेक्स के दोनों संस्करणों को सक्रिय करता है (पहले से स्थापित और अपग्रेड किया गया), उन्हें संपीड़ित करने से मूल्य नहीं जुड़ता है।

संपीड़ित एपेक्स फ़ाइल स्वरूप

यह एक संपीड़ित एपेक्स फ़ाइल का प्रारूप है।

Diagram shows the format of a compressed APEX file

चित्र 2. संपीडित एपेक्स फ़ाइल स्वरूप

शीर्ष स्तर पर, एक संपीड़ित एपेक्स फ़ाइल एक ज़िप फ़ाइल होती है जिसमें मूल शीर्ष फ़ाइल 9 के संपीड़न स्तर के साथ डिफ्लेटेड रूप में होती है, और अन्य फाइलें असम्पीडित संग्रहीत होती हैं।

चार फाइलों में एक एपेक्स फाइल होती है:

  • original_apex : 9 के संपीड़न स्तर के साथ अपस्फीति यह मूल, असम्पीडित एपेक्स फ़ाइल है
  • apex_manifest.pb : केवल संग्रहित
  • AndroidManifest.xml : केवल संग्रहित
  • apex_pubkey : केवल संग्रहित

apex_manifest.pb , AndroidManifest.xml , और apex_pubkey फाइलें original_apex में उनकी संबंधित फाइलों की प्रतियां हैं।

बिल्डिंग कंप्रेस्ड एपेक्स

system/apex/tools पर स्थित apex_compression_tool.py .py टूल का उपयोग करके कंप्रेस्ड एपेक्स का निर्माण किया जा सकता है।

एपेक्स कम्प्रेशन से संबंधित कई पैरामीटर बिल्ड सिस्टम में उपलब्ध हैं।

Android.bp में क्या APEX फ़ाइल कंप्रेसिबल है, इसे compressible प्रॉपर्टी द्वारा नियंत्रित किया जाता है:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

एक PRODUCT_COMPRESSED_APEX उत्पाद ध्वज नियंत्रित करता है कि स्रोत से निर्मित सिस्टम छवि में संपीड़ित एपेक्स फ़ाइलें होनी चाहिए या नहीं।

स्थानीय प्रयोग के लिए आप OVERRIDE_PRODUCT_COMPRESSED_APEX= को true पर सेट करके APEXes को संपीड़ित करने के लिए किसी बिल्ड को बाध्य कर सकते हैं।

बिल्ड सिस्टम द्वारा उत्पन्न कंप्रेस्ड एपेक्स फाइलों में .capex एक्सटेंशन होता है। विस्तार एपेक्स फ़ाइल के संपीड़ित और असम्पीडित संस्करणों के बीच अंतर करना आसान बनाता है।

समर्थित संपीड़न एल्गोरिदम

Android 12 केवल डिफ्लेट-ज़िप संपीड़न का समर्थन करता है।

बूट के दौरान संपीड़ित एपेक्स फ़ाइल को सक्रिय करना

एक संपीड़ित एपेक्स को सक्रिय करने से पहले, इसके अंदर की original_apex फ़ाइल /data/apex/decompressed निर्देशिका में विघटित हो जाती है। परिणामी डीकंप्रेस्ड एपेक्स फ़ाइल /data/apex/active निर्देशिका से हार्ड-लिंक्ड है।

ऊपर वर्णित प्रक्रिया के उदाहरण के रूप में निम्नलिखित उदाहरण पर विचार करें।

/system/apex/com.android.foo.capex को एक संपीड़ित एपेक्स के रूप में सक्रिय किया जा रहा है, संस्करण कोड 37 के साथ पर विचार करें।

  1. /system/apex/com.android.foo.capex के अंदर original_apex फ़ाइल /data/apex/decompressed/com.android.foo@37.apex में विघटित हो जाती है।
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex यह सत्यापित करने के लिए किया जाता है कि इसमें एक सही SELinux लेबल है।
  3. इसकी वैधता सुनिश्चित करने के लिए /data/apex/decompressed/com.android.foo@37.apex पर सत्यापन जांच की जाती है: apexd सार्वजनिक कुंजी को /data/apex/decompressed/com.android.foo@37.apex में बंडल करके जांचता है। सत्यापित करें कि यह /system/apex/com.android.foo.capex में बंडल किए गए के बराबर है।
  4. /data/apex/decompressed/com.android.foo@37.apex फ़ाइल /data/apex/active/com.android.foo@37.apex निर्देशिका से हार्ड-लिंक्ड है।
  5. असम्पीडित एपेक्स फाइलों के लिए नियमित सक्रियण तर्क /data/apex/active/com.android.foo@37.apex पर किया जाता है।

ओटीए के साथ बातचीत

संपीड़ित एपेक्स फाइलों का ओटीए वितरण और आवेदन पर प्रभाव पड़ता है। चूंकि एक ओटीए अपडेट में एक संपीड़ित एपेक्स फ़ाइल हो सकती है जो किसी डिवाइस पर सक्रिय संस्करण की तुलना में उच्च संस्करण स्तर के साथ होती है, ओटीए अपडेट को लागू करने के लिए डिवाइस को रीबूट करने से पहले एक निश्चित मात्रा में खाली स्थान आरक्षित किया जाना चाहिए।

ओटीए प्रणाली का समर्थन करने के लिए, apexd इन दो बाइंडर एपीआई को उजागर करता है:

  • calculateSizeForCompressedApex - एक ओटीए पैकेज में एपेक्स फाइलों को डीकंप्रेस करने के लिए आवश्यक आकार की गणना करता है। इसका उपयोग यह सत्यापित करने के लिए किया जा सकता है कि ओटीए डाउनलोड होने से पहले डिवाइस में पर्याप्त जगह है।
  • reserveSpaceForCompressedApex - OTA पैकेज के अंदर संपीड़ित APEX फ़ाइलों को डीकंप्रेस करने के लिए apexd द्वारा भविष्य में उपयोग के लिए डिस्क पर स्थान सुरक्षित रखता है।

ए/बी ओटीए अपडेट के मामले में, apexd ओटीए रूटीन के बाद के हिस्से के रूप में पृष्ठभूमि में डीकंप्रेसन का प्रयास करता है। यदि डीकंप्रेसन विफल हो जाता है, apexd बूट के दौरान डीकंप्रेसन करता है जो ओटीए अपडेट को लागू करता है।

एपेक्स विकसित करते समय विचार किए गए विकल्प

यहां कुछ विकल्प दिए गए हैं जिन पर एओएसपी ने एपेक्स फ़ाइल प्रारूप को डिजाइन करते समय विचार किया था, और उन्हें या तो शामिल या बाहर क्यों किया गया था।

नियमित पैकेज प्रबंधन प्रणाली

लिनक्स वितरण में dpkg और rpm जैसी पैकेज प्रबंधन प्रणालियाँ हैं, जो शक्तिशाली, परिपक्व और मजबूत हैं। हालाँकि, उन्हें APEX के लिए नहीं अपनाया गया था क्योंकि वे स्थापना के बाद पैकेजों की सुरक्षा नहीं कर सकते। सत्यापन केवल तभी किया जाता है जब संकुल संस्थापित किया जा रहा हो। हमलावर किसी का ध्यान नहीं, स्थापित पैकेज की अखंडता को तोड़ सकते हैं। यह एंड्रॉइड के लिए एक प्रतिगमन है जहां सभी सिस्टम घटकों को केवल-पढ़ने के लिए फाइल सिस्टम में संग्रहीत किया गया था, जिनकी अखंडता प्रत्येक I/O के लिए dm-verity द्वारा संरक्षित है। सिस्टम घटकों में किसी भी तरह की छेड़छाड़ को या तो प्रतिबंधित किया जाना चाहिए, या पता लगाने योग्य होना चाहिए ताकि समझौता होने पर डिवाइस बूट करने से इंकार कर सके।

डीएम-क्रिप्ट अखंडता के लिए

एपेक्स कंटेनर में फाइलें बिल्ट-इन पार्टीशन (उदाहरण के लिए, /system पार्टीशन) से होती हैं, जो डीएम-वेरिटी द्वारा संरक्षित होती हैं, जहां पार्टीशन माउंट होने के बाद भी फाइलों में कोई भी संशोधन प्रतिबंधित है। फाइलों को समान स्तर की सुरक्षा प्रदान करने के लिए, एपेक्स में सभी फाइलों को एक फाइल सिस्टम इमेज में संग्रहित किया जाता है जिसे हैश ट्री और एक vbmeta डिस्क्रिप्टर के साथ जोड़ा जाता है। dm-verity के बिना, /data पार्टीशन में एक एपेक्स अनपेक्षित संशोधनों के प्रति संवेदनशील है जो इसे सत्यापित और स्थापित करने के बाद किए जाते हैं।

वास्तव में, /data विभाजन भी एन्क्रिप्शन परतों जैसे dm-crypt द्वारा सुरक्षित है। हालांकि यह छेड़छाड़ के खिलाफ कुछ स्तर की सुरक्षा प्रदान करता है, इसका प्राथमिक उद्देश्य गोपनीयता है, अखंडता नहीं। जब एक हमलावर /data विभाजन तक पहुंच प्राप्त करता है, तो कोई और सुरक्षा नहीं हो सकती है, और यह फिर से प्रत्येक सिस्टम घटक /system विभाजन में होने की तुलना में एक प्रतिगमन है। APEX फ़ाइल के अंदर हैश ट्री dm-verity के साथ समान स्तर की सामग्री सुरक्षा प्रदान करता है।

/system से /apex . तक पथ पुनर्निर्देशित करना

एपेक्स में पैक की गई सिस्टम घटक फाइलें /apex/<name>/lib/libfoo.so जैसे नए पथों के माध्यम से पहुंच योग्य हैं। जब फ़ाइलें /system विभाजन का हिस्सा थीं, तो वे /system/lib/libfoo.so जैसे पथों के माध्यम से पहुंच योग्य थीं। एपेक्स फाइल के क्लाइंट (अन्य एपेक्स फाइलें या प्लेटफॉर्म) को नए रास्तों का उपयोग करना चाहिए। पथ परिवर्तन के परिणामस्वरूप आपको मौजूदा कोड को अपडेट करने की आवश्यकता हो सकती है।

हालांकि पथ परिवर्तन से बचने का एक तरीका है कि एक एपेक्स फ़ाइल में फ़ाइल सामग्री को /system विभाजन पर ओवरले करना, एंड्रॉइड टीम ने /system विभाजन पर फ़ाइलों को ओवरले नहीं करने का फैसला किया क्योंकि यह प्रदर्शन को प्रभावित कर सकता है क्योंकि फाइलों की संख्या ओवरले की जा रही है ( संभवतः एक के बाद एक ढेर भी) बढ़ गए।

एक अन्य विकल्प फ़ाइल-एक्सेस फ़ंक्शंस जैसे कि open , stat और readlink को हाईजैक करना था, ताकि /system से शुरू होने वाले रास्तों को /apex के तहत उनके संबंधित पथों पर पुनर्निर्देशित किया जा सके। एंड्रॉइड टीम ने इस विकल्प को त्याग दिया क्योंकि पथ स्वीकार करने वाले सभी कार्यों को बदलना संभव नहीं है। उदाहरण के लिए, कुछ ऐप्स बायोनिक को स्थिर रूप से लिंक करते हैं, जो कार्यों को लागू करता है। ऐसे मामलों में, वे ऐप्स रीडायरेक्ट नहीं होते हैं।