ইন্টারফেস ও প্যাকেজ

HIDL ইন্টারফেসের চারপাশে তৈরি করা হয়েছে, এটি হল একটি অ্যাবস্ট্রাক্ট টাইপ যা অবজেক্ট-ওরিয়েন্টেড ভাষায় আচরণ নির্ধারণ করতে ব্যবহার করা হয়। প্রতিটি ইন্টারফেস একটি প্যাকেজের অংশ।

প্যাকেজ

প্যাকেজের নামে package.subpackage-এর মতো সাবলেভেল থাকতে পারে। প্রকাশিত HIDL প্যাকেজের মূল ডিরেক্টরি হল hardware/interfaces অথবা vendor/vendorName (যেমন, Pixel ডিভাইসের জন্য vendor/google)। প্যাকেজের নাম রুট ডিরেক্টরির অধীনে এক বা একাধিক সাবডিরেক্টরি তৈরি করে; প্যাকেজকে সংজ্ঞায়িত করা সব ফাইল একই ডিরেক্টরিতে থাকে। যেমন, package android.hardware.example.extension.light@2.0, hardware/interfaces/example/extension/light/2.0-এর মধ্যে পাওয়া যেতে পারে।

নিম্নলিখিত সারণীতে প্যাকেজের প্রিফিক্স ও লোকেশন তালিকাভুক্ত করা আছে:

প্যাকেজ প্রিফিক্স লোকেশন ইন্টারফেসের ধরন
android.hardware.* hardware/interfaces/* HAL
android.frameworks.* frameworks/hardware/interfaces/* ফ্রেমওয়ার্ক/ সম্পর্কিত
android.system.* system/hardware/interfaces/* সিস্টেম/ সম্পর্কিত
android.hidl.* system/libhidl/transport/* মূল

প্যাকেজ ডিরেক্টরিতে .hal এক্সটেনশন সহ ফাইল আছে। প্রতিটি ফাইলে প্যাকেজের নাম ও ফাইলের ভার্সন উল্লেখ করে package স্টেটমেন্ট থাকতে হবে। types.hal ফাইলটি থাকলে, সেটি কোনও ইন্টারফেসকে সংজ্ঞায়িত করে না, বরং প্যাকেজের প্রতিটি ইন্টারফেসের অ্যাক্সেসযোগ্য ডেটার ধরনকে সংজ্ঞায়িত করে।

ইন্টারফেসের সংজ্ঞা

types.hal ছাড়া, প্রতিটি .hal ফাইল একটি ইন্টারফেসকে সংজ্ঞায়িত করে। কোনও ইন্টারফেসকে সাধারণত নিম্নলিখিতভাবে সংজ্ঞায়িত করা হয়:

interface IBar extends IFoo { // IFoo is another interface
    // embedded types
    struct MyStruct {/*...*/};

    // interface methods
    create(int32_t id) generates (MyStruct s);
    close();
};

স্পষ্টভাবে extends ঘোষণা না করা ইন্টারফেস android.hidl.base@1.0::IBase থেকে অন্তর্নিহিতভাবে প্রসারিত হয় (জাভাতে java.lang.Object-এর মতো।) IBase ইন্টারফেস, অন্তর্নিহিতভাবে ইমপোর্ট করা, বেশ কয়েকটি সংরক্ষিত পদ্ধতি ঘোষণা করে যা ব্যবহারকারী-সংজ্ঞায়িত ইন্টারফেসে পুনরায় ঘোষণা করা উচিত নয় এবং করা যাবে না বা অন্যথায় ব্যবহার করা যাবে না। এইসব পদ্ধতি অন্তর্ভুক্ত:

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

ইমপোর্ট করার প্রসেস

import স্টেটমেন্ট হল HIDL মেকানিজম যা অন্য প্যাকেজে প্যাকেজ ইন্টারফেস ও ধরন অ্যাক্সেস করতে ব্যবহার করা হয়। import বিবৃতি দুটি এন্টিটি নিয়ে কাজ করে:

  • ইমপোর্টকারী এন্টিটি, যা কোনও প্যাকেজ বা কোনও ইন্টারফেস হতে পারে
  • ইমপোর্টকরা এন্টিটি, যা প্যাকেজ বা ইন্টারফেসের মধ্যে যেকোনও একটি হতে পারে

ইমপোর্ট করা এন্টিটি import স্টেটমেন্টের লোকেশন দ্বারা নির্ধারিত হয়। কোনও প্যাকেজের types.hal মধ্যে স্টেটমেন্ট থাকলে, যা ইমপোর্ট করা হচ্ছে তা সম্পূর্ণ প্যাকেজ দেখতে পায়; এটি হল প্যাকেজ-লেভেল ইমপোর্ট। স্টেটমেন্টটি ইন্টারফেস ফাইলের মধ্যে থাকলে, ইমপোর্ট করা এন্টিটি হল ইন্টারফেস নিজেই; এটি হল ইন্টারফেস-লেভেল ইমপোর্ট।

