AIDL এমন অ্যানোটেশন সমর্থন করে যা AIDL কম্পাইলারকে অ্যানোটেড এলিমেন্ট সম্পর্কে অতিরিক্ত তথ্য দেয়, যা জেনারেটেড স্টাব কোডকেও প্রভাবিত করে।
এর সিনট্যাক্স জাভার অনুরূপ:
@AnnotationName(argument1=value, argument2=value) AidlEntity
এখানে, AnnotationName হলো অ্যানোটেশনটির নাম, এবং AidlEntity হলো interface Foo , void method() , বা int arg মতো একটি AIDL এনটিটি। একটি অ্যানোটেশন তার পরবর্তী এনটিটির সাথে সংযুক্ত হয়।
কিছু অ্যানোটেশনের ক্ষেত্রে বন্ধনীর ভেতরে আর্গুমেন্ট সেট করা যায়, যেমনটি আগের উদাহরণে দেখানো হয়েছে। যেসব অ্যানোটেশনের কোনো আর্গুমেন্ট থাকে না, সেগুলোর বন্ধনীর প্রয়োজন হয় না। উদাহরণস্বরূপ:
@AnnotationName AidlEntity
এই অ্যানোটেশনগুলো জাভা অ্যানোটেশনের মতো নয়, যদিও দেখতে একই রকম লাগে। সমস্ত অ্যানোটেশনই পূর্বনির্ধারিত, এবং কোথায় এগুলো যুক্ত করা যাবে তার উপর সীমাবদ্ধতা রয়েছে। কিছু অ্যানোটেশন কেবল একটি নির্দিষ্ট ব্যাকএন্ডে কাজ করে এবং অন্য ব্যাকএন্ডে কোনো প্রভাব ফেলে না।
এখানে পূর্বনির্ধারিত AIDL অ্যানোটেশনগুলির তালিকা দেওয়া হল:
| টীকা | অ্যান্ড্রয়েড সংস্করণে যোগ করা হয়েছে |
|---|---|
nullable | ৭ |
utf8InCpp | ৭ |
VintfStability | ১১ |
UnsupportedAppUsage | ১০ |
Hide | ১১ |
Backing | ১১ |
NdkOnlyStableParcelable | ১৪ |
JavaOnlyStableParcelable | ১১ |
JavaDerive | ১২ |
JavaPassthrough | ১২ |
FixedSize | ১২ |
Descriptor | ১২ |
নালযোগ্য
nullable নির্দেশ করে যে, অ্যানোটেড এনটিটির মান null হতে পারে।
আপনি এই অ্যানোটেশনটি শুধুমাত্র মেথড রিটার্ন টাইপ, মেথড প্যারামিটার এবং পার্সেলযোগ্য ফিল্ডে সংযুক্ত করতে পারেন:
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
প্রিমিটিভ টাইপের সাথে অ্যানোটেশন যুক্ত করা যায় না। নিম্নলিখিতটি একটি ত্রুটি:
void method(in @nullable int a); // int is a primitive type
এই অ্যানোটেশনটি জাভা ব্যাকএন্ডের জন্য কোনো কাজ করে না। জাভাতে, সমস্ত নন-প্রিমিটিভ টাইপ রেফারেন্সের মাধ্যমে পাস করা হয়, যা null ) হতে পারে।
CPP ব্যাকএন্ডে, @nullable T অ্যান্ড্রয়েড ১১ বা তার নিচের সংস্করণে std::unique_ptr<T> এর সাথে এবং অ্যান্ড্রয়েড ১২ বা তার উপরের সংস্করণে std::optional<T> এর সাথে ম্যাপ করে।
NDK ব্যাকএন্ডে, @nullable T std::optional<T> এর সাথে ম্যাপ করা হয়।
রাস্ট ব্যাকএন্ডে, @nullable T Option<T> -এর সাথে ম্যাপ করা হয়।
T[] বা List<T> এর মতো তালিকা-সদৃশ টাইপ L ক্ষেত্রে, @nullable L ম্যাপ করে std::optional<std::vector<std::optional<T>>> (অথবা Android 11 বা তার নিচের সংস্করণের CPP ব্যাকএন্ডের ক্ষেত্রে std::unique_ptr<std::vector<std::unique_ptr<T>>> )।
এই ম্যাপিংয়ের একটি ব্যতিক্রম আছে। যখন T একটি IBinder বা একটি AIDL ইন্টারফেস হয়, তখন Rust ছাড়া অন্য সব ব্যাকএন্ডের জন্য @nullable কোনো কাজ করে না। অন্য কথায়, @nullable IBinder এবং IBinder উভয়ই android::sp<IBinder> -এ সমানভাবে ম্যাপ করে, যা ইতোমধ্যেই নালযোগ্য কারণ এটি একটি স্ট্রং পয়েন্টার (CPP-এর নিয়ম অনুযায়ী নালযোগ্যতা বলবৎ থাকলেও টাইপটি android::sp<IBinder> ই থাকে)। Rust-এ, এই টাইপগুলো শুধুমাত্র তখনই nullable হয় যখন সেগুলোতে @nullable অ্যানোটেশন দেওয়া থাকে। অ্যানোটেশন দেওয়া থাকলে এগুলো Option<T> -এ ম্যাপ করে।
অ্যান্ড্রয়েড ১৩ থেকে শুরু করে, রিকার্সিভ টাইপ মডেল করার জন্য পার্সেলযোগ্য ফিল্ডে @nullable(heap=true) ব্যবহার করা যায়। মেথড প্যারামিটার বা রিটার্ন টাইপের সাথে @nullable(heap=true) ব্যবহার করা যায় না। এটি দিয়ে অ্যানোটেট করা হলে, CPP এবং NDK ব্যাকএন্ডে ফিল্ডটি একটি হিপ-অ্যালোকেটেড রেফারেন্স std::unique_ptr<T> এর সাথে ম্যাপ করা হয়। জাভা ব্যাকএন্ডে @nullable(heap=true) কোনো কাজ করে না।
utf8InCpp
utf8InCpp ঘোষণা করে যে CPP ব্যাকএন্ডের জন্য String ফরম্যাটটি UTF8-এ উপস্থাপিত হবে। এর নাম থেকেই বোঝা যায়, এই অ্যানোটেশনটি অন্যান্য ব্যাকএন্ডের জন্য কোনো কাজ করে না। নির্দিষ্টভাবে বললে, Java ব্যাকএন্ডে String সবসময় UTF16 এবং NDK ব্যাকএন্ডে UTF8 থাকে।
এই অ্যানোটেশনটি String টাইপ যেখানে যেখানে ব্যবহার করা যায়, তার সবখানে যুক্ত করা যেতে পারে; যেমন—রিটার্ন ভ্যালু, প্যারামিটার, কনস্ট্যান্ট ডিক্লারেশন এবং পার্সেলযোগ্য ফিল্ড।
CPP ব্যাকএন্ডের ক্ষেত্রে, AIDL-এ @utf8InCpp String std::string এ ম্যাপ করে, যেখানে অ্যানোটেশন ছাড়া String android::String16 এ ম্যাপ করে, যদি UTF16 ব্যবহৃত হয়।
VintfStability
VintfStability ঘোষণা করে যে একটি ব্যবহারকারী-সংজ্ঞায়িত টাইপ (ইন্টারফেস, পার্সেলযোগ্য, এবং এনাম) সিস্টেম এবং ভেন্ডর ডোমেন জুড়ে ব্যবহার করা যেতে পারে। সিস্টেম-ভেন্ডর আন্তঃকার্যক্ষমতা সম্পর্কে আরও জানতে AIDL for HALs দেখুন।
অ্যানোটেশনটি টাইপের সিগনেচার পরিবর্তন করে না, কিন্তু এটি সেট করা হলে টাইপটির ইনস্ট্যান্সকে স্টেবল হিসেবে চিহ্নিত করা হয়, যাতে এটি ভেন্ডর এবং সিস্টেম প্রসেস জুড়ে চলাচল করতে পারে।
অ্যানোটেশনটি শুধুমাত্র ব্যবহারকারী-সংজ্ঞায়িত টাইপ ডিক্লারেশনের সাথেই সংযুক্ত করা যেতে পারে, যেমনটি এখানে দেখানো হয়েছে:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
যখন কোনো টাইপকে VintfStability দিয়ে অ্যানোটেট করা হয়, তখন সেই টাইপে রেফারেন্স করা অন্য যেকোনো টাইপকেও একইভাবে অ্যানোটেট করতে হবে। নিচের উদাহরণে, Data এবং IBar উভয়কেই VintfStability দিয়ে অ্যানোটেট করতে হবে:
@VintfStability
interface IFoo {
void doSomething(in IBar b); // references IBar
void doAnother(in Data d); // references Data
}
@VintfStability // required
interface IBar {...}
@VintfStability // required
parcelable Data {...}
এছাড়াও, VintfStability দিয়ে টীকাযুক্ত টাইপগুলি সংজ্ঞায়িতকারী AIDL ফাইলগুলি শুধুমাত্র aidl_interface Soong মডিউল টাইপ ব্যবহার করে তৈরি করা যেতে পারে, যেখানে stability প্রপার্টিটি vintf এ সেট করা থাকে:
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
অসমর্থিত অ্যাপ ব্যবহার
UnsupportedAppUsage অ্যানোটেশনটি নির্দেশ করে যে, অ্যানোটেটেড AIDL টাইপটি এমন একটি নন-SDK ইন্টারফেসের অংশ যা লিগ্যাসি অ্যাপগুলোর জন্য অ্যাক্সেসযোগ্য ছিল। হিডেন API-গুলো সম্পর্কে আরও তথ্যের জন্য “Restrictions on non-SDK interfaces” দেখুন।
UnsupportedAppUsage অ্যানোটেশনটি জেনারেট করা কোডের আচরণকে প্রভাবিত করে না। এই অ্যানোটেশনটি শুধুমাত্র জেনারেট করা জাভা ক্লাসকে একই নামের জাভা অ্যানোটেশন দ্বারা অ্যানোটেট করে:
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
নন-জাভা ব্যাকএন্ডের জন্য এটি কোনো কাজ করে না।
সহায়ক টীকা
Backing অ্যানোটেশনটি একটি AIDL enum টাইপের স্টোরেজ টাইপ নির্দিষ্ট করে:
@Backing(type="int")
enum Color { RED, BLUE, }
CPP ব্যাকএন্ডে, এটি int32_t টাইপের একটি C++ enum ক্লাস তৈরি করে:
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
যদি অ্যানোটেশনটি বাদ দেওয়া হয়, তাহলে type byte হিসেবে ধরে নেওয়া হয়, যা CPP ব্যাকএন্ডের জন্য int8_t তে ম্যাপ করে।
type আর্গুমেন্টটি শুধুমাত্র নিম্নলিখিত ইন্টিগ্রাল টাইপগুলিতে সেট করা যেতে পারে:
-
byte(৮-বিট প্রশস্ত) -
int(৩২-বিট প্রশস্ত) -
long(৬৪-বিট প্রশস্ত)
NdkOnlyStableParcelable
NdkOnlyStableParcelable একটি পার্সেলযোগ্য ডিক্লারেশনকে (ডেফিনিশন নয়) স্টেবল হিসেবে চিহ্নিত করে, যাতে এটিকে অন্যান্য স্টেবল AIDL টাইপ থেকে রেফারেন্স করা যায়। এটি JavaOnlyStableParcelable মতোই, তবে NdkOnlyStableParcelable একটি পার্সেলযোগ্য ডিক্লারেশনকে জাভার পরিবর্তে NDK ব্যাকএন্ডের জন্য স্টেবল হিসেবে চিহ্নিত করে।
এই পার্সেলযোগ্যটি ব্যবহার করতে:
- আপনাকে অবশ্যই
ndk_headerনির্দিষ্ট করতে হবে। - আপনার অবশ্যই একটি NDK লাইব্রেরি থাকতে হবে যা পার্সেলযোগ্য (parcelable) নির্দিষ্ট করে এবং লাইব্রেরিটিকে অবশ্যই কম্পাইল করে লাইব্রেরিতে অন্তর্ভুক্ত করতে হবে। উদাহরণস্বরূপ, কোর বিল্ড সিস্টেমে একটি
cc_*মডিউলে,static_libsবাshared_libsব্যবহার করুন।aidl_interfaceএর জন্য,Android.bpএরadditional_shared_librariesএর অধীনে লাইব্রেরিটি যোগ করুন।
জাভাঅনলিস্টেবলপার্সেলেবল
JavaOnlyStableParcelable একটি পার্সেলযোগ্য ডিক্লারেশনকে (ডেফিনিশন নয়) স্টেবল হিসেবে চিহ্নিত করে, যাতে এটিকে অন্যান্য স্টেবল AIDL টাইপ থেকে রেফারেন্স করা যায়।
স্থিতিশীল AIDL-এর জন্য প্রয়োজন যে সমস্ত ব্যবহারকারী-সংজ্ঞায়িত টাইপ স্থিতিশীল হবে। পার্সেলযোগ্য ডেটা টাইপের স্থিতিশীল হওয়ার জন্য প্রয়োজন যে এর ফিল্ডগুলি AIDL সোর্স ফাইলে স্পষ্টভাবে বর্ণিত থাকে:
parcelable Data { // Data is a structured parcelable.
int x;
int y;
}
parcelable AnotherData { // AnotherData is also a structured parcelable
Data d; // OK, because Data is a structured parcelable
}
যদি পার্সেলযোগ্য বস্তুটি অসংগঠিত (বা কেবল ঘোষিত) হয়, তাহলে এটিকে উল্লেখ করা যাবে না:
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
JavaOnlyStableParcelable আপনাকে এই চেকটি ওভাররাইড করার সুযোগ দেয়, যখন আপনি যে পার্সেলেবলটি রেফারেন্স করছেন তা অ্যান্ড্রয়েড এসডিকে-র অংশ হিসেবে নিরাপদে উপলব্ধ থাকে:
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
জাভাডেরাইভ
JavaDerive জাভা ব্যাকএন্ডে পার্সেলযোগ্য টাইপগুলির জন্য স্বয়ংক্রিয়ভাবে মেথড তৈরি করে:
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
কী তৈরি হবে তা নিয়ন্ত্রণ করার জন্য অ্যানোটেশনটির অতিরিক্ত প্যারামিটার প্রয়োজন। সমর্থিত প্যারামিটারগুলো হলো:
-
equals=trueequalsএবংhashCodeমেথড তৈরি হয়। -
toString=truetoStringমেথড তৈরি করে যা টাইপের নাম এবং ফিল্ডগুলো প্রিন্ট করে, যেমন,Data{number: 42, str: foo}।
জাভাডিফল্ট (অপ্রচলিত)
Android 13-এ যুক্ত হওয়া JavaDefault , ডিফল্ট ইমপ্লিমেন্টেশন ভার্সনিং সাপোর্ট ( setDefaultImpl এর জন্য) তৈরি হবে কি না, তা নিয়ন্ত্রণ করে। জায়গা বাঁচানোর জন্য এই সাপোর্টটি এখন আর ডিফল্টভাবে তৈরি করা হয় না।
জাভা পাসথ্রু
JavaPassthrough মাধ্যমে জেনারেট করা জাভা এপিআই-কে যেকোনো জাভা অ্যানোটেশন দিয়ে চিহ্নিত করা যায়।
AIDL-এ এই টীকাগুলি:
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
জেনারেট করা জাভা কোডে নিম্নলিখিত রূপ ধারণ করবে:
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
annotation প্যারামিটারের মান সরাসরি নির্গত হয়। AIDL কম্পাইলার প্যারামিটারের মান পরীক্ষা করে না। যদি কোনো জাভা-স্তরের সিনট্যাক্স ত্রুটি থাকে, তবে তা AIDL কম্পাইলারের পরিবর্তে জাভা কম্পাইলার দ্বারা ধরা পড়বে।
এই অ্যানোটেশনটি যেকোনো AIDL এনটিটির সাথে যুক্ত করা যায়। নন-জাভা ব্যাকএন্ডের জন্য এই অ্যানোটেশনটি কোনো কাজ করে না।
রাস্টডেরাইভ
RustDerive স্বয়ংক্রিয়ভাবে জেনারেট করা রাস্ট টাইপগুলির জন্য ট্রেইট প্রয়োগ করে।
কী তৈরি হবে তা নিয়ন্ত্রণ করার জন্য অ্যানোটেশনটির অতিরিক্ত প্যারামিটার প্রয়োজন। সমর্থিত প্যারামিটারগুলো হলো:
-
Copy=true -
Clone=true -
Ord=true -
PartialOrd=true -
Eq=true -
PartialEq=true -
Hash=true
এই বৈশিষ্ট্যগুলির ব্যাখ্যার জন্য, রাস্ট ডকুমেন্টেশন দেখুন।
নির্দিষ্ট আকার
FixedSize একটি স্ট্রাকচার্ড পার্সেলএবলকে নির্দিষ্ট আকারের হিসেবে চিহ্নিত করে। একবার চিহ্নিত করার পর, আপনি পার্সেলএবলটিতে নতুন ফিল্ড যোগ করতে পারবেন না। পার্সেলএবলটির সমস্ত ফিল্ড অবশ্যই নির্দিষ্ট আকারের টাইপের হতে হবে, যার মধ্যে প্রিমিটিভ টাইপ, এনাম, নির্দিষ্ট আকারের অ্যারে এবং FixedSize দিয়ে চিহ্নিত অন্যান্য পার্সেলএবল অন্তর্ভুক্ত।
ndk ব্যাকএন্ডে FixedSize অবজেক্টগুলোর আকার ও বিন্যাস স্থিতিশীল থাকে।
| প্রকার | আকার (বাইট) | অ্যালাইনমেন্ট (বাইট) |
|---|---|---|
boolean | 1 | 1 |
byte | 1 | 1 |
char | 2 | 2 |
int | 4 | 4 |
long | 8 | 8 |
float | 4 | 4 |
double | 8 | 8 |
parcelable | সমস্ত ক্ষেত্রের মোট আকার | সমস্ত ক্ষেত্রের বৃহত্তম সারিবদ্ধতা |
union | সকল ক্ষেত্রের মধ্যে বৃহত্তম আকার | সমস্ত ক্ষেত্রের বৃহত্তম সারিবদ্ধতা |
enum | ব্যাকিং ধরণের আকার | ব্যাকিং টাইপের সারিবদ্ধকরণ |
T[N] (নির্দিষ্ট আকারের অ্যারে) | T * N এর আকার | T এর সারিবদ্ধকরণ |
String, IBinder, FileDescriptor, ParcelFileDescriptor | N/A | N/A |
বর্ণনাকারী
Descriptor কোনো একটি ইন্টারফেসের ইন্টারফেস ডেসক্রিপ্টরকে জোরপূর্বক নির্দিষ্ট করে:
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
এই ইন্টারফেসটির ডেসক্রিপ্টর হলো android.bar.IWorld । যদি Descriptor অ্যানোটেশনটি না থাকে, তাহলে ডেসক্রিপ্টরটি হবে android.foo.IHello ।
ইতিমধ্যে প্রকাশিত কোনো ইন্টারফেসের নাম পরিবর্তন করার জন্য এটি কার্যকর। নাম পরিবর্তন করা ইন্টারফেসের ডেসক্রিপ্টরকে আগের ইন্টারফেসের ডেসক্রিপ্টরের সমান করে দিলে, ইন্টারফেস দুটি একে অপরের সাথে যোগাযোগ করতে পারে।
@মন্তব্যে লুকান
AIDL কম্পাইলার কমেন্টের মধ্যে থাকা @hide শনাক্ত করে এবং metalava-র ব্যবহারের জন্য এটিকে জাভা আউটপুটে পাঠিয়ে দেয়। এই কমেন্টটি নিশ্চিত করতে সাহায্য করে যে অ্যান্ড্রয়েড বিল্ড সিস্টেম যেন বুঝতে পারে AIDL API-গুলো SDK API নয়।
মন্তব্যে @deprecated
AIDL কম্পাইলার কমেন্টের মধ্যে থাকা @deprecated ট্যাগটিকে এমন একটি AIDL এনটিটি শনাক্ত করার জন্য ব্যবহার করে, যা আর ব্যবহার করা উচিত নয়:
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
প্রতিটি ব্যাকএন্ড অপ্রচলিত সত্তাগুলোকে একটি ব্যাকএন্ড-নির্দিষ্ট অ্যানোটেশন বা অ্যাট্রিবিউট দিয়ে চিহ্নিত করে, যাতে ক্লায়েন্ট কোড সেই অপ্রচলিত সত্তাগুলোকে উল্লেখ করলে সতর্কবার্তা পায়। উদাহরণস্বরূপ, @Deprecated অ্যানোটেশন এবং @deprecated ট্যাগ জাভা জেনারেটেড কোডের সাথে যুক্ত করা হয়।