تتيح لغة 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 مخصّصًا لنظام التشغيل Android 11 أو إصدار أقدم).
هناك استثناء لهذه العملية. عندما تكون قيمة T هي IBinder أو واجهة AIDL، تكون قيمة @nullable هي no-op للخدمات الخلفية Java وCPP وNDK. على سبيل المثال، في الخلفية الخاصة بـ CPP، يتم ربط كل من @nullable IBinder وIBinder بشكل متساوٍ بـ android::sp<IBinder>، وهو قابل للتصغير لأنّه مؤشر قوي (تستمر عمليات القراءة في CPP وNDK في فرض إمكانية القيم الفارغة، ولكن يظل النوع android::sp<IBinder> أو ndk::SpAIBinder).
في الخلفية المستندة إلى Rust، يتم ربط الأنواع التي لا تنفّذ Default (IBinder وواجهات AIDL وParcelFileDescriptor وحزم البيانات غير المنظَّمة) بـ Option<T> استنادًا إلى سياقها:
- أنواع إرجاع الطريقة ومعلمات
inومعلماتinout: لا يمكن أن تكون هذه الأنواع فارغة إلا إذا تم وضع التعليق التوضيحي@nullableعليها، ما يؤدي إلى الربط بـOption<T>(أوOption<&T>لمعلماتinو&mut Option<T>لمعلماتinout). بدون@nullable، يتم ربطها مباشرةً بـT(أو&Tو&mut T). - حقول Parcelable ومعلمات
out: بما أنّ حقول Parcelable التي تم إنشاؤها في Rust تستند إلى معلماتDefaultويتم ضبط معلماتoutتلقائيًا، يتم دائمًا ربط هذه الأنواع بـOption<T>(ويتم ربط المصفوفات ذات الحجم الثابت في هذه السياقات بـ[Option<T>; N]، بينما يتم ربط المصفوفات الديناميكية في معلماتoutبـVec<Option<T>>)، حتى بدون@nullable. عندما لا يتم إضافة التعليق التوضيحي@nullable، سيظل يتم فرض عدم قبول القيم الخالية في وقت التشغيل أثناء تقسيم البيانات (سيتم عرضStatusCode::UNEXPECTED_NULLإذا كانت القيمةNone).
بدءًا من 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.
في 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 in comments
يتعرّف برنامج تجميع AIDL على @hide في التعليقات وينقلها إلى مخرجات Java ليتمكّن Metalava من استخدامه. يساعد هذا التعليق في ضمان أنّ نظام التصميم في Android يدرك أنّ واجهات برمجة تطبيقات لغة تعريف واجهة نظام Android (AIDL) ليست واجهات برمجة تطبيقات لحزمة تطوير البرامج (SDK).
@deprecated في التعليقات
يتعرّف برنامج ترجمة لغة تعريف واجهة Android (AIDL) على @deprecated في التعليقات كعلامة لتحديد عنصر AIDL لم يعُد يجب استخدامه:
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
يضع كل نظام خلفي علامة على الكيانات المتوقّفة نهائيًا باستخدام تعليق توضيحي أو سمة خاصة بالنظام الخلفي، وذلك لتنبيه رمز العميل إذا كان يشير إلى الكيانات المتوقّفة نهائيًا. على سبيل المثال، يتم إرفاق التعليق التوضيحي @Deprecated والعلامة @deprecated
بالرمز البرمجي الذي تم إنشاؤه بلغة Java.