التعليقات التوضيحية في AIDL

يدعم AIDL التعليقات التوضيحية التي تمنح مجمِّع AIDL معلومات إضافية حول العنصر الذي تم التعليق عليه، والتي تؤثر أيضًا في رمز التمثيل البرمجي الذي تم إنشاؤه.

تشبه بناء الجملة بنية Java:

@AnnotationName(argument1=value, argument2=value) AidlEntity

هنا، AnnotationName هو اسم التعليق التوضيحي، وAidlEntity هو كيان AIDL مثل interface Foo أو void method() أو int arg. يتم إرفاق التعليق التوضيحي بالكيان الذي يليه.

يمكن أن تحتوي بعض التعليقات التوضيحية على وسيطات داخل الأقواس، كما هو موضح أعلاه. لا تحتاج التعليقات التوضيحية التي لا تحتوي على وسيطة إلى الأقواس. على سبيل المثال:

@AnnotationName AidlEntity

هذه التعليقات التوضيحية ليست مماثلة لتعليقات Java، على الرغم من أنها تبدو متشابهة جدًا. لا يمكن للمستخدمين تحديد تعليقات AIDL المخصّصة؛ فجميع التعليقات التوضيحية محددة مسبقًا. تؤثر بعض التعليقات التوضيحية على واجهة خلفية معينة فقط ولا تعمل في الخلفيات الأخرى. ولديها قيود مختلفة حيث يمكن إرفاقها.

في ما يلي قائمة بتعليقات 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 أنّه قد لا يتم تقديم قيمة العنصر الذي تم التعليق عليه.

يمكن إرفاق هذا التعليق التوضيحي فقط بأنواع إرجاع الطريقة ومعاملاتها وحقول العناصر القابلة للنقل.

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> في Android 11 أو الإصدارات الأقدم، وstd::optional<T> في Android 12 أو الإصدارات الأحدث.

في الواجهة الخلفية NDK، يتم ربط @nullable T دائمًا بـ std::optional<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 متاحًا، أي أنّ كلاً من @nullable IBinder وIBinder مرتبطان بشكل متساوٍ بـ android::sp<IBinder>، وهو ما يمكن أن يكون قابلاً للإلغاء لأنه مؤشر قوي (تظل قراءات صفحة المنتج في خدمة مقارنة الأسعار تفرض قابلية القيم الفارغة، إلا أنّ النوع لا يزال android::sp<IBinder>).

بدءًا من الإصدار 13 من نظام التشغيل Android، يمكن استخدام @nullable(heap=true) للحقول القابلة للقياس لإنشاء نماذج للأنواع المتكررة. لا يمكن استخدام @nullable(heap=true) مع معلمات الطريقة أو أنواع الإرجاع. وعند إضافة تعليق توضيحي إلى الحقل، يتم ربط هذا الحقل بمرجع تم تخصيصه لأجزاء من الذاكرة في std::unique_ptr<T> في الخلفيات الخلفية لـ CPP/NDK. ميزة "@nullable(heap=true)" ليست عملية في واجهة Java الخلفية.

utf8InCpp

يُشير utf8InCpp إلى أنّ String تم تمثيله بتنسيق UTF8 في خلفية صفحة CPP. وكما يشير اسمه، لا يمكن استخدام التعليق التوضيحي في الخلفيات الأخرى. وعلى وجه التحديد، يكون String دائمًا بترميز UTF16 في الواجهة الخلفية لـ Java وUTF-8 في الواجهة الخلفية لـ NDK.

يمكن إرفاق هذا التعليق التوضيحي في أي مكان يمكن فيه استخدام النوع String، بما في ذلك القيم المعروضة والمعلَمات والتعريفات الثابتة والحقول القابلة لقطع الموقع.

في خلفية CPP، يتم ربط @utf8InCpp String في AIDL بـ std::string، في حين يتم ربط String بدون التعليق التوضيحي بـ android::String16 حيث يتم استخدام UTF16.

يُرجى العِلم أنّ توفُّر التعليق التوضيحي utf8InCpp لا يغيّر طريقة نقل السلاسل عبر السلك. يتم دائمًا نقل السلاسل بتنسيق UTF16 عبر السلك. يتم تحويل سلسلة utf8InCpp التي تتضمّن تعليقات توضيحية إلى UTF16 قبل نقلها. عند استلام سلسلة، يتم تحويلها من UTF16 إلى UTF8 إذا تمت إضافة تعليق توضيحي إليها على أنها utf8InCpp.

ثبات VintfStability

تشير الدالة VintfStability إلى أنّه يمكن استخدام نوع محدّد من المستخدم (واجهة وعنصر قابل للقياس وتعداد) في نطاقات النظام والمورّدين. راجِع AIDL لـ 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 {...}

