प्रॉडक्ट के अलग-अलग हिस्सों के इंटरफ़ेस लागू करना

Android 11 में, product पार्टिशन को अलग कर दिया गया है. इससे यह system और vendor पार्टिशन से अलग हो जाता है. इन बदलावों के तहत, अब आपके पास यह कंट्रोल करने का विकल्प है कि product पार्टीशन, नेटिव और Java इंटरफ़ेस को ऐक्सेस कर सकता है या नहीं. यह ठीक उसी तरह काम करता है जिस तरह product पार्टीशन के लिए इंटरफ़ेस लागू करने की सुविधा काम करती है.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 फ़ाइलों में मौजूद Android.bp वाले मॉड्यूल, प्रॉडक्ट वैरिएंट के लिए उपलब्ध होते हैं.product_available: true

  • product_specific: true के बारे में बताने वाली लाइब्रेरी या बाइनरी, product_specific: true या product_available: true के बारे में बताने वाली अन्य लाइब्रेरी से लिंक हो सकती हैं. इसके लिए, उन्हें अपनी Android.bp फ़ाइलों में ऐसा करना होगा.

  • वीएनडीके लाइब्रेरी की Android.bp फ़ाइलों में product_available: true होना चाहिए, ताकि product बाइनरी, वीएनडीके लाइब्रेरी से लिंक हो सकें.

यहां दी गई टेबल में, इमेज के अलग-अलग वर्शन बनाने के लिए इस्तेमाल की गई Android.bp प्रॉपर्टी के बारे में खास जानकारी दी गई है.

Android.bp फ़ाइल में मौजूद प्रॉपर्टी बनाए गए वैरिएंट
नीति उल्लंघन ठीक करने के लिए कार्रवाई करने से पहले नीति उल्लंघन ठीक करने के बाद
डिफ़ॉल्ट (कोई नहीं) core
(includes /system, /system_ext and /product)
कोर
(इसमें /system और /system_ext शामिल हैं, लेकिन /product नहीं)
system_ext_specific: true कोर कोर
product_specific: true कोर प्रॉडक्ट
vendor: true वेंडर वेंडर
vendor_available: true कोर, वेंडर कोर, वेंडर
product_available: true लागू नहीं कोर, प्रॉडक्ट
vendor_available: true और product_available: true लागू नहीं कोर, प्रॉडक्ट, वेंडर
system_ext_specific: true और vendor_available: true कोर, वेंडर कोर, वेंडर
product_specific: true और vendor_available: true कोर, वेंडर प्रॉडक्ट, वेंडर

बिल्ड टाइम एनफ़ोर्समेंट (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
Public API
@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 makefile तय किया जाता है.

  1. एक मेकफ़ाइल बनाएं, जो 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),)
    
  2. 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 के बाहर मौजूद मेकफ़ाइल में, 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 सेट किया जाता है. इसके बाद, बिल्ड और रनटाइम से जुड़ी गड़बड़ियों का पता लगाया जाता है और उन्हें ठीक किया जाता है. डिवाइस बूट और लॉग की जांच करने के लिए. साथ ही, रनटाइम लिंक फ़ेल होने की गड़बड़ियों को ढूंढने और उन्हें ठीक करने के लिए:

  1. PRODUCT_PRODUCT_VNDK_VERSION := current सेट करें.

  2. डिवाइस बनाएं और बिल्ड से जुड़ी गड़बड़ियों का पता लगाएं. ऐसा हो सकता है कि आपको प्रॉडक्ट के वैरिएंट या मुख्य वैरिएंट मौजूद न होने की वजह से, कुछ बिल्ड ब्रेक दिखें. आम तौर पर, इन ब्रेक का इस्तेमाल किया जाता है:

    • product_specific: true वाला कोई भी hidl_interface मॉड्यूल, सिस्टम मॉड्यूल के लिए उपलब्ध नहीं होगा. इस समस्या को ठीक करने के लिए, product_specific: true को system_ext_specific: true से बदलें.
    • ऐसा हो सकता है कि मॉड्यूल में, प्रॉडक्ट मॉड्यूल के लिए ज़रूरी प्रॉडक्ट वैरिएंट मौजूद न हो. इस समस्या को ठीक करने के लिए, उस मॉड्यूल को product पार्टीशन के लिए उपलब्ध कराएं. इसके लिए, product_available: true सेट करें या मॉड्यूल को product पार्टीशन में ले जाएं. इसके लिए, product_specific: true सेट करें.
  3. बिल्ड से जुड़ी गड़बड़ियों को ठीक करें और पक्का करें कि डिवाइस सफलतापूर्वक बिल्ड हो गया हो.

  4. इमेज को फ़्लैश करें और डिवाइस के बूट होने और लॉग में रनटाइम की गड़बड़ियों का पता लगाएं.

    • अगर टेस्ट केस के लॉग में मौजूद linker टैग, CANNOT LINK EXECUTABLE मैसेज दिखाता है, तो इसका मतलब है कि मेक फ़ाइल में कोई डिपेंडेंसी मौजूद नहीं है. साथ ही, इसे बिल्ड टाइम पर कैप्चर नहीं किया गया था.
    • इसे बिल्ड सिस्टम से देखने के लिए, shared_libs: या required: फ़ील्ड में ज़रूरी लाइब्रेरी जोड़ें.
  5. ऊपर दिए गए दिशा-निर्देशों का इस्तेमाल करके, ज़रूरी डिपेंडेंसी की समस्या हल करें.

चौथा चरण: 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 := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true