পণ্য পার্টিশন ইন্টারফেস প্রয়োগ করুন

অ্যান্ড্রয়েড ১১ product পার্টিশনকে system এবং vendor পার্টিশন থেকে আলাদা করে দেয়। এই পরিবর্তনের অংশ হিসেবে, এখন আপনি product পার্টিশনের নেটিভ এবং জাভা ইন্টারফেসে অ্যাক্সেস নিয়ন্ত্রণ করতে পারবেন (যা vendor পার্টিশনের ইন্টারফেস এনফোর্সমেন্ট যেভাবে কাজ করে তার অনুরূপ)।

নেটিভ ইন্টারফেস প্রয়োগ করুন

নেটিভ ইন্টারফেস এনফোর্সমেন্ট সক্রিয় করতে, PRODUCT_PRODUCT_VNDK_VERSION current এ সেট করুন। (টার্গেটের জন্য শিপিং API লেভেল ২৯-এর বেশি হলে ভার্সনটি স্বয়ংক্রিয়ভাবে current এ সেট হয়ে যায়।) এনফোর্সমেন্ট নিম্নলিখিত বিষয়গুলোর অনুমতি দেয়:

  • লিঙ্ক করার জন্য product পার্টিশনের নেটিভ মডিউলগুলি:
    • product পার্টিশনের অন্যান্য মডিউলগুলিতে স্ট্যাটিক্যালি বা ডাইনামিক্যালি, যেগুলিতে স্ট্যাটিক, শেয়ার্ড বা হেডার লাইব্রেরি অন্তর্ভুক্ত রয়েছে।
    • system পার্টিশনে VNDK লাইব্রেরিগুলো ডাইনামিকভাবে যুক্ত করুন।
  • product পার্টিশনে থাকা আনবান্ডেলড APK-গুলোর JNI লাইব্রেরিগুলো /product/lib অথবা /product/lib64 এ থাকা লাইব্রেরিগুলোর সাথে লিঙ্ক করে (এটি NDK লাইব্রেরিগুলোর অতিরিক্ত)।

এনফোর্সমেন্ট product পার্টিশন ছাড়া অন্য কোনো পার্টিশনে লিঙ্কের অনুমতি দেয় না।

বিল্ড টাইমে প্রয়োগ (Android.bp)

অ্যান্ড্রয়েড ১১-এ, সিস্টেম মডিউলগুলো কোর এবং ভেন্ডর ইমেজ ভ্যারিয়েন্টের পাশাপাশি একটি প্রোডাক্ট ইমেজ ভ্যারিয়েন্টও তৈরি করতে পারে। যখন নেটিভ ইন্টারফেস এনফোর্সমেন্ট সক্রিয় করা হয় ( PRODUCT_PRODUCT_VNDK_VERSION current এ সেট করা হয়):

  • product পার্টিশনের নেটিভ মডিউলগুলো কোর ভ্যারিয়েন্টের পরিবর্তে প্রোডাক্ট ভ্যারিয়েন্টে থাকে।

  • যেসব মডিউলের Android.bp ফাইলে product_available: true থাকে, সেগুলো প্রোডাক্ট ভ্যারিয়েন্টের জন্য উপলব্ধ হয়।

  • যেসব লাইব্রেরি বা বাইনারি তাদের Android.bp ফাইলে product_specific: true উল্লেখ করে, তারা এমন অন্যান্য লাইব্রেরির সাথে লিঙ্ক করতে পারে যেগুলো 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 প্রযোজ্য নয় মূল, পণ্য, বিক্রেতা
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 পার্টিশনের বাইরের লাইব্রেরির সাথে লিঙ্ক করতে পারে না (তবে, এই ধরনের প্রসেসগুলো VNDK লাইব্রেরির সাথে লিঙ্ক করতে পারে)। রানটাইম লিঙ্ক কনফিগারেশন লঙ্ঘন করার চেষ্টা করলে প্রসেসটি ব্যর্থ হয় এবং একটি CANNOT LINK EXECUTABLE ত্রুটি বার্তা তৈরি করে।

জাভা ইন্টারফেস প্রয়োগ করুন

জাভা ইন্টারফেস এনফোর্সমেন্ট সক্রিয় করতে, PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE true তে সেট করুন। (টার্গেটের শিপিং এপিআই লেভেল ২৯-এর বেশি হলে এই মানটি স্বয়ংক্রিয়ভাবে true তে সেট হয়ে যায়।) সক্রিয় করা হলে, এই এনফোর্সমেন্ট নিম্নলিখিত অ্যাক্সেস অনুমোদন বা বাতিল করে:

এপিআই /সিস্টেম /সিস্টেম_এক্সট /পণ্য বিক্রেতা /ডেটা
পাবলিক এপিআই
@সিস্টেমএপিআই
@hide API

vendor পার্টিশনের মতোই, product পার্টিশনের কোনো অ্যাপ বা জাভা লাইব্রেরি শুধুমাত্র পাবলিক এবং সিস্টেম এপিআই ব্যবহার করতে পারে; হিডেন এপিআই ব্যবহারকারী কোনো লাইব্রেরির সাথে লিঙ্ক করার অনুমতি নেই। এই বিধিনিষেধটি বিল্ড টাইমের লিঙ্কিং এবং রানটাইমের রিফ্লেকশনের ক্ষেত্রেও প্রযোজ্য।

নির্মাণ সময় প্রয়োগ

