उत्पाद विभाजन इंटरफेस को लागू करना

एंड्रॉइड 11 product विभाजन को अनबंडल करता है, जिससे यह system और vendor विभाजन से स्वतंत्र हो जाता है। इन परिवर्तनों के भाग के रूप में, अब आप product विभाजन की मूल और जावा इंटरफेस तक पहुंच को नियंत्रित कर सकते हैं (जो vendor विभाजन के लिए इंटरफ़ेस प्रवर्तन कैसे काम करता है इसके समान है)।

देशी इंटरफेस लागू करना

मूल इंटरफ़ेस प्रवर्तन को सक्षम करने के लिए, PRODUCT_PRODUCT_VNDK_VERSION को current पर सेट करें। (लक्ष्य के लिए शिपिंग एपीआई स्तर 29 से अधिक होने पर संस्करण स्वचालित रूप से current पर सेट हो जाता है।) प्रवर्तन अनुमति देता है:

  • लिंक करने के लिए product विभाजन में मूल मॉड्यूल:
    • product विभाजन में अन्य मॉड्यूल के लिए स्थिर या गतिशील रूप से जिसमें स्थिर, साझा या हेडर लाइब्रेरी शामिल हैं।
    • system विभाजन में VNDK लाइब्रेरीज़ के लिए गतिशील रूप से।
  • /product/lib या /product/lib64 में लाइब्रेरीज़ से लिंक करने के लिए product विभाजन में अनबंडल किए गए APK में JNI लाइब्रेरीज़ (यह NDK लाइब्रेरीज़ के अतिरिक्त है)।

प्रवर्तन product विभाजन के अलावा विभाजन के अन्य लिंक की अनुमति नहीं देता है।

निर्माण समय प्रवर्तन (Android.bp)

एंड्रॉइड 11 में, सिस्टम मॉड्यूल कोर और विक्रेता छवि वेरिएंट के अलावा एक उत्पाद छवि संस्करण बना सकते हैं। जब मूल इंटरफ़ेस प्रवर्तन सक्षम किया जाता है ( PRODUCT_PRODUCT_VNDK_VERSION को current पर सेट किया जाता है):

  • product विभाजन में मूल मॉड्यूल मूल संस्करण के बजाय उत्पाद संस्करण में हैं।

  • product_available: true वाले मॉड्यूल उनकी Android.bp फ़ाइलों में उत्पाद संस्करण के लिए उपलब्ध हैं।

  • लाइब्रेरी या बायनेरिज़ जो product_specific: true निर्दिष्ट करती हैं, वे अन्य लाइब्रेरी से लिंक हो सकती हैं जो अपनी Android.bp फ़ाइलों में product_specific: true या product_available: true निर्दिष्ट करती हैं।

  • VNDK पुस्तकालयों की Android.bp फ़ाइलों में product_available: true होना चाहिए ताकि product बायनेरिज़ VNDK libs से लिंक हो सकें।

निम्न तालिका छवि वेरिएंट बनाने के लिए उपयोग की जाने वाली Android.bp गुणों का सारांश प्रस्तुत करती है।

Android.bp में गुण वेरिएंट बनाए गए
प्रवर्तन से पहले प्रवर्तन के बाद
डिफ़ॉल्ट (कोई नहीं) मुख्य

