التعليقات التوضيحية في 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> بشكل متساوٍ، وهو بالفعل لاغٍ لأنه مؤشر قوي (قراءات CPP لا تزال تفرض البطلان، لكن النوع لا يزال android::sp<IBinder> ).

بدءًا من 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.

لاحظ أن وجود التعليق التوضيحي 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 Soong، مع تعيين خاصية 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 {...}

هذا أمر محظور بالنسبة للواجهات الخلفية غير 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 تجاوز عملية التحقق عندما يكون العنصر القابل للتجزئة الذي تشير إليه متاحًا بالفعل بأمان كجزء من Android SDK.

@JavaOnlyStableParcelable
parcelable Data;

parcelable AnotherData {
    Data d; // OK
}

JavaDeriv

يقوم 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 API التي تم إنشاؤها باستخدام تعليق توضيحي عشوائي لـ 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)

في كود جافا الذي تم إنشاؤه.

يتم إصدار قيمة معلمة 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.

@محذوف في التعليقات

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

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

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