import কীওয়ার্ডের পরে থাকা ভ্যালু থেকে ইমপোর্ট করা এন্টিটি নির্ধারণ করা হয়। ভ্যালুটি সম্পূর্ণরূপে উপযুক্ত নাম হতে হবে না; যদি কোনও কম্পোনেন্ট বাদ দেওয়া হয়, তাহলে এটি বর্তমান প্যাকেজ থেকে তথ্য দিয়ে অটোমেটিক পূরণ করা হয়। সম্পূর্ণরূপে উপযুক্ত ভ্যালুর জন্য, নিম্নলিখিত ইমপোর্ট কেস কাজ করে:

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

ইমপোর্টকারী এন্টিটি নিম্নলিখিতগুলির একটি কম্বিনেশনে অ্যাক্সেস পায়:

  • ইমপোর্ট করা প্যাকেজের সাধারণ UDT types.hal-এ সংজ্ঞায়িত করা হয়েছে;
  • ইমপোর্ট করা প্যাকেজের ইন্টারফেস (সম্পূর্ণ প্যাকেজ ইমপোর্ট করার জন্য) অথবা নির্দিষ্ট ইন্টারফেস (আংশিক ইমপোর্ট করার জন্য) সেগুলিকে ইনভোক করা, সেগুলিতে হ্যান্ডেল পাস করা এবং/অথবা সেগুলি থেকে ইনহেরিট করার উদ্দেশ্যে।

ইমপোর্ট স্টেটমেন্ট, ইমপোর্ট করা প্যাকেজ বা ইন্টারফেসের নাম ও ভার্সন প্রদান করতে, সম্পূর্ণ কোয়ালিফায়েড-টাইপ-নেম সিনট্যাক্স ব্যবহার করে:

import android.hardware.nfc@1.0;            // import a whole package
import android.hardware.example@1.0::IQuux; // import an interface and types.hal
import android.hardware.example@1.0::types; // import just types.hal

ইন্টারফেস ইনহেরিটেন্স

ইন্টারফেস, আগে থেকে সংজ্ঞায়িত ইন্টারফেসের এক্সটেনশন হতে পারে। এক্সটেনশন নিম্নলিখিত তিন ধরনের হতে পারে:

  • ইন্টারফেস অপর একটিতে কার্যকারিতা যোগ করতে পারে, এর API অপরিবর্তিত থাকে।
  • প্যাকেজ অপর একটিতে কার্যকারিতা যোগ করতে পারে, এর API পরিবর্তিত হয় না।
  • ইন্টারফেস, প্যাকেজ বা নির্দিষ্ট ইন্টারফেস থেকে ধরন ইমপোর্ট করতে পারে।

একটি ইন্টারফেস শুধুমাত্র অন্য একটি ইন্টারফেসকে এক্সটেন্ড করতে পারে (মাল্টিপল ইনহেরিটেন্স নয়)। শূন্য নয় এমন মাইনর ভার্সন নম্বর সহ প্যাকেজের প্রতিটি ইন্টারফেসকে অবশ্যই প্যাকেজের পূর্ববর্তী ভার্সনের ইন্টারফেসকে এক্সটেন্ড করতে হবে। যেমন, যদি কোনও ইন্টারফেস IBar, প্যাকেজের derivative ভার্সন ৪.০-এ, কোনও ইন্টারফেসের উপর ভিত্তি করে (এক্সটেন্ড করে) IFoo যা প্যাকেজের original ভার্সন ১.২-এ আছে এবং প্যাকেজের original ভার্সন ১.৩ তৈরি করা হয়, তাহলে IBar ভার্সন ৪.১, IFoo-এর ভার্সন ১.৩-কে এক্সটেন্ড করতে পারবে না। পরিবর্তে, IBar ভার্সন 4.1-কে অবশ্যই IBar ভার্সন 4.0-এর এক্সটেনশন হতে হবে IFoo ভার্সন 1.2-এর সাথে এটি যুক্ত। IBar ভার্সন 5.0, IFoo ভার্সন 1.3-এর মেয়াদ বাড়াতে পারে, যদি প্রয়োজন হয়।

ইন্টারফেস এক্সটেনশন মানে এই নয় যে জেনারেট করা কোডে লাইব্রেরি নির্ভরতা বা ক্রস-HAL অন্তর্ভুক্ত করা হবে—এগুলি শুধু HIDL লেভেলে ডেটা স্ট্রাকচার ও মেথড সংজ্ঞা ইমপোর্ট করে। HAL-এর প্রতিটি পদ্ধতি সেই HAL-এ প্রয়োগ করতে হবে।

ভেন্ডর এক্সটেনশন

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

ভার্সনিং

প্যাকেজগুলি ভার্সন করা হয় এবং ইন্টারফেসের মধ্যে প্যাকেজের ভার্সন থাকে। ভার্সন দুটি পূর্ণসংখ্যায় প্রকাশ করা হয়, মেজর.মাইনর।

  • মেজর ভার্সন ব্যাকওয়ার্ড কম্প্যাটিবল নয়। মেজর ভার্সন নম্বর বৃদ্ধি করলে মাইনর ভার্সন নম্বর ০-তে রিসেট হয়ে যায়।
  • মাইনর ভার্সনগুলি আগের ভার্সনের সাথে মানানসই। মাইনর নম্বর বৃদ্ধি করা থেকে বোঝা যায় যে নতুন ভার্সনটি আগের ভার্সনের সাথে সম্পূর্ণভাবে ব্যাকওয়ার্ড-কম্প্যাটিবল। নতুন ডেটা স্ট্রাকচার ও পদ্ধতি যোগ করা যেতে পারে, কিন্তু আগে থেকে থাকা ডেটা স্ট্রাকচার বা পদ্ধতি সিগনেচার পরিবর্তন করা যাবে না।

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