(इसमें /system , /system_ext और /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 त्रुटि संदेश उत्पन्न होता है।

जावा इंटरफ़ेस लागू करना

जावा इंटरफ़ेस प्रवर्तन को सक्षम करने के लिए, PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE को true पर सेट करें। (लक्ष्य के लिए शिपिंग एपीआई स्तर 29 से अधिक होने पर मान स्वचालित रूप से true पर सेट हो जाता है।) सक्षम होने पर, प्रवर्तन निम्नलिखित पहुंच की अनुमति/अस्वीकृति देता है।

एपीआई /प्रणाली /system_ext /उत्पाद /विक्रेता /डेटा
सार्वजनिक एपीआई
@SystemApi
@एपीआई छुपाएं

vendor विभाजन की तरह, product विभाजन में एक ऐप या जावा लाइब्रेरी को केवल सार्वजनिक और सिस्टम एपीआई का उपयोग करने की अनुमति है; छिपी हुई एपीआई का उपयोग करने वाली लाइब्रेरी से लिंक करने की अनुमति नहीं है। इस प्रतिबंध में बिल्ड टाइम पर लिंक करना और रनटाइम में प्रतिबिंब शामिल है।

समय प्रवर्तन बनाएँ

निर्माण के समय, मेक और सूंग platform_apis और sdk_version फ़ील्ड की जांच करके सत्यापित करते हैं कि product विभाजन में जावा मॉड्यूल छिपे हुए एपीआई का उपयोग नहीं करते हैं। product विभाजन में ऐप्स का sdk_version current , system_current , या API के संख्यात्मक संस्करण से भरा होना चाहिए, और platform_apis फ़ील्ड खाली होना चाहिए।

रनटाइम प्रवर्तन

एंड्रॉइड रनटाइम सत्यापित करता है कि product विभाजन में ऐप्स प्रतिबिंब सहित छिपे हुए एपीआई का उपयोग नहीं करते हैं। विवरण के लिए, गैर-एसडीके इंटरफेस पर प्रतिबंध देखें।

उत्पाद इंटरफ़ेस प्रवर्तन सक्षम करना

उत्पाद इंटरफ़ेस प्रवर्तन को सक्षम करने के लिए इस अनुभाग में दिए गए चरणों का उपयोग करें।

कदम काम आवश्यक
1 अपने स्वयं के सिस्टम मेकफ़ाइल को परिभाषित करें जो system विभाजन के लिए पैकेज निर्दिष्ट करता है, फिर device.mk में आर्टिफैक्ट पथ आवश्यकता जांच सेट करें (नॉनसिस्टम मॉड्यूल को system विभाजन में स्थापित होने से रोकने के लिए)। एन
2 अनुमत सूची साफ़ करें. एन
3 मूल इंटरफ़ेस लागू करें और रनटाइम लिंक विफलताओं की पहचान करें (जावा प्रवर्तन के समानांतर चल सकते हैं)। वाई
4 जावा इंटरफेस को लागू करें और रनटाइम व्यवहार को सत्यापित करें (मूल प्रवर्तन के साथ समानांतर में चल सकता है)। वाई
5 रनटाइम व्यवहार की जाँच करें. वाई
6 उत्पाद इंटरफ़ेस प्रवर्तन के साथ device.mk अपडेट करें। वाई

चरण 1: मेकफ़ाइल बनाएं और आर्टिफैक्ट पथ जांच सक्षम करें

इस चरण में, आप 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 में परिभाषित पथों के बाहर कलाकृतियों को स्थापित करने से रोकता है। require-artifacts-in-path

उपरोक्त उदाहरण में, PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS को strict पर सेट करने के साथ, oem_system.mk के बाहर की मेकफ़ाइलें root या system विभाजन में स्थापित मॉड्यूल को शामिल नहीं कर सकती हैं। इन मॉड्यूल को शामिल करने के लिए, आपको या तो उन्हें oem_system.mk फ़ाइल में या सम्मिलित मेकफ़ाइल में परिभाषित करना होगा। अस्वीकृत पथों पर मॉड्यूल स्थापित करने का प्रयास बिल्ड ब्रेक का कारण बनता है। ब्रेक ठीक करने के लिए, निम्न में से कोई एक कार्य करें:

  • विकल्प 1: oem_system.mk में शामिल मेकफ़ाइल्स में सिस्टम मॉड्यूल शामिल करें। इससे आर्टिफैक्ट पथ की आवश्यकता पूरी हो जाती है (क्योंकि मॉड्यूल अब सम्मिलित मेकफ़ाइल में मौजूद हैं) और इस प्रकार 'आवश्यकता-आर्टिफैक्ट्स-इन-पाथ' में पथों के सेट पर इंस्टॉलेशन की अनुमति मिलती है।

  • विकल्प 2: मॉड्यूल को system_ext या product विभाजन में स्थापित करें (और system विभाजन में मॉड्यूल स्थापित न करें)।

  • विकल्प 3: PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST में मॉड्यूल जोड़ें। यह सूची उन मॉड्यूलों को सूचीबद्ध करती है जिन्हें स्थापित करने की अनुमति है।

चरण 2: अनुमत सूची खाली करें

इस चरण में, आप PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST को खाली कर देते हैं ताकि oem_system.mk साझा करने वाले सभी डिवाइस एकल system छवि भी साझा कर सकें। अनुमत सूची को खाली करने के लिए, सूची में किसी भी मॉड्यूल को system_ext या product विभाजन में ले जाएं या उन्हें system मेक फ़ाइलों में जोड़ें। यह चरण वैकल्पिक है क्योंकि उत्पाद इंटरफ़ेस प्रवर्तन को सक्षम करने के लिए सामान्य system छवि को परिभाषित करना आवश्यक नहीं है। हालाँकि, अनुमत सूची को खाली करना system_ext के साथ system सीमा को परिभाषित करने में सहायक है।

चरण 3: मूल इंटरफ़ेस लागू करें

इस चरण में, आप PRODUCT_PRODUCT_VNDK_VERSION := current सेट करें, फिर बिल्ड और रनटाइम त्रुटियों को देखें और उनका समाधान करें। डिवाइस बूट और लॉग की जांच करने और रनटाइम लिंक विफलताओं को ढूंढने और ठीक करने के लिए:

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

  2. डिवाइस बनाएं और बिल्ड त्रुटियों की तलाश करें। आपको अनुपलब्ध उत्पाद वेरिएंट या मुख्य वेरिएंट के लिए कुछ बिल्ड ब्रेक देखने की संभावना है। सामान्य ब्रेक में शामिल हैं:

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

  4. छवि को फ्लैश करें और डिवाइस बूट और लॉग में रनटाइम त्रुटियों को देखें।

    • यदि परीक्षण केस लॉग से linker टैग एक CANNOT LINK EXECUTABLE संदेश दिखाता है, तो मेक फ़ाइल में एक निर्भरता नहीं है (और निर्माण समय पर कैप्चर नहीं किया गया था)।
    • इसे बिल्ड सिस्टम से जांचने के लिए, आवश्यक लाइब्रेरी को shared_libs: या required: फ़ील्ड में जोड़ें।
  5. ऊपर दिए गए मार्गदर्शन का उपयोग करके लुप्त निर्भरताओं का समाधान करें।

चरण 4: जावा इंटरफेस लागू करें

इस चरण में, आप PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true सेट करें, फिर परिणामी बिल्ड त्रुटियों को ढूंढें और ठीक करें। दो विशिष्ट प्रकार की त्रुटियाँ देखें:

  • लिंक प्रकार की त्रुटियाँ. यह त्रुटि इंगित करती है कि एक ऐप जावा मॉड्यूल से लिंक करता है जिसमें व्यापक 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
    

चरण 5: रनटाइम व्यवहार की जाँच करें

इस चरण में, आप सत्यापित करते हैं कि रनटाइम व्यवहार अपेक्षा के अनुरूप हैं। डिबग करने योग्य ऐप्स के लिए, आप StrictMode.detectNonSdkApiUsage का उपयोग करके लॉग द्वारा छिपे हुए एपीआई उपयोग की निगरानी कर सकते हैं (जो ऐप द्वारा छिपे हुए एपीआई का उपयोग करने पर एक लॉग उत्पन्न करता है)। वैकल्पिक रूप से, आप उपयोग के प्रकार (लिंकिंग या प्रतिबिंब), प्रतिबंध स्तर और कॉल स्टैक प्राप्त करने के लिए वेरिडेक्स स्थैतिक विश्लेषण उपकरण का उपयोग कर सकते हैं।

  • वेरिडेक्स सिंटैक्स:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
    
  • उदाहरण वेरिडेक्स परिणाम:

    #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;
    

वेरिडेक्स उपयोग के विवरण के लिए, वेरिडेक्स टूल का उपयोग करके परीक्षण देखें।

चरण 6: डिवाइस.एमके को अपडेट करें

सभी बिल्ड और रनटाइम विफलताओं को ठीक करने और यह सत्यापित करने के बाद कि रनटाइम व्यवहार अपेक्षित है, निम्नलिखित को device.mk में सेट करें:

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true