HAL-এর জন্য AIDL

Android 11, Android-এ HAL-এর জন্য AIDL ব্যবহার করার সুবিধা নিয়ে এসেছে, এর ফলে HIDL ছাড়াই Android-এর অংশগুলি ইমপ্লিমেন্ট করা সম্ভব হয়েছে। যেখানে সম্ভব সেখানে AIDL এক্সক্লুসিভ ব্যবহার করার জন্য ট্রানজিশন HAL (আপস্ট্রিম HAL, HIDL ব্যবহার করলে HIDL ব্যবহার করতে হবে)।

ফ্রেমওয়ার্ক কম্পোনেন্ট, যেমন system.img-এ থাকা কম্পোনেন্ট এবং হার্ডওয়্যার কম্পোনেন্ট, যেমন vendor.img-এ থাকা কম্পোনেন্টের মধ্যে যোগাযোগ করার জন্য AIDL ব্যবহার করা HAL-কে অবশ্যই স্টেবল AIDL ব্যবহার করতে হবে। তবে, একটি পার্টিশনের মধ্যে যোগাযোগ করার জন্য, যেমন, একটি HAL থেকে অন্যটিতে, ব্যবহার করার জন্য IPC মেকানিজমের উপর কোনও বিধিনিষেধ নেই।

অনুপ্রেরণা

HIDL-এর চেয়ে AIDL অনেক বেশি সময় ধরে ব্যবহার করা হচ্ছে এবং Android ফ্রেমওয়ার্ক কম্পোনেন্ট বা অ্যাপের মতো আরও অনেক জায়গায় এটি ব্যবহার করা হয়। AIDL-এ এখন স্থিতিশীল সাপোর্ট আছে, তাই একটি IPC রানটাইম সহ সম্পূর্ণ স্ট্যাক প্রয়োগ করা সম্ভব। এছাড়াও, AIDL-এর HIDL-এর থেকে আরও ভালো ভার্সনিং সিস্টেম আছে। AIDL-এর কিছু সুবিধা এখানে দেওয়া হল:

  • সিঙ্গেল IPC ভাষা ব্যবহার করার অর্থ হল, শেখা, ডিবাগ করা, অপ্টিমাইজ করা এবং সুরক্ষিত করার জন্য শুধুমাত্র একটি জিনিস আছে।
  • AIDL ইন্টারফেসের মালিকদের জন্য ইন-প্লেস ভার্সনিং সাপোর্ট করে:
    • মালিকরা ইন্টারফেসের শেষে পদ্ধতি যোগ করতে বা পার্সেলযোগ্য আইটেমে ফিল্ড যোগ করতে পারেন। এর অর্থ হল, বছরের পর বছর ধরে কোডের ভার্সন তৈরি করা সহজ এবং বছর পিছু খরচও কম (টাইপগুলি একই জায়গায় সংশোধন করা যেতে পারে এবং প্রতিটি ইন্টারফেস ভার্সনের জন্য অতিরিক্ত লাইব্রেরির প্রয়োজন নেই)।
    • টাইপ সিস্টেমের পরিবর্তে রান টাইমে এক্সটেনশন ইন্টারফেস অ্যাটাচ করা যেতে পারে, তাই ইন্টারফেসের নতুন ভার্সনে ডাউনস্ট্রিম এক্সটেনশন রিবেস করার প্রয়োজন নেই।
  • কোনও বিদ্যমান AIDL ইন্টারফেসের মালিক যদি এটিকে স্থিতিশীল করার সিদ্ধান্ত নেন, তাহলে এটি সরাসরি ব্যবহার করা যেতে পারে। আগে, ইন্টারফেসের একটি সম্পূর্ণ কপি HIDL-এ তৈরি করতে হতো।

AIDL রানটাইমের বিরুদ্ধে বিল্ড করা

AIDL-এর তিনটি আলাদা ব্যাকএন্ড আছে: Java, NDK এবং CPP। স্থিতিশীল AIDL ব্যবহার করতে, system/lib*/libbinder.so-এ সবসময় libbinder-এর সিস্টেম কপি ব্যবহার করুন এবং /dev/binder-এ কথা বলুন। vendor ছবিতে দেখানো কোডের জন্য, এর অর্থ হল যে libbinder (VNDK থেকে) ব্যবহার করা যাবে না: এই লাইব্রেরিতে অস্থির C++ API এবং অস্থির ইন্টার্নাল আছে। পরিবর্তে, নেটিভ ভেন্ডর কোডকে অবশ্যই AIDL-এর NDK ব্যাকএন্ড ব্যবহার করতে হবে, libbinder_ndk-এর (যা সিস্টেম libbinder.so দ্বারা ব্যাক করা হয়) বিরুদ্ধে লিঙ্ক করতে হবে এবং aidl_interface এন্ট্রি দ্বারা তৈরি NDK লাইব্রেরির বিরুদ্ধে লিঙ্ক করতে হবে। মডিউলের সঠিক নাম জানতে, মডিউলের নাম সংক্রান্ত নিয়ম দেখুন।

