HIDL Java

Android 8.0-এ Android OS-এর আর্কিটেকচার নতুন করে তৈরি করা হয়েছে যাতে ডিভাইস-ইন্ডিপেন্ডেন্ট Android প্ল্যাটফর্ম এবং ডিভাইস ও ভেন্ডর-নির্দিষ্ট কোডের মধ্যে স্পষ্ট ইন্টারফেস নির্ধারণ করা যায়। Android আগে থেকেই HAL ইন্টারফেসের আকারে এই ধরনের অনেক ইন্টারফেস সংজ্ঞায়িত করেছে, যা hardware/libhardware-এ C হেডার হিসেবে সংজ্ঞায়িত করা হয়েছে। HIDL এইসব HAL ইন্টারফেসকে স্থিতিশীল, ভার্সন করা ইন্টারফেস দিয়ে প্রতিস্থাপন করেছে, যা হয় Java-তে (নিচে বর্ণনা করা হয়েছে) বা ক্লায়েন্ট- এবং সার্ভার-সাইড HIDL ইন্টারফেস C++-এ হতে পারে।

HIDL ইন্টারফেস মূলত নেটিভ কোড থেকে ব্যবহার করার জন্য তৈরি করা হয়েছে এবং এর ফলে HIDL-এর মূল লক্ষ্য হল C++-এ দক্ষ কোড অটোমেটিক জেনারেট করা। তবে, HIDL ইন্টারফেস সরাসরি Java থেকেও ব্যবহার করার জন্য উপলভ্য হতে হবে, কারণ কিছু Android সাবসিস্টেমে (যেমন, টেলিফোনি) Java HIDL ইন্টারফেস থাকে।

এই বিভাগের পৃষ্ঠাগুলিতে HIDL ইন্টারফেসের জন্য Java ফ্রন্টএন্ড বর্ণনা করা হয়েছে, পরিষেবা কীভাবে তৈরি, রেজিস্টার ও ব্যবহার করতে হয় তা বিস্তারিতভাবে বলা হয়েছে এবং Java-তে লেখা HAL ও HAL ক্লায়েন্ট কীভাবে HIDL RPC সিস্টেমের সাথে ইন্টার‍্যাক্ট করে তা ব্যাখ্যা করা হয়েছে।

ক্লায়েন্টের উদাহরণ

এটি হল IFoo প্যাকেজে android.hardware.foo@1.0 ইন্টারফেসের ক্লায়েন্টের একটি উদাহরণ যা পরিষেবা নাম default হিসেবে রেজিস্টার করা হয়েছে এবং কাস্টম পরিষেবা নাম second_impl সহ একটি অতিরিক্ত পরিষেবা।

লাইব্রেরি যোগ করা

আপনি এটি ব্যবহার করতে চাইলে, আপনাকে সংশ্লিষ্ট HIDL স্টাব লাইব্রেরিতে ডিপেন্ডেন্সি যোগ করতে হবে। সাধারণত, এটি একটি স্ট্যাটিক লাইব্রেরি:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

আপনি যদি জানেন যে আপনি ইতিমধ্যেই এই লাইব্রেরিগুলির উপর নির্ভরতা টানছেন, আপনি শেয়ার করা লিঙ্কেজও ব্যবহার করতে পারেন:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Android 10-এ লাইব্রেরি যোগ করার জন্য অতিরিক্ত বিবেচ্য বিষয়

আপনার কাছে এমন কোনও সিস্টেম বা ভেন্ডর অ্যাপ থাকলে যা Android 10 বা তার পরবর্তী যেকোনও ভার্সনকে টার্গেট করে, আপনি এই লাইব্রেরিগুলি স্ট্যাটিক্যালি অন্তর্ভুক্ত করতে পারবেন। এছাড়াও, আপনি ডিভাইসে ইনস্টল করা কাস্টম JAR থেকে (শুধুমাত্র) HIDL ক্লাস ব্যবহার করতে পারেন। সিস্টেম অ্যাপের জন্য আগে থেকে থাকা uses-library মেকানিজম ব্যবহার করে স্টেবল Java API উপলভ্য করা হয়। পরের পদ্ধতিটি ডিভাইসে জায়গা বাঁচায়। আরও বিবরণের জন্য, Java SDK লাইব্রেরি প্রয়োগ করা দেখুন। পুরনো অ্যাপের ক্ষেত্রে, পুরনো আচরণ বজায় থাকে।