বিল্ড করার সময়, Make এবং Soong platform_apis এবং sdk_version ফিল্ডগুলো পরীক্ষা করে নিশ্চিত করে যে product পার্টিশনের জাভা মডিউলগুলো কোনো হিডেন এপিআই (hidden API) ব্যবহার করছে না। product পার্টিশনের অ্যাপগুলোর sdk_version ফিল্ডটি অবশ্যই এপিআই-এর current , system_current , বা সংখ্যাসূচক ভার্সন দিয়ে পূরণ করতে হবে এবং platform_apis ফিল্ডটি খালি থাকতে হবে।

রানটাইম প্রয়োগ

অ্যান্ড্রয়েড রানটাইম যাচাই করে যে product পার্টিশনের অ্যাপগুলো রিফ্লেকশন সহ কোনো হিডেন এপিআই ব্যবহার করছে না। বিস্তারিত জানতে, ‘নন-এসডিকে ইন্টারফেসের উপর বিধিনিষেধ’ দেখুন।

পণ্য ইন্টারফেস প্রয়োগ সক্ষম করুন

প্রোডাক্ট ইন্টারফেস এনফোর্সমেন্ট সক্রিয় করতে এই বিভাগের ধাপগুলো ব্যবহার করুন।

ধাপ কাজ প্রয়োজনীয়
আপনার নিজস্ব একটি সিস্টেম মেকফাইল তৈরি করুন যা system পার্টিশনের জন্য প্যাকেজগুলো নির্দিষ্ট করবে, তারপর device.mk তে আর্টিফ্যাক্টস পাথ রিকোয়ারমেন্ট চেক সেট করুন (যাতে নন-সিস্টেম মডিউলগুলো system পার্টিশনে ইনস্টল হতে না পারে)। এন
অনুমোদিত তালিকাটি পরিষ্করণ করুন। এন
নেটিভ ইন্টারফেস প্রয়োগ করুন এবং রানটাইম লিঙ্ক ব্যর্থতা শনাক্ত করুন (এটি জাভা প্রয়োগের সাথে সমান্তরালভাবে চালানো যেতে পারে)। ওয়াই
জাভা ইন্টারফেস প্রয়োগ করুন এবং রানটাইম আচরণ যাচাই করুন (নেটিভ প্রয়োগের সাথে সমান্তরালে চালানো যেতে পারে)। ওয়াই
রানটাইম আচরণ পরীক্ষা করুন। ওয়াই
প্রোডাক্ট ইন্টারফেস এনফোর্সমেন্ট সহ device.mk আপডেট করুন। ওয়াই

ধাপ ১: মেকফাইল তৈরি করুন এবং আর্টিফ্যাক্ট পাথ চেক সক্রিয় করুন

এই ধাপে আপনি 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 বাইরের মেকফাইলগুলো 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_available: true সেট করে মডিউলটিকে product পার্টিশনে উপলব্ধ করুন অথবা product_specific: true সেট করে মডিউলটিকে product পার্টিশনে স্থানান্তর করুন।
  3. বিল্ড ত্রুটিগুলি সমাধান করুন এবং ডিভাইসটি সফলভাবে বিল্ড হওয়া নিশ্চিত করুন।

  4. ইমেজটি ফ্ল্যাশ করুন এবং ডিভাইস বুট ও লগগুলিতে রানটাইম ত্রুটিগুলি সন্ধান করুন।

    • যদি কোনো টেস্ট কেস লগের linker ট্যাগে ‘ CANNOT LINK EXECUTABLE বার্তাটি দেখা যায়, তাহলে মেক ফাইলে কোনো একটি ডিপেন্ডেন্সি অনুপস্থিত (এবং সেটি বিল্ড করার সময় ক্যাপচার করা হয়নি)।
    • বিল্ড সিস্টেম থেকে এটি পরীক্ষা করতে, প্রয়োজনীয় লাইব্রেরিটি shared_libs: অথবা required: ফিল্ডে যোগ করুন।
  5. উপরে প্রদত্ত নির্দেশনা ব্যবহার করে অনুপস্থিত নির্ভরতাগুলো সমাধান করুন।

ধাপ ৪: জাভা ইন্টারফেস প্রয়োগ করুন

এই ধাপে, আপনি 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.
    
  • প্রতীক ত্রুটি। এই ত্রুটি নির্দেশ করে যে একটি প্রতীক খুঁজে পাওয়া যাচ্ছে না কারণ এটি একটি লুকানো API-তে রয়েছে। এটি ঠিক করতে, একটি দৃশ্যমান (লুকানো নয়) API ব্যবহার করুন অথবা একটি বিকল্প খুঁজুন। ত্রুটির উদাহরণ:

    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 ব্যবহার করে লগের মাধ্যমে হিডেন এপিআই-এর ব্যবহার নিরীক্ষণ করতে পারেন (অ্যাপটি কোনো হিডেন এপিআই ব্যবহার করলে এটি একটি লগ তৈরি করে)। বিকল্পভাবে, আপনি ব্যবহারের ধরন (লিঙ্কিং বা রিফ্লেকশন), রেস্ট্রিকশন লেভেল এবং কল স্ট্যাক জানার জন্য ভেরিডেক্স স্ট্যাটিক অ্যানালাইসিস টুলটি ব্যবহার করতে পারেন।

  • ভেরিডেক্স সিনট্যাক্স:

    ./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;
    

ভেরিডেক্স ব্যবহারের বিস্তারিত তথ্যের জন্য, “ভেরিডেক্স টুল ব্যবহার করে পরীক্ষা করুন” দেখুন।

ধাপ ৬: device.mk আপডেট করুন।

সমস্ত বিল্ড ও রানটাইম ব্যর্থতা সমাধান করার পর এবং রানটাইম আচরণ প্রত্যাশিত কিনা তা যাচাই করার পর, device.mk ফাইলে নিম্নলিখিত বিষয়গুলো সেট করুন:

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true