একটি AIDL HAL ইন্টারফেস লিখুন

সিস্টেম ও ভেন্ডরের মধ্যে AIDL ইন্টারফেস ব্যবহার করতে হলে, ইন্টারফেসে দুটি পরিবর্তন করতে হবে:

  • প্রতিটি টাইপ ডেফিনিশনকে @VintfStability দিয়ে অ্যানোটেট করতে হবে।
  • aidl_interface ঘোষণায় stability: "vintf", অন্তর্ভুক্ত করতে হবে।

শুধুমাত্র ইন্টারফেসের মালিক এইসব পরিবর্তন করতে পারবেন।

আপনি এইসব পরিবর্তন করলে, কাজ করার জন্য ইন্টারফেসকে অবশ্যই VINTF ম্যানিফেস্টে থাকতে হবে। ভেন্ডর টেস্ট স্যুট (VTS) টেস্ট vts_treble_vintf_vendor_test ব্যবহার করে এটি (এবং সম্পর্কিত প্রয়োজনীয়তা, যেমন রিলিজ করা ইন্টারফেস ফ্রিজ করা হয়েছে কিনা তা যাচাই করা) পরীক্ষা করুন। আপনি এইসব প্রয়োজনীয়তা ছাড়াই @VintfStability ইন্টারফেস ব্যবহার করতে পারবেন, এর জন্য আপনাকে NDK ব্যাকএন্ডে AIBinder_forceDowngradeToLocalStability, C++ ব্যাকএন্ডে android::Stability::forceDowngradeToLocalStability, অথবা Java ব্যাকএন্ডে android.os.Binder#forceDowngradeToSystemStability কল করতে হবে, তবে এটি অন্য প্রসেসে পাঠানোর আগে বাইন্ডার অবজেক্টে করতে হবে।

এছাড়াও, সর্বাধিক কোড পোর্টেবিলিটির জন্য এবং অপ্রয়োজনীয় অতিরিক্ত লাইব্রেরির মতো সম্ভাব্য সমস্যা এড়াতে, CPP ব্যাকএন্ড বন্ধ করুন।

CPP ব্যাকএন্ড কীভাবে বন্ধ করতে হয় তা কোডে দেখানো হয়েছে:

    aidl_interface: {
        ...
        backend: {
            cpp: {
                enabled: false,
            },
        },
    }

AIDL HAL ইন্টারফেস খোঁজা

HALS-এর জন্য AOSP স্টেবল AIDL ইন্টারফেস, HIDL ইন্টারফেসের মতো একই বেস ডিরেক্টরির aidl ফোল্ডারের মধ্যে থাকে:

  • hardware/interfaces হল সেইসব ইন্টারফেসের জন্য যা সাধারণত হার্ডওয়্যার প্রদান করে।
  • frameworks/hardware/interfaces হল হার্ডওয়্যারের জন্য প্রদান করা উচ্চ-স্তরের ইন্টারফেস।
  • system/hardware/interfaces হল হার্ডওয়্যারের জন্য প্রদান করা লো-লেভেল ইন্টারফেস।

vendor বা hardware-এর মধ্যে এক্সটেনশন ইন্টারফেসকে অন্যান্য hardware/interfaces সাবডিরেক্টরিতে রাখুন।

এক্সটেনশন ইন্টারফেস

প্রতিটি রিলিজের সাথে Android-এর কাছে অফিসিয়াল AOSP ইন্টারফেসের একটি সেট থাকে। Android পার্টনাররা এইসব ইন্টারফেসে ক্ষমতা যোগ করতে চাইলে, তাদের সরাসরি এগুলি পরিবর্তন করা উচিত নয় কারণ এটি তাদের Android রানটাইমকে AOSP Android রানটাইমের সাথে মানানসই করে তোলে। এইসব ইন্টারফেস পরিবর্তন করা এড়িয়ে চলুন যাতে GSI ইমেজ কাজ করা চালিয়ে যেতে পারে।

দুটি আলাদা আলাদা উপায়ে এক্সটেনশন রেজিস্টার করা যায়:

তবে, একটি এক্সটেনশন রেজিস্টার করা হয়, যখন ভেন্ডর-নির্দিষ্ট (অর্থাৎ আপস্ট্রিম AOSP-এর অংশ নয়) কম্পোনেন্ট ইন্টারফেস ব্যবহার করে, মার্জ কনফ্লিক্ট সম্ভব নয় তবে, আপস্ট্রিম AOSP কম্পোনেন্টে ডাউনস্ট্রিম পরিবর্তন করা হলে, মার্জ কনফ্লিক্ট হতে পারে এবং নিম্নলিখিত স্ট্র্যাটেজিগুলি সাজেস্ট করা হয়:

  • পরবর্তী রিলিজে AOSP-তে ইন্টারফেস আপস্ট্রিম করুন।
  • আপস্ট্রিম ইন্টারফেসে এমন কিছু যোগ করা হয়েছে যা পরবর্তী রিলিজের ক্ষেত্রে আরও বেশি নমনীয়তা প্রদান করে (মার্জ সংঘাত ছাড়াই)।

