تتيح لغة AIDL استخدام التعليقات التوضيحية التي تقدّم للمترجم البرمجي AIDL معلومات إضافية حول العنصر الذي تمت إضافة التعليق التوضيحي إليه، ما يؤثر أيضًا في رمز العنصر النائب الذي تم إنشاؤه.
تتشابه بنية هذه الأوامر مع بنية Java:
@AnnotationName(argument1=value, argument2=value) AidlEntity
في هذا المثال، AnnotationName هو اسم التعليق التوضيحي، وAidlEntity هو عنصر AIDL، مثل interface Foo أو void method() أو int arg. يتم إرفاق تعليق توضيحي بالعنصر الذي يليه.
يمكن أن تتضمّن بعض التعليقات التوضيحية وسيطات مضبوطة داخل الأقواس، كما هو موضّح في المثال السابق. لا تحتاج التعليقات التوضيحية التي لا تتضمّن وسيطة إلى أقواس. مثلاً:
@AnnotationName AidlEntity
لا تتشابه هذه التعليقات التوضيحية مع تعليقات Java التوضيحية، على الرغم من أنّها تبدو متشابهة. جميع التعليقات التوضيحية محددة مسبقًا، وتخضع لقيود بشأن الأماكن التي يمكنك إرفاقها بها. تؤثّر بعض التعليقات التوضيحية في بعض الأنظمة الخلفية فقط، ولا يكون لها أي تأثير في الأنظمة الخلفية الأخرى.
في ما يلي قائمة بالتعليقات التوضيحية المُحدَّدة مسبقًا في AIDL:
| التعليقات التوضيحية | تمت إضافة هذا الإذن في إصدار Android |
|---|---|
nullable | 7 |
utf8InCpp | 7 |
VintfStability | 11 |
UnsupportedAppUsage | 10 |
Hide | 11 |
Backing | 11 |
NdkOnlyStableParcelable | 14 |
JavaOnlyStableParcelable | 11 |
JavaDerive | 12 |
JavaPassthrough | 12 |
FixedSize | 12 |
Descriptor | 12 |
nullable
توضّح nullable أنّ قيمة العنصر المشروح يمكن أن تكون فارغة.
يمكنك إرفاق هذه التعليق التوضيحي فقط بأنواع إرجاع الطرق ومعلَمات الطرق والحقول القابلة للتجزئة:
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
لا تؤدي هذه التعليقات التوضيحية أي عملية في الخلفية المستندة إلى Java. في Java، يتم تمرير جميع الأنواع غير الأساسية حسب المرجع، ما قد يؤدي إلى null.
في الخلفية الخاصة بـ CPP، يتم ربط @nullable T بـ std::unique_ptr<T> في الإصدار 11 من نظام التشغيل Android أو الإصدارات الأقدم، وبـ std::optional<T> في الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث.
في الخلفية الأصلية (NDK)، يتم ربط @nullable T بـ std::optional<T>.
في الخلفية المستندة إلى Rust، يتم ربط @nullable T بـ Option<T>.
بالنسبة إلى نوع يشبه القائمة L مثل T[] أو List<T>، يتم ربط @nullable L بـ std::optional<std::vector<std::optional<T>>> (أو std::unique_ptr<std::vector<std::unique_ptr<T>>> في حال كان الخادم الخلفي لـ CPP متوافقًا مع الإصدار 11 من نظام التشغيل Android أو إصدار أقدم).
هناك استثناء لهذه العملية. عندما يكون T
هو IBinder أو واجهة AIDL، يكون @nullable بلا تأثير لجميع الأنظمة الخلفية باستثناء Rust. بعبارة أخرى، يتم ربط كل من
@nullable IBinder وIBinder بشكل متساوٍ بـ android::sp<IBinder>، وهو
قابل للقيم الخالية لأنّه مؤشر قوي (لا تزال عمليات القراءة في CPP
تفرض إمكانية القيم الخالية، ولكن يظل النوع android::sp<IBinder>). في Rust،
تكون هذه الأنواع nullable فقط إذا تم وضع التعليق التوضيحي @nullable عليها. ويتم ربطها بـ Option<T> في حال إضافة تعليق توضيحي إليها.
بدءًا من Android 13، يمكن استخدام @nullable(heap=true) مع حقول قابلة للتسلسل من أجل تصميم أنواع متكرّرة. لا يمكن استخدام @nullable(heap=true) مع مَعلمات الطرق أو أنواع الإرجاع. عند إضافة هذه التعليقات التوضيحية، يتم ربط الحقل بمرجع مخصّص في الذاكرة المؤقتة std::unique_ptr<T> في الخلفيتَين CPP وNDK. @nullable(heap=true) هي عملية غير نشطة في الخلفية المستندة إلى Java.
utf8InCpp
تعلن utf8InCpp أنّ String يتم تمثيله بتنسيق UTF8 في الخلفية الخاصة بلغة CPP. وكما يشير اسمه، فإنّ التعليق التوضيحي لا يؤدي أي عملية في الأنظمة الخلفية الأخرى.
على وجه التحديد، يكون String دائمًا بتنسيق UTF16 في الخلفية المستندة إلى Java وبتنسيق UTF8 في الخلفية المستندة إلى NDK.
يمكن إرفاق هذه التعليقات التوضيحية في أي مكان يمكن فيه استخدام النوع String،
بما في ذلك قيم الإرجاع والمَعلمات وتعريفات الثوابت والحقول القابلة للتجزئة.
بالنسبة إلى الخلفية البرمجية CPP، يتم ربط @utf8InCpp String في AIDL بـ std::string، حيث يتم ربط
String بدون التعليق التوضيحي بـ android::String16 حيث يتم استخدام UTF16.
VintfStability
تعلن VintfStability عن إمكانية استخدام نوع محدّد من قِبل المستخدم (واجهة، وقابل للتسلسل، وقيمة تعداد) في جميع نطاقات النظام والمورّد. راجِع
AIDL لواجهات HAL لمعرفة المزيد حول
إمكانية التشغيل التفاعلي بين النظام والمورّد.
لا تغيّر التعليقات التوضيحية توقيع النوع، ولكن عند ضبطها، يتم وضع علامة على مثيل النوع على أنّه ثابت حتى يتمكّن من الانتقال بين عمليات المورّد والنظام.
يمكن إرفاق التعليق التوضيحي بتعريفات الأنواع التي يحدّدها المستخدم فقط، كما هو موضّح هنا:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
عند إضافة التعليق التوضيحي VintfStability إلى أحد الأنواع، يجب إضافة التعليق التوضيحي نفسه إلى أي نوع آخر تتم الإشارة إليه في النوع. في المثال التالي، يجب إضافة التعليق التوضيحي VintfStability إلى كل من Data وIBar:
@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 {...}
بالإضافة إلى ذلك، لا يمكن إنشاء ملفات AIDL التي تحدّد الأنواع التي تمّت إضافة تعليقات توضيحية إليها باستخدام VintfStability إلا باستخدام نوع وحدة aidl_interface Soong، مع ضبط السمة stability على vintf:
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
UnsupportedAppUsage
تشير التعليقة التوضيحية UnsupportedAppUsage إلى أنّ نوع AIDL الذي تمت إضافة التعليقات التوضيحية إليه هو جزء من واجهة غير متوفرة في حزمة SDK، وقد كان متاحًا للتطبيقات القديمة.
يمكنك الاطّلاع على القيود المفروضة على الواجهات غير التابعة لحزمة تطوير البرامج (SDK) للحصول على مزيد من المعلومات حول واجهات برمجة التطبيقات المخفية.
لا يؤثر التعليق التوضيحي UnsupportedAppUsage في سلوك الرمز البرمجي الذي تم إنشاؤه. تضيف التعليقات التوضيحية تعليقًا توضيحيًا إلى فئة Java التي تم إنشاؤها فقط، ويكون التعليق التوضيحي في Java بالاسم نفسه:
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
لا يتم تنفيذ أي عملية في الخلفيات غير المستندة إلى Java.
التعليق التوضيحي الداعم
تحدّد التعليق التوضيحي Backing نوع التخزين لنوع تعداد AIDL:
@Backing(type="int")
enum Color { RED, BLUE, }
في الخلفية البرمجية للغة CPP، يؤدي ذلك إلى إنشاء فئة تعداد C++ من النوع int32_t:
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
في حال حذف التعليق التوضيحي، سيتم افتراض أنّ قيمة type هي byte، ما يؤدي إلى ربطها بالقيمة int8_t في الخلفية الخاصة بمنصة CPP.
لا يمكن ضبط وسيطة type إلا على الأنواع المتكاملة التالية:
-
byte(8 بت) -
int(بعرض 32 بت) long(بعرض 64 بت)
NdkOnlyStableParcelable
تضع العلامة NdkOnlyStableParcelable علامة على تعريف (وليس تصريحًا) قابل للتسلسل على أنّه ثابت، ما يتيح إمكانية الرجوع إليه من أنواع AIDL ثابتة أخرى. هذه السمة مشابهة للسمة JavaOnlyStableParcelable، ولكن السمة NdkOnlyStableParcelable تحدّد أنّ تعريف الكائن القابل للتسلسل مستقر في الخلفية الخاصة بـ NDK بدلاً من Java.
لاستخدام هذا العنصر القابل للتسلسل:
- يجب تحديد
ndk_header. - يجب أن تتضمّن حزمة تطوير البرامج (NDK) مكتبة تحدّد العنصر القابل للتسلسل، ويجب تجميع المكتبة في الحزمة. على سبيل المثال، في نظام الإنشاء الأساسي على وحدة
cc_*، استخدِمstatic_libsأوshared_libs. بالنسبة إلىaidl_interface، أضِف المكتبة ضمنadditional_shared_librariesفيAndroid.bp.
JavaOnlyStableParcelable
تضع العلامة 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 تجاهل عملية التحقّق عندما يكون العنصر القابل للتسلسل الذي تشير إليه متاحًا بأمان كجزء من حزمة تطوير البرامج (SDK) لنظام التشغيل Android:
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
تنشئ JavaDerive تلقائيًا طرقًا لأنواع قابلة للتسلسل في
الخادم الخلفي المستند إلى Java:
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
تتطلّب التعليقات التوضيحية مَعلمات إضافية للتحكّم في المحتوى الذي سيتم إنشاؤه. المَعلمات المتوافقة هي:
- تنشئ
equals=trueالدالتَينequalsوhashCode. - تنشئ
toString=trueالطريقةtoStringالتي تطبع اسم النوع والحقول، على سبيل المثال،Data{number: 42, str: foo}.
JavaDefault (متوقّفة نهائيًا)
تتحكّم السمة JavaDefault، التي تمت إضافتها في نظام التشغيل Android 13، في ما إذا كان سيتم إنشاء دعم إصدار التنفيذ التلقائي (لـ setDefaultImpl). ولم يعُد يتم إنشاء هذا الدعم تلقائيًا من أجل توفير مساحة.
JavaPassthrough
تسمح السمة JavaPassthrough بإضافة تعليق توضيحي Java عشوائي إلى واجهة Java API التي تم إنشاؤها.
في ما يلي التعليقات التوضيحية في AIDL:
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
يصبح ما يلي في رمز Java الذي تم إنشاؤه:
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
يتم إرسال قيمة المَعلمة annotation مباشرةً. لا يفحص برنامج ترجمة AIDL قيمة المَعلمة. إذا كان هناك أي خطأ في بنية Java، لن يرصده برنامج ترجمة AIDL، بل سيرصده برنامج ترجمة Java.
يمكن إرفاق هذه التعليق التوضيحي بأي عنصر AIDL. هذه التعليق التوضيحي لا يؤدي أي عملية في الأنظمة الخلفية غير المستندة إلى Java.
RustDerive
تنفّذ RustDerive تلقائيًا السمات لأنواع Rust التي تم إنشاؤها.
تتطلّب التعليقات التوضيحية مَعلمات إضافية للتحكّم في المحتوى الذي سيتم إنشاؤه. المَعلمات المتوافقة هي:
Copy=trueClone=trueOrd=truePartialOrd=trueEq=truePartialEq=trueHash=true
للحصول على توضيحات حول هذه السمات، يُرجى الاطّلاع على مستندات Rust.
FixedSize
تضع FixedSize علامة على حزمة قابلة للتحليل كحجم ثابت. بعد وضع العلامة، لن تتمكّن من إضافة حقول جديدة إلى العنصر القابل للتسلسل. يجب أن تكون جميع حقول العنصر القابل للتسلسل من أنواع ذات حجم ثابت، بما في ذلك الأنواع الأساسية والتعدادات والمصفوفات ذات الحجم الثابت والعناصر الأخرى القابلة للتسلسل والمميّزة بالعلامة FixedSize.
تتميز عناصر FixedSize بأحجام وعمليات محاذاة ثابتة في الخلفية ndk.
| النوع | الحجم (بالبايت) | المحاذاة (بايت) |
|---|---|---|
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.
ويكون ذلك مفيدًا لإعادة تسمية واجهة سبق نشرها. إنّ جعل واصف الواجهة التي تمت إعادة تسميتها مطابقًا لواصف الواجهة قبل إعادة التسمية يتيح للواجهتين التواصل مع بعضهما.
@hide في التعليقات
يتعرّف برنامج ترجمة AIDL على @hide في التعليقات وينقلها إلى مخرجات Java ليتمكّن Metalava من استخدامه. يساعد هذا التعليق في ضمان أن يتعرّف نظام الإصدار في Android على أنّ واجهات برمجة تطبيقات AIDL ليست واجهات برمجة تطبيقات لحزمة تطوير البرامج (SDK).
@deprecated في التعليقات
يتعرّف برنامج ترجمة AIDL على @deprecated في التعليقات كعلامة لتحديد عنصر AIDL لم يعُد يجب استخدامه:
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
يضع كل نظام خلفي تعليقًا توضيحيًا أو سمة خاصة بالنظام الخلفي على الكيانات المتوقّفة نهائيًا، وذلك لتنبيه رمز العميل إذا كان يشير إلى الكيانات المتوقّفة نهائيًا. على سبيل المثال، يتم إرفاق التعليق التوضيحي @Deprecated والعلامة @deprecated بالرمز البرمجي الذي تم إنشاؤه بلغة Java.