APEX फ़ाइल फ़ॉर्मैट का इस्तेमाल करके, Android OS के निचले लेवल के मॉड्यूल को पैकेज किया जा सकता है और इंस्टॉल किया जा सकता है. इसकी मदद से, नेटिव सेवाओं और लाइब्रेरी, HAL लागू करने की सुविधा, फ़र्मवेयर, कॉन्फ़िगरेशन फ़ाइलें वगैरह जैसे कॉम्पोनेंट को अलग से बनाया और इंस्टॉल किया जा सकता है.
वेंडर APEX, बिल्ड सिस्टम की मदद से /vendor पार्टीशन में अपने-आप इंस्टॉल हो जाते हैं. साथ ही, apexd इन्हें रनटाइम में चालू कर देता है. ये ठीक उसी तरह काम करते हैं जैसे अन्य पार्टीशन में मौजूद APEX.
इस्तेमाल के उदाहरण
वेंडर की इमेज को मॉड्यूलर बनाना
APEX, वेंडर की इमेज पर सुविधाओं को नैचुरल तरीके से बंडल करने और मॉड्यूलर बनाने में मदद करते हैं.
जब वेंडर इमेज को, वेंडर के अलग-अलग APEX के कॉम्बिनेशन के तौर पर बनाया जाता है, तो डिवाइस बनाने वाली कंपनियां आसानी से अपने डिवाइस पर वेंडर के खास तौर पर लागू किए गए फ़ीचर चुन सकती हैं. अगर मैन्युफ़ैक्चरर को दिए गए एपीईएक्स में से कोई भी एपीईएक्स उनकी ज़रूरत के मुताबिक नहीं है या उनके पास बिलकुल नया कस्टम हार्डवेयर है, तो वे नया वेंडर एपीईएक्स भी बना सकते हैं.
उदाहरण के लिए, कोई ओईएम अपने डिवाइस के लिए, AOSP वाई-फ़ाई को लागू करने वाले APEX, SoC ब्लूटूथ को लागू करने वाले 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 और एलएलएनडीके लाइब्रेरी शामिल हैं. इन डिपेंडेंसी को पैकेजिंग से बाहर रखा जाता है. साथ ही, डिपेंडेंसी को APEX मेनिफ़ेस्ट में रिकॉर्ड किया जाता है. linkerconfig, मेनिफ़ेस्ट को प्रोसेस करता है, ताकि बाहरी नेटिव डिपेंडेंसी रनटाइम में उपलब्ध हों.
यहां दिए गए स्निपेट में, APEX में बाइनरी (my_service) और इसकी नॉन-स्टेबल डिपेंडेंसी (*.so फ़ाइलें), दोनों शामिल हैं.
apex {
..
vendor: true,
binaries: ["my_service"],
..
}
यहां दिए गए स्निपेट में, एपीईएक्स में शेयर की गई लाइब्रेरी my_standalone_lib और इसकी सभी नॉन-स्टेबल डिपेंडेंसी शामिल हैं. इनके बारे में ऊपर बताया गया है.
apex {
..
vendor: true,
native_shared_libs: ["my_standalone_lib"],
..
}
APEX को छोटा करें
APEX का साइज़ बढ़ सकता है, क्योंकि इसमें ऐसी डिपेंडेंसी शामिल होती हैं जो स्टेबल नहीं होती हैं. हमारा सुझाव है कि आप स्टैटिक लिंकिंग का इस्तेमाल करें. libc++.so और libbase.so जैसी सामान्य लाइब्रेरी को HAL बाइनरी से स्टैटिक तौर पर लिंक किया जा सकता है. स्थिर इंटरफ़ेस उपलब्ध कराने के लिए, डिपेंडेंसी बनाना एक और विकल्प हो सकता है. डिपेंडेंसी को APEX में बंडल नहीं किया जाएगा.
एचएएल लागू करना
एचएएल को लागू करने के लिए, वेंडर एपीईएक्स में इससे जुड़ी बाइनरी और लाइब्रेरी उपलब्ध कराएं. ये लाइब्रेरी, यहां दिए गए उदाहरणों की तरह होनी चाहिए:
एचएएल को पूरी तरह से लागू करने के लिए, एपेक्स को सभी ज़रूरी VINTF फ़्रैगमेंट और init स्क्रिप्ट भी तय करनी चाहिए.
VINTF फ़्रैगमेंट
अगर VINTF फ़्रैगमेंट, APEX के etc/vintf में मौजूद हैं, तो उन्हें वेंडर APEX से दिखाया जा सकता है.
APEX में VINTF फ़्रैगमेंट एम्बेड करने के लिए, prebuilts प्रॉपर्टी का इस्तेमाल करें.
apex {
..
vendor: true,
prebuilts: ["fragment.xml"],
..
}
prebuilt_etc {
name: "fragment.xml",
src: "fragment.xml",
sub_dir: "vintf",
}
क्वेरी एपीआई
जब VINTF फ़्रैगमेंट को APEX में जोड़ा जाता है, तब एचएएल इंटरफ़ेस और APEX के नामों की मैपिंग पाने के लिए, libbinder_ndk एपीआई का इस्तेमाल करें.
AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default"):trueअगर एचएएल इंस्टेंस को APEX में तय किया गया है.AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...): इससे एपीईएक्स का नाम मिलता है, जो एचएएल इंस्टेंस को तय करता है.AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...): इसका इस्तेमाल पासथ्रू एचएएल खोलने के लिए करें.
Init स्क्रिप्ट
APEX में init स्क्रिप्ट को दो तरीकों से शामिल किया जा सकता है: (A) APEX पेलोड में पहले से बनी टेक्स्ट फ़ाइल या (B) /vendor/etc में मौजूद सामान्य init स्क्रिप्ट. एक ही APEX के लिए, दोनों को सेट किया जा सकता है.
APEX में स्क्रिप्ट शुरू करने का तरीका:
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 में init स्क्रिप्ट को APEX चालू होने के बाद पार्स और एक्ज़ीक्यूट किया जाता है. इसलिए, कुछ इवेंट या प्रॉपर्टी का इस्तेमाल नहीं किया जा सकता. कार्रवाइयों को जल्द से जल्द ट्रिगर करने के लिए, apex.all.ready=true का इस्तेमाल करें.
बूटस्ट्रैप एपीईएक्स, on init का इस्तेमाल कर सकते हैं, लेकिन on early-init का नहीं.
फ़र्मवेयर
उदाहरण:
prebuilt_firmware मॉड्यूल टाइप का इस्तेमाल करके, फ़र्मवेयर को वेंडर APEX में इस तरह एम्बेड करें.
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
कर्नेल मॉड्यूल
कर्नेल मॉड्यूल को वेंडर एपीईएक्स में, पहले से बने मॉड्यूल के तौर पर एम्बेड करें. इसके लिए, यह तरीका अपनाएं.
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
..
}
अन्य कॉन्फ़िगरेशन फ़ाइलें
वेंडर एपीईएक्स, कई अन्य कॉन्फ़िगरेशन फ़ाइलों के साथ काम करते हैं. ये फ़ाइलें आम तौर पर वेंडर पार्टीशन में, वेंडर एपीईएक्स में पहले से बनी हुई फ़ाइलों के तौर पर मिलती हैं. साथ ही, इनमें और भी फ़ाइलें जोड़ी जा रही हैं.
उदाहरण:
- सुविधा के एलान वाले एक्सएमएल
- सेंसर की सुविधा वाले XML, सेंसर HAL वेंडर APEX में प्रीबिल्ट के तौर पर मौजूद होते हैं
- कॉन्फ़िगरेशन फ़ाइलें इनपुट करना
- टचस्क्रीन कॉन्फ़िगरेशन, सिर्फ़ कॉन्फ़िगरेशन वाले वेंडर एपीईएक्स में प्रीबिल्ट के तौर पर कॉन्फ़िगर किए जाते हैं
बूटस्ट्रैप वेंडर APEX
एपीईएक्स चालू होने से पहले, keymint जैसी कुछ एचएएल सेवाएं उपलब्ध होनी चाहिए. ये HAL, आम तौर पर init स्क्रिप्ट में अपनी सेवा की परिभाषा में early_hal सेट करते हैं. इसका एक और उदाहरण animation क्लास है, जो आम तौर पर post-fs-data इवेंट से पहले शुरू होती है. जब ऐसी HAL सेवा को वेंडर APEX में पैकेज किया जाता है, तो APEX मेनिफ़ेस्ट में "vendorBootstrap": true को APEX बनाएं, ताकि इसे पहले चालू किया जा सके. ध्यान दें कि बूटस्ट्रैप एपीईएक्स को सिर्फ़ /vendor/apex जैसी पहले से बनी जगह से चालू किया जा सकता है, न कि /data/apex से.
सिस्टम प्रॉपर्टी
ये सिस्टम प्रॉपर्टी हैं, जिन्हें फ़्रेमवर्क, वेंडर के APEX को सपोर्ट करने के लिए पढ़ता है:
input_device.config_file.apex=<apex name>- इस विकल्प को सेट करने पर, इनपुट कॉन्फ़िगरेशन फ़ाइलों (*.idc,*.kl, और*.kcm) को APEX की/etc/usrडायरेक्ट्री में खोजा जाता है.ro.vulkan.apex=<apex name>- इस फ़्लैग को सेट करने पर, Vulkan ड्राइवर को APEX से लोड किया जाता है. Vulkan ड्राइवर का इस्तेमाल शुरुआती HAL करते हैं. इसलिए, APEX बूटस्ट्रैप APEX बनाएं और उस लिंकर नेमस्पेस को कॉन्फ़िगर करें, ताकि वह दिख सके.
setprop कमांड का इस्तेमाल करके, init स्क्रिप्ट में सिस्टम प्रॉपर्टी सेट करें.
अतिरिक्त सुविधाएं
बूटअप के समय APEX चुनना
उदाहरण:
बूट के दौरान, वेंडर APEX को चालू किया जा सकता है.
अगर सिस्टम प्रॉपर्टी ro.vendor.apex.<apex name> का इस्तेमाल करके फ़ाइल का नाम तय किया जाता है, तो उस <apex name> के लिए, सिर्फ़ फ़ाइल के नाम से मेल खाने वाला APEX चालू किया जाता है.
अगर इस सिस्टम प्रॉपर्टी को none पर सेट किया जाता है, तो <apex name> वाले APEX को अनदेखा कर दिया जाता है (चालू नहीं किया जाता). इस सुविधा का इस्तेमाल करके, एक ही नाम वाले APEX की कई कॉपी इंस्टॉल की जा सकती हैं. अगर एक ही APEX के कई वर्शन हैं, तो उनके लिए एक ही कुंजी का इस्तेमाल किया जाना चाहिए.
इस्तेमाल के उदाहरण:
- वाई-फ़ाई एचएएल वेंडर एपेक्स के तीन वर्शन इंस्टॉल करें: QA टीमें, एक वर्शन का इस्तेमाल करके मैन्युअल या ऑटोमेटेड टेस्टिंग कर सकती हैं. इसके बाद, दूसरे वर्शन में रीबूट करके टेस्ट फिर से चला सकती हैं. इसके बाद, वे फ़ाइनल नतीजों की तुलना कर सकती हैं.
- कैमरा HAL वेंडर APEX के दो वर्शन इंस्टॉल करें, मौजूदा और एक्सपेरिमेंट के तौर पर उपलब्ध: डॉगफ़ूडिंग करने वाले लोग, एक्सपेरिमेंट के तौर पर उपलब्ध वर्शन का इस्तेमाल कर सकते हैं. इसके लिए, उन्हें कोई अतिरिक्त फ़ाइल डाउनलोड और इंस्टॉल करने की ज़रूरत नहीं होती. इसलिए, वे आसानी से वापस मौजूदा वर्शन पर स्विच कर सकते हैं.
बूटअप के दौरान, apexd एक खास फ़ॉर्मैट में sysprops ढूंढता है, ताकि सही APEX वर्शन को चालू किया जा सके.
प्रॉपर्टी की के लिए मान्य फ़ॉर्मैट ये हैं:
- Bootconfig:
- इस कुकी का इस्तेमाल,
BoardConfig.mkमें डिफ़ॉल्ट वैल्यू सेट करने के लिए किया जाता है. androidboot.vendor.apex.<apex name>(ro.boot.vendor.apex.<apex name>के तौर पर एक्सपोर्ट किया गया).
- इस कुकी का इस्तेमाल,
- डाइनैमिक अर्ली-बूट कॉन्फ़िगरेशन (
init_dev_config):- हर एसकेयू के हिसाब से APEX को चालू और बंद करने के लिए, प्रोडक्शन मैकेनिज़्म का सुझाव दिया गया है. यह सुविधा Android 17 और इसके बाद के वर्शन में उपलब्ध है.
- यह कुकी, बूट होने पर
apexd-bootstrapके चलने से पहलेro.boot.vendor.apex.<apex name>को डाइनैमिक तरीके से सेट करती है. प्रॉपर्टी की वैल्यू कोnoneपर सेट करने से, APEX का ऐक्टिवेशन साफ़ तौर पर बंद हो जाता है. - आर्किटेक्चर की जानकारी के लिए, डिवाइस को जल्दी बूट करने की सुविधा का कॉन्फ़िगरेशन (
init_dev_config) देखें.
- परसिस्टेंट sysprop (अब सेवा में नहीं है):
persist.vendor.apex.<apex name>- यह सुविधा सिर्फ़ डेवलपमेंट के लिए है.
apexd,/dataपार्टीशन के माउंट होने से पहले, पहले से इंस्टॉल किए गए APEX को चालू करता है. इसलिए,/dataमें सेव किए गए परसिस्टेंट sysprops का इस्तेमाल, प्रोडक्शन बिल्ड में APEX को जल्दी चुनने के लिए नहीं किया जा सकता.
प्रॉपर्टी की वैल्यू, उस APEX का फ़ाइल नाम होना चाहिए जिसे चालू करना है. इसके अलावा, APEX को बंद करने के लिए none का इस्तेमाल किया जा सकता है.
// 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,
..
}
APEX चुनने के लिए bootconfig का इस्तेमाल करना
बिल्ड टाइम पर कौनसा APEX इस्तेमाल करना है, यह तय करने के लिए BoardConfig.mk में bootconfig का इस्तेमाल करके डिफ़ॉल्ट वर्शन कॉन्फ़िगर करें:
# 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
अगर डिवाइस पर फ़्लैश करने के बाद बूटकॉन्फ़िग अपडेट करने की सुविधा काम करती है (जैसे कि fastboot oem कमांड का इस्तेमाल करना), तो एक से ज़्यादा बार इंस्टॉल किए गए APEX के लिए बूटकॉन्फ़िग प्रॉपर्टी बदलने से, बूटअप पर चालू किया गया वर्शन भी बदल जाता है.
Cuttlefish पर आधारित वर्चुअल रेफ़रंस डिवाइसों के लिए, लॉन्च करते समय सीधे तौर पर बूटकॉन्फ़िग प्रॉपर्टी सेट करने के लिए, --extra_bootconfig_args कमांड का इस्तेमाल किया जा सकता है. उदाहरण के लिए:
launch_cvd --noresume \
--extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";
APEX चुनने के लिए init_dev_config का इस्तेमाल करना
Android 17 और इसके बाद के वर्शन में, वेंडर के एपीईएक्स को रनटाइम पर डाइनैमिक तरीके से चुनने या बंद करने के लिए, init_dev_config सेवा की मदद से वेंडर टूल लागू करें.
यह टूल, apexd-bootstrap से पहले early-init के दौरान चलता है. साथ ही, rustutils::system_properties का इस्तेमाल करके ro.boot.vendor.apex.* प्रॉपर्टी सेट करता है.
प्रॉपर्टी को किसी APEX के फ़ाइल नाम पर सेट करने से, चालू करने के लिए उस वर्शन को चुना जाता है. वहीं, वैल्यू को none पर सेट करने से, किसी APEX को चालू करने की सुविधा को साफ़ तौर पर बंद किया जा सकता है. उदाहरण के लिए, उन एसकेयू पर जहां हार्डवेयर पेरिफ़ेरल मौजूद नहीं हैं.
use rustutils::system_properties;
fn main() {
// Select an APEX version based on detected SKU, or disable it altogether:
let hal_apex = match sku_type {
1 => "com.oem.camera.hal.my_apex_default",
2 => "com.oem.camera.hal.my_apex_experimental",
_ => "none",
};
system_properties::write(
"ro.boot.vendor.apex.com.oem.camera.hal",
hal_apex,
).expect("Failed to set vendor APEX selection property");
}
डेवलपमेंट के लिए, परसिस्टेंट sysprops का इस्तेमाल करना (अब काम नहीं करता)
डेवलपमेंट और डीबग करने के लिए, डिवाइस बूट होने के बाद, चालू किए गए वर्शन को बदला जा सकता है. इसके लिए, परसिस्टेंट sysprop को सेट करें:
$ adb root;
$ adb shell setprop \
persist.vendor.apex.com.oem.camera.hal \
com.oem.camera.hal.my_apex_experimental;
$ adb reboot;