Android 11 में, product पार्टिशन को अलग कर दिया गया है. इससे यह system और vendor पार्टिशन से अलग हो जाता है. इन बदलावों के तहत, अब product पार्टिशन के नेटिव और Java इंटरफ़ेस के ऐक्सेस को कंट्रोल किया जा सकता है. यह vendor पार्टिशन के लिए इंटरफ़ेस लागू करने के तरीके जैसा ही है.
नेटिव इंटरफ़ेस लागू करना
नेटिव इंटरफ़ेस लागू करने की सुविधा चालू करने के लिए, PRODUCT_PRODUCT_VNDK_VERSION को current पर सेट करें. (जब टारगेट के लिए शिपिंग एपीआई लेवल 29 से ज़्यादा होता है, तो वर्शन अपने-आप current पर सेट हो जाता है.) इस सुविधा से ये काम किए जा सकते हैं:
productपार्टिशन में मौजूद नेटिव मॉड्यूल को लिंक करना:productपार्टिशन में मौजूद अन्य मॉड्यूल से स्टैटिक या डाइनैमिक तरीके से लिंक करना. इनमें स्टैटिक, शेयर की गई या हेडर लाइब्रेरी शामिल होती हैं.systemपार्टिशन में मौजूद वीएनडीके लाइब्रेरी से डाइनैमिक तरीके से लिंक करना.
productपार्टिशन में मौजूद अनबंडल किए गए APK में मौजूद JNI लाइब्रेरी को/product/libया/product/lib64में मौजूद लाइब्रेरी से लिंक करना. यह NDK लाइब्रेरी के अलावा है.
इस सुविधा से, product पार्टिशन के अलावा अन्य पार्टिशन से लिंक नहीं किया जा सकता.
बिल्ड टाइम पर इंटरफ़ेस लागू करना (Android.bp)
Android 11 में, सिस्टम मॉड्यूल, कोर और वेंडर इमेज वैरिएंट के अलावा, प्रॉडक्ट इमेज वैरिएंट भी बना सकते हैं. जब नेटिव इंटरफ़ेस लागू करने की सुविधा चालू होती है, तब PRODUCT_PRODUCT_VNDK_VERSION को current पर सेट किया जाता है:
productपार्टिशन में मौजूद नेटिव मॉड्यूल, कोर वैरिएंट के बजाय प्रॉडक्ट वैरिएंट में होते हैं.जिन मॉड्यूल की
Android.bpफ़ाइलों मेंproduct_available: trueहोता है वे प्रॉडक्ट वैरिएंट के लिए उपलब्ध होते हैं.जिन लाइब्रेरी या बाइनरी में
product_specific: trueहोता है वे उन अन्य लाइब्रेरी से लिंक हो सकती हैं जिनकीAndroid.bpफ़ाइलों मेंproduct_specific: trueयाproduct_available: trueहोता है.वीएनडीके लाइब्रेरी की
Android.bpफ़ाइलों मेंproduct_available: trueहोना चाहिए ताकिproductबाइनरी, वीएनडीके लाइब्रेरी से लिंक हो सकें.
नीचे दी गई टेबल में, इमेज वैरिएंट बनाने के लिए इस्तेमाल की जाने वाली Android.bp प्रॉपर्टी के बारे में बताया गया है.
| Android.bp में मौजूद प्रॉपर्टी | बनाए गए वैरिएंट | |
|---|---|---|
| इंटरफ़ेस लागू करने से पहले | इंटरफ़ेस लागू करने के बाद | |
| default (none) | core
(इसमें /system, /system_ext और
/product शामिल हैं) |
core
(इसमें /system और /system_ext शामिल हैं, लेकिन
/product नहीं) |
system_ext_specific: true |
core | core |
product_specific: true |
core | product |
vendor: true |
vendor | vendor |
vendor_available: true |
core, vendor | core, vendor |
product_available: true |
लागू नहीं | core, product |
vendor_available: true AND product_available:
true |
लागू नहीं | core, product, vendor |
system_ext_specific: true AND vendor_available:
true |
core, vendor | core, vendor |
product_specific: true AND vendor_available:
true |
core, vendor | product, vendor |
बिल्ड टाइम पर इंटरफ़ेस लागू करना (Android.mk)
जब नेटिव इंटरफ़ेस लागू करने की सुविधा चालू होती है, तब
product पार्टिशन में इंस्टॉल किए गए नेटिव मॉड्यूल में native:product लिंक टाइप होता है. यह सिर्फ़
अन्य native:product या native:vndk मॉड्यूल से लिंक हो सकता है. इनके अलावा किसी अन्य मॉड्यूल से लिंक करने की कोशिश करने पर, बिल्ड सिस्टम, लिंक टाइप की जांच में गड़बड़ी दिखाता है.
रनटाइम पर इंटरफ़ेस लागू करना
जब नेटिव इंटरफ़ेस लागू करने की सुविधा चालू होती है, तब बायोनिक लिंकर के लिए लिंकर कॉन्फ़िगरेशन, सिस्टम प्रोसेस को product लाइब्रेरी का इस्तेमाल करने की अनुमति नहीं देता. इससे product प्रोसेस के लिए product सेक्शन बनता है, जो product पार्टिशन के बाहर मौजूद लाइब्रेरी से लिंक नहीं हो सकता. हालांकि, ऐसी प्रोसेस, वीएनडीके लाइब्रेरी से लिंक हो सकती हैं. रनटाइम लिंक कॉन्फ़िगरेशन का उल्लंघन करने की कोशिश करने पर, प्रोसेस फ़ेल हो जाती है और CANNOT LINK EXECUTABLE गड़बड़ी का मैसेज दिखता है.
Java इंटरफ़ेस लागू करना
Java इंटरफ़ेस लागू करने की सुविधा चालू करने के लिए, PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE को true पर सेट करें. (जब टारगेट के लिए शिपिंग एपीआई लेवल 29 से ज़्यादा होता है, तो वैल्यू अपने-आप true पर सेट हो जाती है.) इस सुविधा को चालू करने पर, इन ऐक्सेस की अनुमति दी जा सकती है या नहीं दी जा सकती:
| एपीआई | /system | /system_ext | /product | /vendor | /data |
|---|---|---|---|---|---|
| पब्लिक एपीआई | |||||
| @SystemApi | |||||
| @hide API |
vendor पार्टिशन की तरह, product पार्टिशन में मौजूद किसी ऐप्लिकेशन या Java लाइब्रेरी को सिर्फ़ पब्लिक और सिस्टम एपीआई का इस्तेमाल करने की अनुमति होती है. छिपे हुए एपीआई का इस्तेमाल करने वाली लाइब्रेरी से लिंक करने की अनुमति नहीं होती. इस पाबंदी में, बिल्ड टाइम पर लिंक करना और रनटाइम में रिफ़्लेक्शन शामिल है.
बिल्ड टाइम पर इंटरफ़ेस लागू करना
बिल्ड टाइम पर, Make और Soong यह पुष्टि करते हैं कि product पार्टिशन में मौजूद Java मॉड्यूल, छिपे हुए एपीआई का इस्तेमाल न करें. इसके लिए, वे platform_apis और sdk_version फ़ील्ड की जांच करते हैं. product पार्टिशन में मौजूद ऐप्लिकेशन के sdk_version में current, system_current या एपीआई का न्यूमेरिक वर्शन होना चाहिए. साथ ही, platform_apis फ़ील्ड खाली होना चाहिए.
रनटाइम पर इंटरफ़ेस लागू करना
Android रनटाइम यह पुष्टि करता है कि product पार्टिशन में मौजूद ऐप्लिकेशन, छिपे हुए एपीआई का इस्तेमाल न करें. इसमें रिफ़्लेक्शन भी शामिल है. ज़्यादा जानकारी के लिए, एनडीके इंटरफ़ेस पर
पाबंदियां
देखें.
प्रॉडक्ट इंटरफ़ेस लागू करने की सुविधा चालू करना
प्रॉडक्ट इंटरफ़ेस लागू करने की सुविधा चालू करने के लिए, इस सेक्शन में दिया गया तरीका अपनाएं.
| चरण | टास्क | ज़रूरी है |
|---|---|---|
| 1 | अपना सिस्टम मेकफ़ाइल तय करें, जिसमें
system पार्टिशन के लिए पैकेज तय किए गए हों. इसके बाद, आर्टफ़ैक्ट पाथ की ज़रूरी शर्तों की जांच
device.mk में सेट करें, ताकि सिस्टम के अलावा अन्य मॉड्यूल को
system पार्टिशन में इंस्टॉल होने से रोका जा सके. |
नहीं |
| 2 | अनुमति वाली सूची को खाली करें. | नहीं |
| 3 | नेटिव इंटरफ़ेस लागू करें और रनटाइम लिंक की गड़बड़ियों की पहचान करें. इसे Java इंटरफ़ेस लागू करने की सुविधा के साथ-साथ चलाया जा सकता है. | Y |
| 4 | Java इंटरफ़ेस लागू करें और रनटाइम के व्यवहार की पुष्टि करें. इसे नेटिव इंटरफ़ेस लागू करने की सुविधा के साथ-साथ चलाया जा सकता है . | Y |
| 5 | रनटाइम के व्यवहार की जांच करें. | Y |
| 6 | device.mk को प्रॉडक्ट इंटरफ़ेस लागू करने की सुविधा के साथ अपडेट करें. |
Y |
पहला चरण: मेकफ़ाइल बनाना और आर्टफ़ैक्ट पाथ की जांच चालू करना
इस चरण में, system मेकफ़ाइल तय करें.
एक मेकफ़ाइल बनाएं, जिसमें
systemपार्टिशन के लिए पैकेज तय किए गए हों. उदाहरण के लिए,oem_system.mkफ़ाइल बनाएं. इसमें यह जानकारी शामिल करें:$(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk) # Applications PRODUCT_PACKAGES += \ CommonSystemApp1 \ CommonSystemApp2 \ CommonSystemApp3 \ # Binaries PRODUCT_PACKAGES += \ CommonSystemBin1 \ CommonSystemBin2 \ CommonSystemBin3 \ # Libraries PRODUCT_PACKAGES += \ CommonSystemLib1 \ CommonSystemLib2 \ CommonSystemLib3 \ PRODUCT_SYSTEM_NAME := oem_system PRODUCT_SYSTEM_BRAND := Android PRODUCT_SYSTEM_MANUFACTURER := Android PRODUCT_SYSTEM_MODEL := oem_system PRODUCT_SYSTEM_DEVICE := generic # For system-as-root devices, system.img should be mounted at /, so we # include ROOT here. _my_paths := \ $(TARGET_COPY_OUT_ROOT)/ \ $(TARGET_COPY_OUT_SYSTEM)/ \ $(call require-artifacts-in-path, $(_my_paths),)device.mkफ़ाइल में,systemपार्टिशन के लिए सामान्य मेकफ़ाइल इनहेरिट करें और आर्टफ़ैक्ट पाथ की ज़रूरी शर्तों की जांच चालू करें. उदाहरण के लिए:$(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk) # Enable artifact path requirements checking PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
आर्टफ़ैक्ट पाथ की ज़रूरी शर्तों के बारे में जानकारी
जब PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS को true या strict पर सेट किया जाता है, तब बिल्ड सिस्टम, अन्य मेकफ़ाइल में तय किए गए पैकेज को require-artifacts-in-path में तय किए गए पाथ पर इंस्टॉल होने से रोकता है. साथ ही, मौजूदा मेकफ़ाइल में तय किए गए पैकेज को require-artifacts-in-path में तय किए गए पाथ के बाहर आर्टफ़ैक्ट इंस्टॉल होने से रोकता है.
ऊपर दिए गए उदाहरण में, PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS को
strict पर सेट करने पर, oem_system.mk के बाहर मौजूद मेकफ़ाइल में,
the root या system पार्टिशन में इंस्टॉल किए गए मॉड्यूल शामिल नहीं किए जा सकते. इन मॉड्यूल को शामिल करने के लिए, आपको इन्हें oem_system.mk फ़ाइल में या शामिल की गई मेकफ़ाइल में तय करना होगा.
अनुमति न होने वाले पाथ पर मॉड्यूल इंस्टॉल करने की कोशिश करने पर, बिल्ड फ़ेल हो जाते हैं. बिल्ड फ़ेल होने की समस्या को ठीक करने के लिए, इनमें से कोई एक काम करें:
पहला विकल्प:
oem_system.mkमें शामिल मेकफ़ाइल में, सिस्टम मॉड्यूल शामिल करें. इससे आर्टफ़ैक्ट पाथ की ज़रूरी शर्त पूरी हो जाती है, क्योंकि अब मॉड्यूल, शामिल की गई मेकफ़ाइल में मौजूद हैं. इसलिए, `require-artifacts-in-path` में पाथ के सेट पर इंस्टॉल करने की अनुमति मिल जाती है.दूसरा विकल्प: मॉड्यूल को
system_extयाproductपार्टिशन में इंस्टॉल करें. साथ ही, मॉड्यूल कोsystemपार्टिशन में इंस्टॉल न करें.तीसरा विकल्प: मॉड्यूल को
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LISTमें जोड़ें. इसमें, इंस्टॉल किए जा सकने वाले मॉड्यूल की सूची दी जाती है.
दूसरा चरण: अनुमति वाली सूची को खाली करना
इस चरण में, PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST
को खाली करें, ताकि oem_system.mk शेयर करने वाले सभी डिवाइस, एक ही system
इमेज शेयर कर सकें. अनुमति वाली सूची को खाली करने के लिए, सूची में मौजूद किसी भी मॉड्यूल को
system_ext या product पार्टिशन में ले जाएं या उन्हें system मेकफ़ाइल में जोड़ें. यह चरण ज़रूरी नहीं है, क्योंकि प्रॉडक्ट इंटरफ़ेस लागू करने की सुविधा चालू करने के लिए, सामान्य system इमेज तय करना ज़रूरी नहीं है. हालांकि, अनुमति वाली सूची को खाली करने से, system_ext के साथ system बाउंड्री तय करने में
मदद मिलती है.
तीसरा चरण: नेटिव इंटरफ़ेस लागू करना
इस चरण में, PRODUCT_PRODUCT_VNDK_VERSION := current सेट करें. इसके बाद, बिल्ड और रनटाइम की गड़बड़ियां ढूंढें और उन्हें ठीक करें. डिवाइस बूट और लॉग की जांच करने, रनटाइम लिंक की गड़बड़ियां ढूंढने और उन्हें ठीक करने के लिए:
PRODUCT_PRODUCT_VNDK_VERSION := currentसेट करें.डिवाइस बनाएं और बिल्ड की गड़बड़ियां ढूंढें. ऐसा हो सकता है कि आपको प्रॉडक्ट वैरिएंट या कोर वैरिएंट न होने की वजह से, कुछ बिल्ड फ़ेल दिखें. आम तौर पर, ये बिल्ड फ़ेल होते हैं:
hidl_interfaceका कोई भी मॉड्यूल जिसमेंproduct_specific: trueहै, वह सिस्टम मॉड्यूल के लिए उपलब्ध नहीं होगा. इसे ठीक करने के लिए,product_specific: trueकोsystem_ext_specific: trueसे बदलें.- ऐसा हो सकता है कि मॉड्यूल में, प्रॉडक्ट मॉड्यूल के लिए ज़रूरी प्रॉडक्ट वैरिएंट मौजूद न हो. इसे ठीक करने के लिए, उस मॉड्यूल को
productपार्टिशन के लिए उपलब्ध कराएं. इसके लिए,product_available: trueसेट करें. इसके अलावा, मॉड्यूल कोproductपार्टिशन में ले जाएं. इसके लिए,product_specific: trueसेट करें.
बिल्ड की गड़बड़ियां ठीक करें और पक्का करें कि डिवाइस सफलतापूर्वक बिल्ड हो गया हो.
इमेज फ़्लैश करें और डिवाइस बूट और लॉग में रनटाइम की गड़बड़ियां ढूंढें.
- अगर टेस्ट केस लॉग में
linkerटैग,CANNOT LINK EXECUTABLEमैसेज दिखाता है, तो मेकफ़ाइल में कोई डिपेंडेंसी मौजूद नहीं है. साथ ही, इसे बिल्ड टाइम पर कैप्चर नहीं किया गया था. - बिल्ड सिस्टम से इसकी जांच करने के लिए, ज़रूरी लाइब्रेरी को
shared_libs:याrequired:फ़ील्ड में जोड़ें.
- अगर टेस्ट केस लॉग में
ऊपर दी गई सलाह का इस्तेमाल करके, मौजूद न रहने वाली डिपेंडेंसी को ठीक करें.
चौथा चरण: Java इंटरफ़ेस लागू करना
इस चरण में, PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true सेट करें. इसके बाद, बिल्ड की गड़बड़ियां ढूंढें और उन्हें ठीक करें. खास तौर पर, दो तरह की गड़बड़ियां ढूंढें:
लिंक टाइप की गड़बड़ियां. इस गड़बड़ी से पता चलता है कि कोई ऐप्लिकेशन, Java मॉड्यूल से लिंक है जिसका
sdk_versionज़्यादा है. इसे ठीक करने के लिए, ऐप्लिकेशन काsdk_versionबढ़ाया जा सकता है या लाइब्रेरी काsdk_versionसीमित किया जा सकता है. गड़बड़ी का उदाहरण:error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.सिंबल की गड़बड़ियां. इस गड़बड़ी से पता चलता है कि कोई सिंबल नहीं मिल रहा है, क्योंकि वह छिपे हुए एपीआई में है. इसे ठीक करने के लिए, दिखने वाले (छिपे हुए नहीं) एपीआई का इस्तेमाल करें या कोई दूसरा विकल्प ढूंढें. गड़बड़ी का उदाहरण:
frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader( ^ symbol: class ProxyAuthenticate location: class SipSessionGroup.SipSessionImpl
पांचवां चरण: रनटाइम के व्यवहार की जांच करना
इस चरण में, पुष्टि करें कि रनटाइम का व्यवहार आपकी उम्मीद के मुताबिक है. डीबग किए जा सकने वाले ऐप्लिकेशन के लिए, StrictMode.detectNonSdkApiUsage का इस्तेमाल करके, लॉग की मदद से छिपे हुए एपीआई के इस्तेमाल को मॉनिटर किया जा सकता है. इससे, ऐप्लिकेशन के छिपे हुए एपीआई का इस्तेमाल करने पर लॉग जनरेट होता है. इसके अलावा,
veridex
स्टैटिक विश्लेषण टूल का इस्तेमाल करके, इस्तेमाल का टाइप (लिंक करना या रिफ़्लेक्शन),
पाबंदी का लेवल, और कॉल स्टैक की जानकारी पाई जा सकती है.
Veridex सिंटैक्स:
./art/tools/veridex/appcompat.sh --dex-file={apk file}Veridex के नतीजे का उदाहरण:
#1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s): Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s): Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
Veridex के इस्तेमाल के बारे में ज़्यादा जानकारी के लिए, veridex टूल का इस्तेमाल करके टेस्ट करना देखें.
छठा चरण: device.mk अपडेट करना
बिल्ड और रनटाइम की सभी गड़बड़ियां ठीक करने और यह पुष्टि करने के बाद कि रनटाइम का व्यवहार आपकी उम्मीद के मुताबिक है, device.mk में यह जानकारी सेट करें:
PRODUCT_PRODUCT_VNDK_VERSION := currentPRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true