এক্সটেনশন পার্সেল করা যায়: ParcelableHolder

ParcelableHolder হল Parcelable ইন্টারফেসের একটি ইনস্ট্যান্স যা Parcelable-এর অন্য একটি ইনস্ট্যান্স কন্টেন করতে পারে।

ParcelableHolder-এর মূল ব্যবহার হল Parcelable-কে আরও প্রসারিত করা। যেমন, ডিভাইস ইমপ্লিমেন্টাররা আশা করেন যে তারা AOSP-এর সংজ্ঞায়িত Parcelable, AospDefinedParcelable-কে এক্সটেন্ড করতে পারবেন, যাতে তাদের ভ্যালু-অ্যাড ফিচার অন্তর্ভুক্ত করা যায়।

আপনার ভ্যালু-অ্যাড ফিচার সহ Parcelable এক্সটেন্ড করতে ParcelableHolder ইন্টারফেস ব্যবহার করুন। ParcelableHolder ইন্টারফেসে Parcelable-এর একটি ইনস্ট্যান্স রয়েছে। আপনি যদি Parcelable-এ সরাসরি ফিল্ড যোগ করার চেষ্টা করেন, তাহলে সেটি একটি সমস্যার কারণ হয়:

parcelable AospDefinedParcelable {
  int a;
  String b;
  String x; // ERROR: added by a device implementer
  int[] y; // added by a device implementer
}

আগের কোডে যেমন দেখা গেছে, এই প্র্যাক্টিসটি ভেঙে গেছে কারণ ডিভাইস ইমপ্লিমেন্টারদের যোগ করা ফিল্ড Android-এর পরবর্তী রিলিজগুলিতে Parcelable পরিবর্তন করা হলে সেগুলি কনফ্লিক্ট করতে পারে।

ParcelableHolder ব্যবহার করে, পার্সেল করা যায় এমন আইটেমের মালিক Parcelable-এর কোনও ইনস্ট্যান্সে এক্সটেনশন পয়েন্ট নির্ধারণ করতে পারেন:

parcelable AospDefinedParcelable {
  int a;
  String b;
  ParcelableHolder extension;
}

তারপরে, ডিভাইস ইমপ্লিমেন্টাররা তাদের এক্সটেনশনের জন্য নিজস্ব Parcelable ইনস্ট্যান্স ডিফাইন করতে পারবেন:

parcelable OemDefinedParcelable {
  String x;
  int[] y;
}

নতুন Parcelable ইনস্ট্যান্সটি ParcelableHolder ফিল্ডের মাধ্যমে আসল Parcelable-এর সাথে অ্যাটাচ করা যেতে পারে:


// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;

ap.extension.setParcelable(op);

...

OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);

// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();

ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);

...

std::shared_ptr<OemDefinedParcelable> op_ptr;

ap.extension.getParcelable(&op_ptr);

// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);

...

std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);

// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });

ap.extension.set_parcelable(Rc::clone(&op));

...

let op = ap.extension.get_parcelable::<OemDefinedParcelable>();

AIDL HAL সার্ভার ইনস্ট্যান্সের নাম

প্রচলিত নিয়ম অনুযায়ী, AIDL HAL পরিষেবার ইনস্ট্যান্সের নাম $package.$type/$instance ফর্ম্যাটে থাকে। যেমন, ভাইব্রেটর HAL-এর একটি ইনস্ট্যান্স android.hardware.vibrator.IVibrator/default হিসেবে রেজিস্টার করা হয়।

AIDL HAL সার্ভার লেখা

@VintfStability AIDL সার্ভারকে অবশ্যই VINTF ম্যানিফেস্টে ঘোষণা করতে হবে, যেমন:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>

অন্যথায়, তাদের স্বাভাবিকভাবে AIDL পরিষেবা রেজিস্টার করতে হবে। VTS টেস্ট চালানোর সময়, এটি আশা করা হয় যে ঘোষণা করা সব AIDL HAL উপলভ্য।

AIDL ক্লায়েন্ট লেখা

AIDL ক্লায়েন্টদের অবশ্যই কম্প্যাটিবিলিটি ম্যাট্রিক্সে নিজেদের ঘোষণা করতে হবে, যেমন:

    <hal format="aidl" optional="true">
        <name>android.hardware.vibrator</name>
        <version>1-2</version>
        <interface>
            <name>IVibrator</name>
            <instance>default</instance>
        </interface>
    </hal>

আগে থেকে থাকা HAL-কে HIDL থেকে AIDL-এ কনভার্ট করা

HIDL ইন্টারফেসকে AIDL-এ কনভার্ট করতে hidl2aidl টুল ব্যবহার করুন।