Android 10 থেকে শুরু করে, এইসব লাইব্রেরির "হালকা" ভার্সনও উপলভ্য। এর মধ্যে সেই ক্লাসটি অন্তর্ভুক্ত যা নিয়ে প্রশ্ন করা হয়েছে, কিন্তু কোনও নির্ভরশীল ক্লাস অন্তর্ভুক্ত নয়। যেমন, android.hardware.foo-V1.0-java-shallow-এ foo প্যাকেজের ক্লাস অন্তর্ভুক্ত থাকে, কিন্তু android.hidl.base-V1.0-java-এর ক্লাস অন্তর্ভুক্ত থাকে না, যার মধ্যে সব HIDL ইন্টারফেসের বেস ক্লাস থাকে। আপনি যদি এমন একটি লাইব্রেরি তৈরি করেন যেখানে আগে থেকেই পছন্দের ইন্টারফেসের' বেস ক্লাস উপলভ্য আছে, তাহলে আপনি নিম্নলিখিতগুলি ব্যবহার করতে পারবেন:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java-shallow", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow

এছাড়াও, HIDL বেস ও ম্যানেজার লাইব্রেরি আর বুট ক্লাসপাথে অ্যাপের জন্য উপলভ্য নেই (আগে, এগুলি কখনও কখনও লুকানো API হিসেবে ব্যবহার করা হত, কারণ Android-এর ডেলিগেট-ফার্স্ট ক্লাসলোডার)। পরিবর্তে, এগুলি jarjar সহ একটি নতুন নেমস্পেসে সরানো হয়েছে এবং যে অ্যাপগুলি এগুলি ব্যবহার করে (অবশ্যই প্রাইভেট অ্যাপ) তাদের নিজস্ব আলাদা কপি থাকতে হবে। HIDL ব্যবহার করে বুট ক্লাসপাথে থাকা মডিউলকে অবশ্যই এইসব Java লাইব্রেরির শ্যালো ভ্যারিয়েন্ট ব্যবহার করতে হবে এবং বুট ক্লাসপাথে থাকা এইসব লাইব্রেরির ভার্সন ব্যবহার করতে jarjar_rules: ":framework-jarjar-rules"-কে তাদের Android.bp-এ যোগ করতে হবে।

আপনার Java সোর্স পরিবর্তন করা

এই পরিষেবার শুধুমাত্র একটি ভার্সন (@1.0) আছে, তাই এই কোড শুধুমাত্র সেই ভার্সনটিই ফিরিয়ে আনে। পরিষেবার একাধিক আলাদা আলাদা ভার্সন কীভাবে ম্যানেজ করতে হয় তা জানতে ইন্টারফেস এক্সটেনশন দেখুন।

import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);

পরিষেবা প্রদান করা

HAL থেকে অ্যাসিঙ্ক্রোনাস কলব্যাক পাওয়ার জন্য Java-তে ফ্রেমওয়ার্ক কোডকে ইন্টারফেস পরিবেশন করতে হতে পারে।