بالإضافة إلى ذلك، لا يمكن إنشاء ملفّات AIDL التي تحدّد الأنواع التي تتضمّن تعليقات توضيحية باستخدام VintfStability إلا باستخدام نوع وحدة aidl_interface Sayg، مع ضبط السمة stability على "vintf".

aidl_interface {
    name: "my_interface",
    srcs: [...],
    stability: "vintf",
}

استخدام غير متوافق مع التطبيق

يشير التعليق التوضيحي UnsupportedAppUsage إلى أنّ نوع AIDL الذي يتضمّن تعليقات توضيحية هو جزء من واجهة غير حزمة تطوير البرامج (SDK) التي أتاحت التطبيقات القديمة الوصول إليها. راجع القيود المفروضة على الواجهات غير المستندة إلى حزمة SDK للحصول على مزيد من المعلومات حول واجهات برمجة التطبيقات المخفية.

ولا يؤثر تعليق UnsupportedAppUsage التوضيحي في سلوك الرمز الذي تم إنشاؤه. لا يضيف التعليق التوضيحي سوى تعليقات توضيحية على فئة Java التي تم إنشاؤها إلا مع تعليق Java التوضيحي الذي يحمل الاسم نفسه.

// in AIDL
@UnsupportedAppUsage
interface IFoo {...}

// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}

لا يمكن تنفيذ هذا الإجراء على الخلفيات التي لا تستخدم JavaScript.

دعامة

يحدّد التعليق التوضيحي 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). لم يعُد يتم توفير هذا الدعم تلقائيًا لتوفير مساحة.

مرور Java

يتيح JavaPassthrough إضافة تعليقات توضيحية إلى واجهة برمجة تطبيقات Java التي تم إنشاؤها، وذلك باستخدام تعليق توضيحي عشوائي لـ Java.

التعليقات التوضيحية التالية في لغة 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)

في رمز Java الذي تم إنشاؤه.

تنبعث قيمة المَعلمة annotation مباشرةً. لا ينظر محوّل AIDL في قيمة المعلمة. إذا كان هناك أي خطأ في بنية Java، لن يكتشفه المحول البرمجي لـ AIDL ولكن من خلال المحول البرمجي لـ Java.

يمكن إرفاق هذا التعليق التوضيحي بأي كيان AIDL. لا يمكن استخدام هذا التعليق التوضيحي للواجهات الخلفية بخلاف Java.

حجم ثابت

يضع FixedSize علامة على قطعة إعلانية منظَّمة على أنّها ذات حجم ثابت. بعد وضع علامة على العنصر، لن يُسمح بإضافة حقول جديدة إليه. يجب أيضًا أن تكون جميع حقول قطع العقارات ذات أحجام ثابتة، بما في ذلك الأنواع الأولية والتعدادات والصفائف ذات الحجم الثابت وغيرها من العناصر التي تحمل علامة FixedSize.

وهذا لا يوفر أي ضمان على مستوى وحدات بت مختلفة ولا ينبغي الاعتماد عليه في التواصل متعدد البت.

الواصف

تحدد السمة Descriptor واصف الواجهة للواجهة بقوة.

package android.foo;

@Descriptor(value="android.bar.IWorld")
interface IHello {...}

واصف هذه الواجهة هو android.bar.IWorld. في حال عدم توفّر تعليق Descriptor التوضيحي، سيكون الواصف هو android.foo.IHello.

يفيد ذلك في إعادة تسمية واجهة منشورة من قبل. جعل واصف الواجهة المُعاد تسميتها مماثلاً لواصف الواجهة قبل إعادة التسمية يمكن للواجهتين التحدث مع بعضها البعض.

إخفاء @ في التعليقات

يتعرّف المحول البرمجي AIDL على اللغة @hide في التعليقات ويمررها إلى مخرجات Java ليتم توصيلها باستخدام Metalava. يضمن هذا التعليق معرفة نظام إصدار Android أن واجهات برمجة تطبيقات AIDL ليست واجهات برمجة تطبيقات لحزمة تطوير البرامج (SDK).

@deprecated في التعليقات

يتعرّف برنامج التحويل البرمجي AIDL على @deprecated في التعليقات كعلامة لتحديد كيان AIDL الذي يجب عدم استخدامه بعد الآن.

interface IFoo {
  /** @deprecated use bar() instead */
  void foo();
  void bar();
}

تضع كل واجهة خلفية عناصر متوقّفة نهائيًا مع تعليق توضيحي أو سمة خاصة بالخلفية حتى يتم تحذير رمز العميل إذا كان يشير إلى العناصر المتوقّفة نهائيًا. على سبيل المثال، يتم إرفاق التعليق التوضيحي @Deprecated والعلامة @deprecated بالرمز البرمجي الذي ينشئه Java.