hidl2aidl ফিচার:

  • প্রদত্ত প্যাকেজের জন্য HAL (.hal) ফাইলের উপর ভিত্তি করে AIDL (.aidl) ফাইল তৈরি করুন।
  • নতুন তৈরি AIDL প্যাকেজের জন্য সব ব্যাকএন্ড চালু করে বিল্ড নিয়ম তৈরি করুন।
  • HIDL থেকে AIDL-এ অনুবাদ করার জন্য Java, CPP এবং NDK ব্যাকএন্ডে অনুবাদ পদ্ধতি তৈরি করুন।
  • প্রয়োজনীয় ডিপেন্ডেন্সি সহ ট্রান্সলেট লাইব্রেরির জন্য বিল্ড নিয়ম তৈরি করুন।
  • HIDL এবং AIDL এনুমেরেটরদের CPP এবং NDK ব্যাকএন্ডে একই ভ্যালু আছে কিনা তা নিশ্চিত করতে স্ট্যাটিক অ্যাসার্ট তৈরি করুন।

HAL ফাইলের প্যাকেজকে AIDL ফাইলে কনভার্ট করতে এইসব ধাপ অনুসরণ করুন:

  1. system/tools/hidl/hidl2aidl-এ থাকা টুল তৈরি করুন।

    লেটেস্ট সোর্স থেকে এই টুল তৈরি করলে সবচেয়ে সম্পূর্ণ অভিজ্ঞতা পাওয়া যায়। আপনি আগের রিলিজ থেকে পুরনো ব্রাঞ্চে ইন্টারফেস কনভার্ট করতে লেটেস্ট ভার্সন ব্যবহার করতে পারেন:

    m hidl2aidl
  2. যে প্যাকেজটি কনভার্ট করতে হবে সেটি সহ আউটপুট ডিরেক্টরি দিয়ে টুলটি এক্সিকিউট করুন।

    বিকল্প হিসেবে, তৈরি করা সব ফাইলের উপরে নতুন লাইসেন্স ফাইলের কন্টেন্ট যোগ করতে -l আর্গুমেন্ট ব্যবহার করুন। সঠিক লাইসেন্স ও তারিখ ব্যবহার করতে ভুলবেন না:

    hidl2aidl -o <output directory> -l <file with license> <package>

    যেমন:

    hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
  3. জেনারেট করা ফাইলগুলি পড়ে দেখুন এবং কনভার্সন সংক্রান্ত কোনও সমস্যা থাকলে তা সমাধান করুন:

    • conversion.log-এ সমাধান না করা কোনও সমস্যা থাকলে, প্রথমে সেটি সমাধান করতে হবে।
    • জেনারেট করা AIDL ফাইলে সতর্কতা ও সাজেশন থাকতে পারে যেগুলির উপর অ্যাকশন নিতে হবে। এইসব কমেন্ট // দিয়ে শুরু হয়।
    • প্যাকেজ পরিষ্কার করুন এবং উন্নতি করুন।
    • @JavaDerive toString বা equals-এর মতো প্রয়োজনীয় ফিচারের জন্য অ্যানোটেশন চেক করুন।
  4. আপনার প্রয়োজনীয় টার্গেটগুলিই শুধু তৈরি করুন:

    • ব্যবহার করা হবে না এমন ব্যাকএন্ড বন্ধ করুন। CPP ব্যাকএন্ডের পরিবর্তে NDK ব্যাকএন্ড ব্যবহার করুন; AIDL রানটাইমের বিরুদ্ধে বিল্ড করুন দেখুন।
    • অনুবাদ লাইব্রেরি বা এর তৈরি করা যেকোনও কোড সরিয়ে দিন যা ব্যবহার করা হবে না।
  5. AIDL ও HIDL-এর মধ্যে প্রধান পার্থক্য দেখুন:

    • AIDL-এর বিল্ট-ইন Status ও ব্যতিক্রম ব্যবহার করলে সাধারণত ইন্টারফেসের উন্নতি হয় এবং ইন্টারফেস-নির্দিষ্ট স্ট্যাটাস ধরনের প্রয়োজন হয় না।
    • HIDL-এর মতো AIDL ইন্টারফেস আর্গুমেন্টগুলি ডিফল্ট হিসেবে @nullable হয় না।

AIDL HAL-এর জন্য SEPolicy

ভেন্ডর কোডে দৃশ্যমান AIDL পরিষেবার ধরনটিতে অবশ্যই hal_service_type অ্যাট্রিবিউট থাকতে হবে। অন্যথায়, sepolicy কনফিগারেশন অন্য যেকোনও AIDL পরিষেবার মতোই হবে (যদিও HAL-এর জন্য বিশেষ অ্যাট্রিবিউট আছে)। HAL পরিষেবা কন্টেক্সটের একটি উদাহরণ এখানে দেওয়া হল:

    type hal_foo_service, service_manager_type, hal_service_type;