android.hardware.foo প্যাকেজের 1.0 ভার্সনে IFooCallback ইন্টারফেসের জন্য, আপনি নিম্নলিখিত ধাপগুলি ব্যবহার করে Java-তে আপনার ইন্টারফেস প্রয়োগ করতে পারেন:

  1. HIDL-এ আপনার ইন্টারফেস নির্ধারণ করুন।
  2. /tmp/android/hardware/foo/IFooCallback.java-কে রেফারেন্স হিসেবে খুলুন।
  3. আপনার Java ইমপ্লিমেন্টেশনের জন্য একটি নতুন মডিউল তৈরি করুন।
  4. অ্যাবস্ট্রাক্ট ক্লাস android.hardware.foo.V1_0.IFooCallback.Stub পরীক্ষা করে দেখুন, তারপর এটিকে এক্সটেন্ড করতে এবং অ্যাবস্ট্রাক্ট পদ্ধতি প্রয়োগ করতে একটি নতুন ক্লাস লিখুন।

অটোমেটিক জেনারেট করা ফাইল দেখুন

অটোমেটিক তৈরি হওয়া ফাইল দেখতে, এগুলি রান করান:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

এইসব কমান্ড ডিরেক্টরি /tmp/android/hardware/foo/1.0 জেনারেট করে। file hardware/interfaces/foo/1.0/IFooCallback.hal-এর জন্য, এটি file /tmp/android/hardware/foo/1.0/IFooCallback.java তৈরি করে, যা Java ইন্টারফেস, প্রক্সি কোড এবং স্টাব (প্রক্সি ও স্টাব, দু'টিই ইন্টারফেসের সাথে সামঞ্জস্যপূর্ণ) এনক্যাপসুলেট করে।

-Lmakefile বিল্ড টাইমে এই কমান্ড চালানোর নিয়ম তৈরি করে এবং আপনাকে android.hardware.foo-V1.0-java অন্তর্ভুক্ত করতে ও সঠিক ফাইলের সাথে লিঙ্ক করতে দেয়। ইন্টারফেস সম্পূর্ণ প্রোজেক্টের জন্য অটোমেটিক এটি করে এমন একটি স্ক্রিপ্ট hardware/interfaces/update-makefiles.sh-এ পাওয়া যাবে। এই উদাহরণের পাথগুলি হল আপেক্ষিক; হার্ডওয়্যার/ইন্টারফেস আপনার কোড ট্রি-এর অধীনে একটি সাময়িক ডিরেক্টরি হতে পারে, যাতে আপনি এটি প্রকাশ করার আগে HAL ডেভেলপ করতে পারেন।

পরিষেবা চালানো

HAL IFoo ইন্টারফেস প্রদান করে, যা IFooCallback ইন্টারফেসের মাধ্যমে ফ্রেমওয়ার্কে অ্যাসিঙ্ক্রোনাস কলব্যাক করতে হবে। IFooCallback ইন্টারফেসটি খুঁজে পাওয়ার যোগ্য পরিষেবা হিসেবে নাম দিয়ে রেজিস্টার করা নেই; পরিবর্তে, IFoo-এ অবশ্যই setFooCallback(IFooCallback x)-এর মতো পদ্ধতি থাকতে হবে।

android.hardware.foo প্যাকেজের IFooCallback ভার্সন 1.0 থেকে সেট-আপ করতে, Android.mk-এ android.hardware.foo-V1.0-java যোগ করুন। পরিষেবা চালানোর জন্য এই কোডটি ব্যবহার করুন:

import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service from which you will be receiving callbacks.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);

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

ধরে নেওয়া যাক, কোনও পরিষেবা সমস্ত ডিভাইস জুড়ে IFoo ইন্টারফেস ইমপ্লিমেন্ট করে। সেক্ষেত্রে, কোনও নির্দিষ্ট ডিভাইসে, পরিষেবাটি ইন্টারফেস এক্সটেনশনে ইমপ্লিমেন্ট করা অতিরিক্ত ক্ষমতা প্রদান করতে পারে IBetterFoo, যেমন:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

এক্সটেন্ডেড ইন্টারফেস সম্পর্কে অবগত কলিং কোড castFrom() জাভা পদ্ধতি ব্যবহার করে বেস ইন্টারফেসকে এক্সটেন্ডেড ইন্টারফেসে নিরাপদে কাস্ট করতে পারে:

IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service implements only the base interface.
}