ইন্টারফেস লেআউটের সারসংক্ষেপ

এই বিভাগে HIDL ইন্টারফেস প্যাকেজ (যেমন hardware/interfaces) কীভাবে ম্যানেজ করতে হয় তার সারসংক্ষেপ দেওয়া হয়েছে এবং HIDL বিভাগ জুড়ে দেখানো তথ্য একত্রিত করা হয়েছে। পড়ার আগে, নিশ্চিত করুন যে আপনি HIDL ভার্সনিং, hidl-gen-এর সাথে হ্যাশিং কনসেপ্ট, সাধারণভাবে HIDL-এর সাথে কাজ করা এবং নিম্নলিখিত সংজ্ঞা সম্পর্কে পরিচিত:

শব্দ সংজ্ঞা
অ্যাপ্লিকেশন বাইনারি ইন্টারফেস (ABI) প্রয়োজনীয় বাইনারি লিঙ্কেজ সহ অ্যাপ্লিকেশন প্রোগ্রামিং ইন্টারফেস।
সম্পূর্ণরূপে উপযুক্ত নাম (fqName) hidl-এর ধরন আলাদা করে চেনার জন্য নাম। উদাহরণ: android.hardware.foo@1.0::IFoo.
প্যাকেজ HIDL ইন্টারফেস ও ধরন সহ প্যাকেজ। উদাহরণ: android.hardware.foo@1.0.
প্যাকেজ রুট HIDL ইন্টারফেস থাকা মূল প্যাকেজ। উদাহরণ: HIDL ইন্টারফেস android.hardware প্যাকেজ রুটে android.hardware.foo@1.0 আছে।
প্যাকেজ রুট পাথ Android সোর্স ট্রি-তে সেই লোকেশন যেখানে প্যাকেজ রুট ম্যাপ করা হয়।

আরও সংজ্ঞার জন্য, HIDL পরিভাষা দেখুন।

প্রতিটি ফাইল প্যাকেজ রুট ম্যাপিং এবং এর সম্পূর্ণ কোয়ালিফায়েড নাম থেকে খুঁজে পাওয়া যাবে

hidl-gen-এর জন্য প্যাকেজ রুটকে আর্গুমেন্ট হিসেবে নির্দিষ্ট করা হয়েছে -r android.hardware:hardware/interfaces। যেমন, প্যাকেজটি vendor.awesome.foo@1.0::IFoo হলে এবং hidl-gen -r vendor.awesome:some/device/independent/path/interfaces-এ পাঠানো হলে, ইন্টারফেস ফাইলটি $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal-এ থাকতে হবে।

বাস্তবে, awesome নামের কোনও ভেন্ডর বা OEM-কে vendor.awesome-এ তাদের স্ট্যান্ডার্ড ইন্টারফেস রাখার জন্য সাজেস্ট করা হয়। প্যাকেজ পাথ বেছে নেওয়ার পরে, এটি পরিবর্তন করা যাবে না কারণ এটি ইন্টারফেসের ABI-তে বেক করা আছে।

প্যাকেজ পাথ ম্যাপিং অনন্য হতে হবে

যেমন, আপনার কাছে -rsome.package:$PATH_A এবং -rsome.package:$PATH_B থাকলে, একটি সামঞ্জস্যপূর্ণ ইন্টারফেস ডিরেক্টরির জন্য $PATH_A অবশ্যই $PATH_B-এর সমান হতে হবে (এটি ইন্টারফেসের ভার্সন তৈরি করা অনেক সহজ করে তোলে)।

প্যাকেজ রুটে ভার্সনিং ফাইল থাকতে হবে

আপনি যদি -r vendor.awesome:vendor/awesome/interfaces-এর মতো কোনও প্যাকেজ পাথ তৈরি করেন, তাহলে আপনাকে $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt ফাইলও তৈরি করতে হবে, যেটিতে hidl-gen-এ -Lhash বিকল্প ব্যবহার করে তৈরি করা ইন্টারফেসের হ্যাশ থাকতে হবে (এটি hidl-gen-এর সাথে হ্যাশিং-এ বিস্তারিতভাবে আলোচনা করা হয়েছে)।

ইন্টারফেস ডিভাইস-নিরপেক্ষ লোকেশন থেকে যায়

বাস্তবে, আমরা বিভিন্ন ব্রাঞ্চের মধ্যে ইন্টারফেস শেয়ার করার পরামর্শ দিই। এর ফলে বিভিন্ন ডিভাইস ও ব্যবহারের ক্ষেত্রে সর্বাধিক কোড আবার ব্যবহার করা যায় এবং সর্বাধিক কোড টেস্ট করা যায়।