প্ল্যাটফর্মের মাধ্যমে সংজ্ঞায়িত বেশিরভাগ পরিষেবার জন্য, সঠিক ধরনের পরিষেবা প্রসঙ্গ ইতিমধ্যেই যোগ করা হয়েছে (যেমন, android.hardware.foo.IFoo/default-কে ইতিমধ্যেই hal_foo_service হিসেবে চিহ্নিত করা হয়েছে)। তবে, কোনও ফ্রেমওয়ার্ক ক্লায়েন্ট একাধিক ইনস্ট্যান্স নাম সাপোর্ট করলে, ডিভাইস-নির্দিষ্ট service_contexts ফাইলে অতিরিক্ত ইনস্ট্যান্স নাম যোগ করতে হবে:

    android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0

আপনি নতুন ধরনের HAL তৈরি করলে, আপনাকে অবশ্যই HAL অ্যাট্রিবিউট যোগ করতে হবে। একটি নির্দিষ্ট HAL অ্যাট্রিবিউট একাধিক পরিষেবার ধরনের সাথে যুক্ত থাকতে পারে (যার প্রত্যেকটিতে একাধিক ইনস্ট্যান্স থাকতে পারে, যেমনটি এইমাত্র আলোচনা করা হয়েছে)। HAL, foo-এর জন্য, hal_attribute(foo) আছে। এই ম্যাক্রো hal_foo_client এবং hal_foo_server অ্যাট্রিবিউটকে সংজ্ঞায়িত করে। কোনও ডোমেনের জন্য, hal_client_domain এবং hal_server_domain ম্যাক্রো কোনও ডোমেনকে প্রদত্ত HAL অ্যাট্রিবিউটের সাথে যুক্ত করে। যেমন, সিস্টেম সার্ভার এই HAL-এর ক্লায়েন্ট হওয়ার ফলে নীতি hal_client_domain(system_server, hal_foo) মেনে চলে। একইভাবে, HAL সার্ভারে hal_server_domain(my_hal_domain, hal_foo) থাকে।

সাধারণত, প্রদত্ত HAL অ্যাট্রিবিউটের জন্য, রেফারেন্স বা উদাহরণ HAL-এর মতো hal_foo_default ডোমেনও তৈরি করুন। তবে, কিছু ডিভাইস তাদের নিজস্ব সার্ভারের জন্য এইসব ডোমেন ব্যবহার করে। একাধিক সার্ভারের জন্য ডোমেনগুলির মধ্যে পার্থক্য করা শুধুমাত্র তখনই গুরুত্বপূর্ণ যদি একাধিক সার্ভার থাকে যেগুলি একই ইন্টারফেস পরিবেশন করে এবং তাদের প্রয়োগে আলাদা আলাদা অনুমতির সেট প্রয়োজন হয়। এইসব ম্যাক্রোর মধ্যে, hal_foo কোনও sepolicy অবজেক্ট নয়। এর পরিবর্তে, এই টোকেনটি ক্লায়েন্ট সার্ভার পেয়ারের সাথে যুক্ত অ্যাট্রিবিউটগুলির গ্রুপকে রেফার করার জন্য এই ম্যাক্রো ব্যবহার করে।

তবে, এখনও পর্যন্ত, hal_foo_service এবং hal_foo (hal_attribute(foo) থেকে অ্যাট্রিবিউট পেয়ার) সংশ্লিষ্ট নয়। hal_attribute_service ম্যাক্রো (HIDL HAL-এ hal_attribute_hwservice ম্যাক্রো ব্যবহার করা হয়) ব্যবহার করে AIDL HAL পরিষেবার সাথে HAL অ্যাট্রিবিউট যুক্ত করা হয়, যেমন, hal_attribute_service(hal_foo, hal_foo_service)। এর অর্থ হল, hal_foo_clientটি প্রসেস HAL-এর অ্যাক্সেস পেতে পারে এবং hal_foo_serverটি প্রসেস HAL রেজিস্টার করতে পারে। এইসব রেজিস্ট্রেশন সংক্রান্ত নিয়ম কনটেক্সট ম্যানেজার (servicemanager) এনফোর্স করে।

পরিষেবার নাম সবসময় HAL অ্যাট্রিবিউটের সাথে নাও মিলতে পারে, যেমন, hal_attribute_service(hal_foo, hal_foo2_service)। সাধারণত, যেহেতু এর অর্থ হল পরিষেবাগুলি সবসময় একসাথে ব্যবহার করা হয়, তাই আপনি hal_foo2_service সরিয়ে দিতে পারেন এবং সব পরিষেবা কনটেক্সটের জন্য hal_foo_service ব্যবহার করতে পারেন। HAL একাধিক hal_attribute_service ইনস্ট্যান্স সেট করলে, এর কারণ হল মূল HAL অ্যাট্রিবিউট নাম যথেষ্ট সাধারণ নয় এবং এটি পরিবর্তন করা যায় না।

