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

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 मेकफ़ाइल तय करें.

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

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

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

    • hidl_interface का कोई भी मॉड्यूल जिसमें product_specific: true है, वह सिस्टम मॉड्यूल के लिए उपलब्ध नहीं होगा. इसे ठीक करने के लिए, 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