APEX फ़ाइल फ़ॉर्मैट का इस्तेमाल करके, कम लेवल के Android OS मॉड्यूल को पैकेज और इंस्टॉल किया जा सकता है. इससे नेटिव सेवाओं और लाइब्रेरी, एचएएल लागू करने, फ़र्मवेयर, कॉन्फ़िगरेशन फ़ाइलों वगैरह जैसे कॉम्पोनेंट को अलग से बनाने और इंस्टॉल करने की सुविधा मिलती है.
वेंडर APEXes को बिल्ड सिस्टम से, /vendor
में अपने-आप इंस्टॉल किया जाता है
इसे apexd
से रनटाइम पर बांटा जाता है और इसे अन्य APEXes की तरह ही चालू किया जाता है
विभाजन.
इस्तेमाल के उदाहरण
वेंडर इमेज को मॉड्यूलर बनाना
APEX, वेंडर इमेज पर सुविधाओं को लागू करने के लिए, बंडल करने और मॉड्यूल बनाने की सुविधा देते हैं.
जब वेंडर की इमेज, स्वतंत्र रूप से बने वेंडर के कॉम्बिनेशन के तौर पर बनाई जाती हैं APEXes, डिवाइस निर्माता आसानी से आपके लिए जो वेंडर चाहते थे कि वे उनके डिवाइस पर लागू हों. मैन्युफ़ैक्चरर यह भी बना सकते हैं कि नया वेंडर APEX, अगर दिया गया कोई भी APEX उनकी ज़रूरतों के मुताबिक नहीं है या उनके पास नया कस्टम हार्डवेयर.
उदाहरण के लिए, कोई OEM अपने डिवाइस को AOSP वाई-फ़ाई लागू करने वाले APEX, SoC ब्लूटूथ लागू करने वाले APEX, और कस्टम OEM टेलीफ़ोनी लागू करने वाले APEX के साथ कॉम्पोज़ कर सकता है.
वेंडर APEX के बिना, वेंडर कॉम्पोनेंट के बीच इतनी सारी डिपेंडेंसी के साथ लागू करने के लिए, सावधानी से समन्वय और ट्रैकिंग की ज़रूरत होती है. सभी कॉम्पोनेंट (इनमें कॉन्फ़िगरेशन फ़ाइलें और अतिरिक्त लाइब्रेरी शामिल हैं) को APEX में रैप करके, अलग-अलग कॉम्पोनेंट को एक-दूसरे से बदला जा सकता है. ऐसा करने के लिए, अलग-अलग सुविधाओं के बीच होने वाले कम्यूनिकेशन के किसी भी समय, साफ़ तौर पर बताए गए इंटरफ़ेस का इस्तेमाल करें.
डेवलपर के लिए, बार-बार अपडेट करना
वेंडर APEX, वेंडर मॉड्यूल डेवलप करते समय डेवलपर को तेज़ी से बदलाव करने में मदद करते हैं. ऐसा वेंडर APEX में वाई-फ़ाई एचएएल जैसी पूरी सुविधा को लागू करके करते हैं. इसके बाद, डेवलपर वेंडर की पूरी इमेज को फिर से बनाने के बजाय, बदलावों की जांच करने के लिए वेंडर APEX को अलग-अलग बना सकते हैं और उसे पुश कर सकते हैं.
इससे, उन डेवलपर के लिए डेवलपर के इटरेटेशन साइकल को आसान और तेज़ बनाया जा सकता है जो मुख्य रूप से किसी एक सुविधा वाले एरिया में काम करते हैं और सिर्फ़ उस सुविधा वाले एरिया पर काम करना चाहते हैं.
किसी फ़ीचर एरिया को APEX में नैचुरल बंडल करने से, इस प्रक्रिया को आसान बनाने में मदद मिलती है और उन सुविधाओं के लिए बदलाव करने, उन्हें लागू करने, और उनकी जाँच करने के बारे में बताया गया है. उदाहरण के लिए, APEX को फिर से इंस्टॉल करने पर, बंडल की गई लाइब्रेरी या कॉन्फ़िगरेशन फ़ाइलें अपने-आप अपडेट हो जाएंगी APEX में शामिल हैं.
किसी फ़ीचर एरिया को APEX में बंडल करने से, डीबग करने या वापस लाने की प्रोसेस आसान हो जाती है डिवाइस पर ऐप्लिकेशन की खराब परफ़ॉर्मेंस का पता चला है. उदाहरण के लिए, अगर किसी नए बिल्ड में टेलीफ़ोन सेवा ठीक से काम नहीं कर रही है, तो डेवलपर किसी डिवाइस पर टेलीफ़ोन सेवा लागू करने वाला पुराना APEX इंस्टॉल करके देख सकते हैं कि क्या टेलीफ़ोन सेवा ठीक से काम कर रही है. इसके लिए, उन्हें पूरा बिल्ड फ़्लैश करने की ज़रूरत नहीं है.
वर्कफ़्लो का उदाहरण:
# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w
# Test the device.
... testing ...
# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...
# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...
उदाहरण
बुनियादी जानकारी
सामान्य APEX के लिए, APEX फ़ाइल फ़ॉर्मैट का मुख्य पेज देखें जानकारी. इसमें डिवाइस से जुड़ी ज़रूरी शर्तें, फ़ाइल फ़ॉर्मैट की जानकारी, और इंस्टॉल करने के तरीके.
Android.bp
में, vendor: true
प्रॉपर्टी सेट करने पर, APEX मॉड्यूल एक वेंडर APEX बन जाता है.
apex {
..
vendor: true,
..
}
बाइनरी और शेयर की गई लाइब्रेरी
APEX में, APEX पेलोड के अंदर ट्रांज़िशन डिपेंडेंसी शामिल होती हैं. ऐसा तब तक होता है, जब तक उनके पास स्थिर इंटरफ़ेस न हों.
वेंडर APEX डिपेंडेंसी के लिए स्थायी नेटिव इंटरफ़ेस में, cc_library
शामिल है
stubs
और LLNDK लाइब्रेरी. इन डिपेंडेंसी को इनसे बाहर रखा जाता है
पैकेजिंग, और डिपेंडेंसी को APEX मेनिफ़ेस्ट में रिकॉर्ड किया जाता है. मेनिफ़ेस्ट को linkerconfig
प्रोसेस करता है, ताकि बाहरी नेटिव डिपेंडेंसी, रनटाइम के दौरान उपलब्ध हों.
नीचे दिए गए स्निपेट में, APEX में बाइनरी (my_service
) और उसकी अस्थिर डिपेंडेंसी (*.so
फ़ाइलें) दोनों शामिल हैं.
apex {
..
vendor: true,
binaries: ["my_service"],
..
}
नीचे दिए गए स्निपेट में, APEX में शेयर की गई लाइब्रेरी शामिल है
my_standalone_lib
और इसकी कोई भी नॉन-स्टेबल डिपेंडेंसी (जैसा कि ऊपर बताया गया है).
apex {
..
vendor: true,
native_shared_libs: ["my_standalone_lib"],
..
}
APEX को छोटा करें
APEX बड़ी संख्या में हो सकता है, क्योंकि यह नॉन-स्टेबल डिपेंडेंसी को बंडल करता है. हमारा सुझाव है कि आप स्टैटिक लिंकिंग का इस्तेमाल करें. libc++.so
और libbase.so
जैसी सामान्य लाइब्रेरी को, एचएएल बाइनरी से स्टैटिक तौर पर लिंक किया जा सकता है. एक और विकल्प यह है कि आप किसी स्थिर इंटरफ़ेस को उपलब्ध कराने के लिए, डिपेंडेंसी बनाएं. डिपेंडेंसी को APEX में बंडल नहीं किया जाएगा.
एचएएल लागू करना
HAL लागू करने के बारे में बताने के लिए, उससे जुड़ी बाइनरी और लाइब्रेरी उपलब्ध कराएं वेंडर APEX में दिए गए उदाहरणों की तरह:
एचएएल लागू करने के लिए, APEX को काम के सभी VINTF फ़्रैगमेंट और init स्क्रिप्ट की जानकारी भी देनी चाहिए.
VINTF फ़्रैगमेंट
जब फ़्रैगमेंट, APEX के etc/vintf
में मौजूद होते हैं, तो वेंडर APEX से VINTF फ़्रैगमेंट दिखाए जा सकते हैं.
APEX में VINTF फ़्रैगमेंट एम्बेड करने के लिए, prebuilts
प्रॉपर्टी का इस्तेमाल करें.
apex {
..
vendor: true,
prebuilts: ["fragment.xml"],
..
}
prebuilt_etc {
name: "fragment.xml",
src: "fragment.xml",
sub_dir: "vintf",
}
क्वेरी एपीआई
जब APEX में VINTF फ़्रैगमेंट जोड़े जाते हैं, तो पाने के लिए libbinder_ndk
API का इस्तेमाल करें
HAL इंटरफ़ेस और APEX नामों की मैपिंग.
AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default")
:true
अगर APEX में HAL इंस्टेंस के बारे में बताया गया है.AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...)
: HAL इंस्टेंस की जानकारी देने वाला APEX नाम पाता है.AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...)
: पासथ्रू एचएएल खोलने के लिए, इसका इस्तेमाल करें.
Init स्क्रिप्ट
APEXes दो तरीकों से इनिट स्क्रिप्ट शामिल कर सकता है: (A)
APEX पेलोड या (B) /vendor/etc
में एक सामान्य इनिट स्क्रिप्ट. आप दोनों को सेट कर सकते हैं
एक ही APEX के लिए.
APEX में init स्क्रिप्ट:
prebuilt_etc {
name: "myinit.rc",
src: "myinit.rc"
}
apex {
..
vendor: true,
prebuilts: ["myinit.rc"],
..
}
वेंडर APEX में मौजूद init स्क्रिप्ट में service
परिभाषाएं और
on <property or event>
डायरेक्टिव हो सकते हैं.
पक्का करें कि service
डेफ़िनिशन, एक ही APEX में बाइनरी पर ले जाती हो.
उदाहरण के लिए, com.android.foo
APEX, foo-service
नाम की सेवा तय कर सकता है.
on foo-service /apex/com.android.foo/bin/foo
...
on
निर्देशों का इस्तेमाल करते समय सावधानी बरतें. क्योंकि APEX में इनिट स्क्रिप्ट
APEXS चालू करने के बाद पार्स और एक्ज़ीक्यूट किया गया, कुछ इवेंट या प्रॉपर्टी
इस्तेमाल नहीं किया जा सकता. कार्रवाइयों को जल्द से जल्द ट्रिगर करने के लिए, apex.all.ready=true
का इस्तेमाल करें.
बूटस्ट्रैप एपेक्स on init
का इस्तेमाल कर सकते हैं, लेकिन नहीं
on early-init
.
फ़र्मवेयर
उदाहरण:
वेंडर APEX में फ़र्मवेयर को prebuilt_firmware
मॉड्यूल टाइप के साथ इस तरह से जोड़ें.
prebuilt_firmware {
name: "my.bin",
src: "path_to_prebuilt_firmware",
vendor: true,
}
apex {
..
vendor: true,
prebuilts: ["my.bin"], // installed inside APEX as /etc/firmware/my.bin
..
}
prebuilt_firmware
मॉड्यूल, APEX की <apex name>/etc/firmware
डायरेक्ट्री में इंस्टॉल किए जाते हैं. ueventd
, /apex/*/etc/firmware
डायरेक्ट्री को यहां स्कैन करता है
मिल सकता है.
APEX के file_contexts
को फ़र्मवेयर पेलोड की सभी एंट्री को सही तरीके से लेबल करना चाहिए, ताकि यह पक्का किया जा सके कि रनटाइम के दौरान ueventd
इन फ़ाइलों को ऐक्सेस कर सके. आम तौर पर, vendor_file
लेबल काफ़ी होता है. उदाहरण के लिए:
(/.*)? u:object_r:vendor_file:s0
Kernel मॉड्यूल
वेंडर APEX में पहले से बने मॉड्यूल के तौर पर, कर्नेल मॉड्यूल जोड़ें. इसके लिए, यहां दिया गया तरीका अपनाएं.
prebuilt_etc {
name: "my.ko",
src: "my.ko",
vendor: true,
sub_dir: "modules"
}
apex {
..
vendor: true,
prebuilts: ["my.ko"], // installed inside APEX as /etc/modules/my.ko
..
}
APEX के file_contexts
को किसी भी कर्नेल मॉड्यूल पेलोड एंट्री को लेबल करना चाहिए
सही तरीके से. उदाहरण के लिए:
/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0
कर्नेल मॉड्यूल साफ़ तौर पर इंस्टॉल होने चाहिए. init स्क्रिप्ट का उदाहरण नीचे दिया गया है
इस सेक्शन में, insmod
के ज़रिए इंस्टॉल करने की जानकारी दिखती है:
my_init.rc
:
on early-boot
insmod /apex/myapex/etc/modules/my.ko
..
रनटाइम रिसॉर्स ओवरले
उदाहरण:
rros
प्रॉपर्टी का इस्तेमाल करके, वेंडर APEX में रनटाइम रिसॉर्स ओवरले एम्बेड करें.
runtime_resource_overlay {
name: "my_rro",
soc_specific: true,
}
apex {
..
vendor: true,
rros: ["my_rro"], // installed inside APEX as /overlay/my_rro.apk
..
}
अन्य कॉन्फ़िगरेशन फ़ाइलें
वेंडर APEX, आम तौर पर वेंडर के सेगमेंट में पहले से बनी हुई कई अन्य कॉन्फ़िगरेशन फ़ाइलों के साथ काम करते हैं. साथ ही, इसमें और भी फ़ाइलें जोड़ी जा रही हैं.
उदाहरण:
- सुविधा के एलान से जुड़ा एक्सएमएल
- सेंसर, एक्सएमएल को इस तरह दिखाते हैं सेंसर वाले HAL वेंडर APEX में पहले से बनाया गया
- कॉन्फ़िगरेशन फ़ाइलें इनपुट करना
- टचस्क्रीन कॉन्फ़िगरेशन इस तरह से होता है: सिर्फ़ कॉन्फ़िगरेशन वाले वेंडर APEX में पहले से बनाया गया
बूटस्ट्रैप वेंडर APEXes
keymint
जैसी एचएएल की कुछ सेवाएं, एपेक्स के उपलब्ध होने से पहले उपलब्ध हो जानी चाहिए
चालू किया गया. आम तौर पर, ये एचएएल अपनी सेवा की परिभाषा में, early_hal
को init स्क्रिप्ट में सेट करते हैं. दूसरा उदाहरण animation
क्लास है, जो आम तौर पर शुरू की जाती है
post-fs-data
इवेंट से पहले. जब एचएएल की ऐसी शुरुआती सेवा दी जाती है
वेंडर APEX में पैकेज के तौर पर, इसके APEX में एपेक्स "vendorBootstrap": true
बनाएं
मेनिफ़ेस्ट करें, ताकि इसे जल्दी चालू किया जा सके. ध्यान दें कि बूटस्ट्रैप APEXes
सिर्फ़ पहले से बनी जगह से चालू की गई, जैसे /vendor/apex
, से नहीं
/data/apex
.
सिस्टम प्रॉपर्टी
ये सिस्टम की ऐसी प्रॉपर्टी हैं जिन्हें फ़्रेमवर्क, वेंडर की मदद करने के लिए पढ़ता है एपेक्स:
input_device.config_file.apex=<apex name>
- सेट होने पर, इनपुट कॉन्फ़िगरेशन फ़ाइलों (*.idc
,*.kl
, और*.kcm
) को APEX की/etc/usr
डायरेक्ट्री से खोजा जाता है.ro.vulkan.apex=<apex name>
- सेट होने पर, Vulkan ड्राइवर को APEX से लोड किया जाता है. Vulkan ड्राइवर का इस्तेमाल, शुरुआती एचएएल (हार्डवेयर लेवल एपीआई) करते हैं. इसलिए, APEX को बूटस्ट्रैप APEX बनाएं और लिंकर नेमस्पेस को दिखने के लिए कॉन्फ़िगर करें.
setprop
कमांड का इस्तेमाल करके, init स्क्रिप्ट में सिस्टम प्रॉपर्टी सेट करें.
डेवलपमेंट से जुड़ी अन्य सुविधाएं
बूटअप के समय APEX चुनना
उदाहरण:
डेवलपर, एक ही APEX नाम और कुंजी वाले वेंडर APEX के कई वर्शन भी इंस्टॉल कर सकते हैं. इसके बाद, वे यह चुन सकते हैं कि हर बार बूटअप के दौरान कौनसा वर्शन चालू किया जाए. इसके लिए, वे लगातार काम करने वाले sysprops का इस्तेमाल करते हैं. डेवलपर के इस्तेमाल के कुछ उदाहरणों के लिए, यह adb install
का इस्तेमाल करके APEX की नई कॉपी इंस्टॉल करने से आसान हो सकता है.
इस्तेमाल के उदाहरण:
- वाईफ़ाई एचएएल वेंडर APEX के तीन वर्शन इंस्टॉल करें: क्यूए टीमें, एक वर्शन का इस्तेमाल करके मैन्युअल या ऑटोमेटेड टेस्टिंग कर सकती हैं. इसके बाद, दूसरे वर्शन में रीबूट करके टेस्ट फिर से चला सकती हैं और फिर फ़ाइनल नतीजों की तुलना कर सकती हैं.
- कैमरा HAL वेंडर APEX के दो वर्शन इंस्टॉल करें, मौजूदा और एक्सपेरिमेंट के तौर पर उपलब्ध: डॉगफ़ूडर, एक्सपेरिमेंट के तौर पर उपलब्ध वर्शन को इसके बिना भी इस्तेमाल कर सकते हैं अतिरिक्त फ़ाइल डाउनलोड और इंस्टॉल करना, ताकि वे आसानी से वापस स्वैप कर सकें.
बूटअप के दौरान, apexd
सही APEX वर्शन को चालू करने के लिए, किसी खास फ़ॉर्मैट के हिसाब से sysprops खोजता है.
प्रॉपर्टी कुंजी के लिए सही फ़ॉर्मैट हैं:
- बूटकॉन्फ़िगरेशन
- इसका इस्तेमाल,
BoardConfig.mk
में डिफ़ॉल्ट वैल्यू सेट करने के लिए किया जाता है. androidboot.vendor.apex.<apex name>
- इसका इस्तेमाल,
- परसिस्टेंट सिस्टमॉप
- इसका इस्तेमाल, पहले से बूट किए गए डिवाइस पर सेट की गई डिफ़ॉल्ट वैल्यू को बदलने के लिए किया जाता है.
- मौजूद होने पर, बूट कॉन्फ़िगरेशन की वैल्यू बदल जाती है.
persist.vendor.apex.<apex name>
प्रॉपर्टी की वैल्यू, उस APEX फ़ाइल का नाम होना चाहिए जिसे चालू करना है.
// Default version.
apex {
name: "com.oem.camera.hal.my_apex_default",
vendor: true,
..
}
// Non-default version.
apex {
name: "com.oem.camera.hal.my_apex_experimental",
vendor: true,
..
}
डिफ़ॉल्ट वर्शन को भी बूट कॉन्फ़िगरेशन का इस्तेमाल करके कॉन्फ़िगर किया जाना चाहिए
BoardConfig.mk
:
# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default
डिवाइस के बूट होने के बाद, पहले से सेट sysprop को सेट करके, चालू किए गए वर्शन को बदलें:
$ adb root;
$ adb shell setprop \
persist.vendor.apex.com.oem.camera.hal \
com.oem.camera.hal.my_apex_experimental;
$ adb reboot;
अगर डिवाइस, फ़्लैश करने के बाद bootconfig को अपडेट करने की सुविधा देता है, जैसे कि fastboot
oem
निर्देशों की मदद से, तो एक से ज़्यादा इंस्टॉल किए गए APEX के लिए bootconfig प्रॉपर्टी में बदलाव करने पर, बूटअप के समय चालू होने वाले वर्शन में भी बदलाव होता है.
कटलफ़िश पर आधारित वर्चुअल रेफ़रंस डिवाइसों के लिए,
बूट कॉन्फ़िगरेशन प्रॉपर्टी को सेट करने के लिए, --extra_bootconfig_args
कमांड का इस्तेमाल किया जा सकता है
वह भी सीधे लॉन्च हो रहा हो. उदाहरण के लिए:
launch_cvd --noresume \
--extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";