এইসব একসাথে রাখলে, HAL-এর একটি উদাহরণ এইরকম দেখতে লাগে:

    public/attributes:
    // define hal_foo, hal_foo_client, hal_foo_server
    hal_attribute(foo)

    public/service.te
    // define hal_foo_service
    type hal_foo_service, hal_service_type, protected_service, service_manager_type

    public/hal_foo.te:
    // allow binder connection from client to server
    binder_call(hal_foo_client, hal_foo_server)
    // allow client to find the service, allow server to register the service
    hal_attribute_service(hal_foo, hal_foo_service)
    // allow binder communication from server to service_manager
    binder_use(hal_foo_server)

    private/service_contexts:
    // bind an AIDL service name to the selinux type
    android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0

    private/<some_domain>.te:
    // let this domain use the hal service
    binder_use(some_domain)
    hal_client_domain(some_domain, hal_foo)

    vendor/<some_hal_server_domain>.te
    // let this domain serve the hal service
    hal_server_domain(some_hal_server_domain, hal_foo)

অ্যাটাচ করা এক্সটেনশন ইন্টারফেস

একটি এক্সটেনশন যেকোনও বাইন্ডার ইন্টারফেসে যোগ করা যেতে পারে, সেটি সরাসরি পরিষেবা ম্যানেজারের সাথে রেজিস্টার করা উচ্চ স্তরের ইন্টারফেস হোক বা সাব-ইন্টারফেস হোক৷ এক্সটেনশন পাওয়ার সময়, আপনাকে অবশ্যই কনফার্ম করতে হবে যে এক্সটেনশনের ধরনটি প্রত্যাশিত মতোই আছে। আপনি শুধুমাত্র বাইন্ডার পরিবেশনকারী প্রসেস থেকে এক্সটেনশন সেট করতে পারবেন।

আগে থেকে থাকা HAL-এর কার্যকারিতা কোনও এক্সটেনশন পরিবর্তন করলে, অ্যাটাচ করা এক্সটেনশন ব্যবহার করুন। সম্পূর্ণ নতুন ক্ষমতার প্রয়োজন হলে, এই মেকানিজম প্রয়োজন হয় না এবং আপনি সরাসরি পরিষেবা ম্যানেজারের সাথে একটি এক্সটেনশন ইন্টারফেস রেজিস্টার করতে পারেন। অ্যাটাচ করা এক্সটেনশন ইন্টারফেস তখনই সবচেয়ে বেশি কাজে লাগে যখন সেগুলি সাব-ইন্টারফেসের সাথে অ্যাটাচ করা হয়, কারণ এই হায়ারার্কিগুলি অনেক গভীর বা মাল্টি-ইনস্ট্যান্স হতে পারে। অন্য পরিষেবার বাইন্ডার ইন্টারফেসের অনুক্রম মিরর করার জন্য গ্লোবাল এক্সটেনশন ব্যবহার করতে হলে, সরাসরি অ্যাটাচ করা এক্সটেনশনের মতো একই ধরনের ক্ষমতা প্রদান করার জন্য ব্যাপক বুককিপিংয়ের প্রয়োজন হয়।

বাইন্ডারে এক্সটেনশন সেট করতে, নিম্নলিখিত API ব্যবহার করুন:

  • NDK ব্যাকএন্ড: AIBinder_setExtension
  • Java ব্যাকএন্ড: android.os.Binder.setExtension
  • CPP ব্যাকএন্ড: android::Binder::setExtension
  • Rust ব্যাকএন্ড: binder::Binder::set_extension

বাইন্ডারে এক্সটেনশন পেতে, নিম্নলিখিত API ব্যবহার করুন:

  • NDK ব্যাক-এন্ড: AIBinder_getExtension
  • Java ব্যাকএন্ড: android.os.IBinder.getExtension
  • CPP ব্যাকএন্ড: android::IBinder::getExtension
  • Rust ব্যাকএন্ড: binder::Binder::get_extension

আপনি সংশ্লিষ্ট ব্যাকএন্ডে getExtension ফাংশনের ডকুমেন্টেশনে এইসব API সম্পর্কে আরও তথ্য পাবেন। এক্সটেনশন কীভাবে ব্যবহার করতে হয় তার একটি উদাহরণ hardware/interfaces/tests/extension/vibrator-এ দেওয়া আছে।

AIDL ও HIDL-এর মধ্যে প্রধান পার্থক্য

