प्रॉडक्ट विभाजन इंटरफ़ेस लागू करें

Android 11, product पार्टीशन को अनबंड कर देता है. इससे यह system और vendor पार्टीशन से अलग हो जाता है. इन बदलावों के तहत, अब आपके पास product partition के नेटिव और Java इंटरफ़ेस के ऐक्सेस को कंट्रोल करने का विकल्प है. यह उसी तरह काम करता है जिस तरह vendor partition के लिए इंटरफ़ेस लागू करने की सुविधा काम करती है.

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

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

  • product पार्टीशन में मौजूद नेटिव मॉड्यूल, जिन्हें लिंक करना है:
    • product सेक्शन में मौजूद दूसरे मॉड्यूल में, स्टैटिक या डाइनैमिक तौर पर लागू किया जा सकता है. इन मॉड्यूल में स्टैटिक, शेयर की गई या हेडर लाइब्रेरी शामिल होती हैं.
    • system पार्टीशन में, VNDK लाइब्रेरी को डाइनैमिक तौर पर.
  • product पार्टीशन में मौजूद, बंडल नहीं किए गए APKs में 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 बताने वाली अन्य लाइब्रेरी से लिंक हो सकती हैं.

  • VNDK लाइब्रेरी की Android.bp फ़ाइलों में product_available: true होना ज़रूरी है, ताकि product बाइनरी, VNDK लाइब्रेरी से लिंक हो सकें.

इस टेबल में, इमेज के वैरिएंट बनाने के लिए इस्तेमाल की जाने वाली 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 लागू नहीं core, product, vendor
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 partition की तरह ही, product partition में मौजूद किसी ऐप्लिकेशन या Java लाइब्रेरी को सिर्फ़ सार्वजनिक और सिस्टम एपीआई का इस्तेमाल करने की अनुमति है. साथ ही, ऐसी लाइब्रेरी से लिंक करने की अनुमति नहीं है जो छिपे हुए एपीआई का इस्तेमाल करती है. इस पाबंदी में, बिल्ड के समय लिंक करने और रनटाइम में रिफ़्लेक्शन शामिल है.

बिल्ड प्रोसेस में लगने वाले समय को लागू करना

बिल्ड के समय, Make और Soong यह पुष्टि करते हैं कि product partition में मौजूद Java मॉड्यूल, platform_apis और sdk_version फ़ील्ड की जांच करके, छिपे हुए एपीआई का इस्तेमाल नहीं करते. product पार्टीशन में मौजूद ऐप्लिकेशन के sdk_version एट्रिब्यूट की वैल्यू के तौर पर, एपीआई के current, system_current या अंकों वाले वर्शन का इस्तेमाल किया जाना चाहिए. साथ ही, platform_apis फ़ील्ड खाली होना चाहिए.

रनटाइम पर लागू होने वाले नियम

Android रनटाइम इस बात की पुष्टि करता है कि product पार्टिशन में मौजूद ऐप्लिकेशन, छिपे हुए एपीआई का इस्तेमाल नहीं करते. इनमें रिफ़्लेक्शन भी शामिल है. ज़्यादा जानकारी के लिए, SDK के अलावा अन्य इंटरफ़ेस पर पाबंदियां लेख पढ़ें.

प्रॉडक्ट इंटरफ़ेस लागू करने की सुविधा चालू करना

प्रॉडक्ट इंटरफ़ेस पर, नीति उल्लंघन ठीक करने के तरीके (एनफ़ोर्समेंट) को चालू करने के लिए, इस सेक्शन में दिया गया तरीका अपनाएं.

चरण टास्क ज़रूरी है
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 partition के लिए सामान्य मेकफ़ाइल को इनहेरिट करें और आर्टफ़ैक्ट पाथ की ज़रूरी शर्तों की जांच करने की सुविधा चालू करें. उदाहरण के लिए:

    $(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 फ़ाइल में या किसी शामिल Makefile में तय करना होगा. जिन पाथ पर मॉड्यूल इंस्टॉल करने की अनुमति नहीं है उन पर मॉड्यूल इंस्टॉल करने की कोशिश करने पर, बिल्डिंग रुक जाती है. ब्रेक को ठीक करने के लिए, इनमें से कोई एक काम करें:

  • पहला विकल्प: 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_available: true को सेट करके उस मॉड्यूल को product partition के लिए उपलब्ध कराएं या product_specific: true को सेट करके मॉड्यूल को product partition में ले जाएं.
  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