AIDL HAL বা AIDL HAL ইন্টারফেস ব্যবহার করার সময়, HIDL HAL লেখার সাথে পার্থক্য সম্পর্কে সচেতন থাকুন।

  • AIDL ভাষার সিনট্যাক্স জাভার কাছাকাছি। HIDL সিনট্যাক্স C++-এর মতো।
  • সব AIDL ইন্টারফেসে বিল্ট-ইন সমস্যার স্ট্যাটাস থাকে। কাস্টম স্ট্যাটাস টাইপ তৈরি করার পরিবর্তে, ইন্টারফেস ফাইলে কনস্ট্যান্ট স্ট্যাটাস ইন্টিজার তৈরি করুন এবং CPP ও NDK ব্যাকএন্ডে EX_SERVICE_SPECIFIC এবং Java ব্যাকএন্ডে ServiceSpecificException ব্যবহার করুন। Error হ্যান্ডেলিং দেখুন।
  • বাইন্ডার অবজেক্ট পাঠানো হলে AIDL অটোমেটিক থ্রেড পুল শুরু করে না। আপনাকে সেগুলি ম্যানুয়ালি শুরু করতে হবে (থ্রেড ম্যানেজমেন্ট দেখুন)।
  • AIDL, আনচেক করা ট্রান্সপোর্ট সংক্রান্ত সমস্যার (HIDL Return আনচেক করা সমস্যার ক্ষেত্রে অ্যাবরট করে) ক্ষেত্রে অ্যাবরট করে না।
  • AIDL-এ প্রতি ফাইলে শুধুমাত্র এক ধরনের ডেটা ঘোষণা করা যায়।
  • আউটপুট প্যারামিটার ছাড়াও AIDL আর্গুমেন্টকে in, out বা inout হিসেবে নির্দিষ্ট করা যেতে পারে (কোনও সিঙ্ক্রোনাস কলব্যাক নেই)।
  • AIDL, handle-এর পরিবর্তে fd-কে আদিম টাইপ হিসেবে ব্যবহার করে।
  • HIDL, মানানসই নয় এমন পরিবর্তনের জন্য মেজর ভার্সন এবং মানানসই পরিবর্তনের জন্য মাইনর ভার্সন ব্যবহার করে। AIDL-এ, ব্যাকওয়ার্ড-কম্প্যাটিবল পরিবর্তনগুলি যথাযথভাবে করা হয়। AIDL-এ মেজর ভার্সনের কোনও স্পষ্ট ধারণা নেই; এর পরিবর্তে, এটি প্যাকেজের নামের মধ্যে অন্তর্ভুক্ত করা হয়। যেমন, AIDL প্যাকেজের নাম bluetooth2 ব্যবহার করতে পারে।
  • AIDL সাধারণত রিয়েলটাইম অগ্রাধিকার ইনহেরিট করে না। রিয়েলটাইম অগ্রাধিকার ইনহেরিটেন্স চালু করতে, প্রতিটি বাইন্ডারের জন্য setInheritRt ফাংশন ব্যবহার করতে হবে।

HAL-এর জন্য পরীক্ষা

এই বিভাগে HAL পরীক্ষা করার পেশাদার পদ্ধতি বর্ণনা করা হয়েছে। আপনার HAL-এর ইন্টিগ্রেশন টেস্ট VTS-এ না থাকলেও এইসব পদ্ধতি বৈধ।

প্রত্যাশিত HAL প্রয়োগ যাচাই করার জন্য Android, VTS-এর উপর নির্ভর করে। VTS নিশ্চিত করতে সাহায্য করে যে Android পুরনো ভেন্ডর ইমপ্লিমেন্টেশনের সাথে ব্যাকওয়ার্ড কম্প্যাটিবল হতে পারে। VTS-এ ব্যর্থ হওয়া ইমপ্লিমেন্টেশনে মানানসই হওয়া সংক্রান্ত পরিচিত সমস্যা থাকে যা OS-এর ভবিষ্যতের ভার্সনে কাজ করতে বাধা দিতে পারে।

HAL-এর জন্য VTS-এর দুটি প্রধান অংশ রয়েছে।

১. ডিভাইসে থাকা HAL Android-এর পরিচিত ও প্রত্যাশিত কিনা তা যাচাই করা

Android, ইনস্টল করা সব HAL-এর স্ট্যাটিক, সঠিক তালিকার উপর নির্ভর করে। এই তালিকা VINTF ম্যানিফেস্টে প্রকাশ করা হয়েছে। বিশেষ, প্ল্যাটফর্ম-ব্যাপী পরীক্ষা সম্পূর্ণ সিস্টেমের HAL লেয়ারের ইন্টিগ্রিটি একসাথে যাচাই করে। HAL-নির্দিষ্ট কোনও পরীক্ষা লেখার আগে, আপনাকে এই পরীক্ষাগুলিও চালাতে হবে, কারণ সেগুলি বলতে পারে যে কোনও HAL-এর অসামঞ্জস্যপূর্ণ VINTF কনফিগারেশন আছে কিনা।

এই টেস্টের সেট test/vts-testcase/hal/treble/vintf-এ পাওয়া যাবে। আপনি যদি কোনও ভেন্ডর HAL ইমপ্লিমেন্টেশনে কাজ করেন, তাহলে এটি যাচাই করতে vts_treble_vintf_vendor_test ব্যবহার করুন। আপনি atest vts_treble_vintf_vendor_test কমান্ডের মাধ্যমে এই টেস্ট রান করতে পারবেন।

এইসব পরীক্ষা নিম্নলিখিত বিষয়গুলি যাচাই করার জন্য দায়ী:

  • VINTF ম্যানিফেস্টে ঘোষিত প্রতিটি @VintfStability ইন্টারফেস একটি পরিচিত রিলিজ করা ভার্সনে ফ্রিজ করা হয়। এটি ইন্টারফেসের উভয় দিকই ইন্টারফেসের সেই ভার্সনের সঠিক সংজ্ঞার সাথে একমত কিনা তা যাচাই করে। সাধারণ অপারেশনের জন্য এটি প্রয়োজন।
  • VINTF ম্যানিফেস্টে ঘোষণা করা সব HAL সেই ডিভাইসে উপলভ্য থাকে। ঘোষিত HAL পরিষেবা ব্যবহার করার জন্য পর্যাপ্ত অনুমতি আছে এমন যেকোনও ক্লায়েন্টকে যেকোনও সময় সেইসব পরিষেবা পেতে এবং ব্যবহার করতে পারতে হবে।
  • VINTF ম্যানিফেস্টে ঘোষণা করা সব HAL, ম্যানিফেস্টে ঘোষণা করা ইন্টারফেসের ভার্সন পরিবেশন করছে।
  • ডিভাইসে কোনও অবচিত HAL পরিবেশন করা হচ্ছে না। Android, HAL ইন্টারফেসের আগের ভার্সনের জন্য সাপোর্ট বন্ধ করে দেয়, এটি FCM লাইফসাইকেলে বর্ণনা করা হয়েছে।
  • ডিভাইসে প্রয়োজনীয় HAL আছে। Android-এর সঠিকভাবে কাজ করার জন্য কিছু HAL প্রয়োজন।

২. প্রতিটি HAL-এর প্রত্যাশিত আচরণ যাচাই করুন

প্রতিটি HAL ইন্টারফেসের নিজস্ব VTS টেস্ট আছে যা ক্লায়েন্টের থেকে প্রত্যাশিত আচরণ যাচাই করে। ঘোষিত HAL ইন্টারফেসের প্রতিটি ইনস্ট্যান্সের বিরুদ্ধে টেস্ট কেস চালানো হয় এবং প্রয়োগ করা ইন্টারফেসের ভার্সনের উপর ভিত্তি করে নির্দিষ্ট আচরণ প্রয়োগ করা হয়।

C++-এ, আপনি সিস্টেমে ইনস্টল করা প্রতিটি HAL-এর তালিকা পেতে পারেন libaidlvintf_gtest_helper-এ android::getAidlHalInstanceNames ফাংশন সহ। Rust-এ binder::get_declared_instances ব্যবহার করুন।

এইসব টেস্ট HAL প্রয়োগের প্রতিটি দিক কভার করার চেষ্টা করে যার উপর Android ফ্রেমওয়ার্ক নির্ভর করে বা ভবিষ্যতে করতে পারে।

এইসব পরীক্ষার মধ্যে ফিচার সাপোর্ট, সমস্যার সমাধান এবং পরিষেবা থেকে ক্লায়েন্ট যা আশা করতে পারে এমন যেকোনও আচরণ যাচাই করা অন্তর্ভুক্ত।

HAL ডেভেলপমেন্টের জন্য VTS মাইলস্টোন

Android-এর HAL ইন্টারফেস তৈরি বা পরিবর্তন করার সময় VTS টেস্ট (বা যেকোনও টেস্ট) আপ-টু-ডেট রাখতে হবে।

Android Vendor API রিলিজের জন্য ফ্রোজেন করার আগে VTS টেস্ট সম্পূর্ণ করতে হবে এবং ভেন্ডর ইমপ্লিমেন্টেশন যাচাই করার জন্য রেডি থাকতে হবে । ইন্টারফেস ফ্রিজ করার আগে সেগুলি রেডি থাকতে হবে যাতে ডেভেলপাররা তাদের ইমপ্লিমেন্টেশন তৈরি করতে, যাচাই করতে এবং HAL ইন্টারফেস ডেভেলপারদের মতামত প্রদান করতে পারেন।

Cuttlefish-এ পরীক্ষা করুন

হার্ডওয়্যার উপলভ্য না থাকলে, Android, HAL ইন্টারফেসের জন্য ডেভেলপমেন্ট ভেহিকেল হিসেবে Cuttlefish ব্যবহার করে। এর ফলে Android-এর স্কেলেবল ইন্টিগ্রেশন টেস্টিং করা যায়।

hal_implementation_test পরীক্ষা, যাতে Cuttlefish-এ লেটেস্ট HAL ইন্টারফেস ভার্সনের ইমপ্লিমেন্টেশন আছে, এটি নিশ্চিত করে যে Android নতুন ইন্টারফেস হ্যান্ডেল করতে প্রস্তুত এবং নতুন হার্ডওয়্যার ও ডিভাইস উপলভ্য হওয়ার সাথে সাথেই VTS পরীক্ষা নতুন ভেন্ডর ইমপ্লিমেন্টেশন পরীক্ষা করতে প্রস্তুত।