لغة تعريف واجهة نظام Android ‏(AIDL)

تستند لغة AIDL بشكل غير محكم إلى لغة Java. تحدّد الملفات عقد واجهة وأنواع بيانات وثوابت مختلفة مستخدَمة في هذا العقد.

الحزمة

يبدأ كل ملف AIDL بحزمة اختيارية تتوافق مع أسماء الحزم في مختلف الأنظمة الخلفية. يبدو تعريف الحزمة على النحو التالي:

    package my.package;

على غرار Java، يجب أن تكون ملفات AIDL في بنية مجلدات تتطابق مع حزمتها. يجب أن تكون الملفات التي تحتوي على الحزمة my.package في المجلد my/package/.

الأنواع

في ملفات AIDL، هناك العديد من المواضع التي يمكن فيها تحديد الأنواع. للحصول على قائمة دقيقة بالأنواع المتوافقة مع لغة AIDL، راجِع أنواع الخلفيات في AIDL.

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

تتيح عدة أجزاء من لغة AIDL استخدام التعليقات التوضيحية. للحصول على قائمة بالتعليقات التوضيحية ومواضع تطبيقها، يُرجى الاطّلاع على التعليقات التوضيحية في AIDL.

عمليات الاستيراد

لاستخدام أنواع محدّدة في واجهات أخرى، عليك أولاً إضافة التبعيات في نظام الإصدار. في وحدتَي cc_* وjava_* Soong، حيث يتم استخدام ملفات .aidl مباشرةً ضمن srcs في إصدارات منصة Android، يمكنك إضافة أدلة باستخدام الحقل aidl: { include_dirs: ... }. لعمليات الاستيراد باستخدام aidl_interface، اطّلِع على هذه المقالة.

يبدو الاستيراد على النحو التالي:

    import some.package.Foo;  // explicit import

عند استيراد نوع في الحزمة نفسها، يمكن حذف الحزمة. ومع ذلك، يمكن أن يؤدي حذف الحزمة إلى حدوث أخطاء استيراد غامضة عند تحديد الأنواع بدون حزمة ووضعها في مساحة الاسم العامة (بشكل عام، يجب أن تكون جميع الأنواع ذات مساحة اسم):

    import Foo;  // same as my.package.Foo

تحديد الأنواع

تحدّد ملفات AIDL بشكل عام الأنواع التي تُستخدَم كواجهة.

واجهات

في ما يلي مثال على واجهة AIDL:

    interface ITeleport {
        // Location defined elsewhere
        void teleport(Location baz, float speed);
        String getName();

        // ITeleportCallback defined elsewhere
        void methodWithCallback(ITeleportCallback callback);

        // ITeleportSession defined elsewhere
        ITeleportSession getASubInterface();
    }

تحدّد الواجهة عنصرًا يتضمّن سلسلة من الطرق. يمكن أن تكون الطرق إما oneway (oneway void doFoo()) أو متزامنة. إذا تم تعريف واجهة على أنّها oneway (oneway interface ITeleport {...})، ستكون جميع الطرق فيها oneway ضمنيًا. يتم إرسال الطرق أحادية الاتجاه بشكل غير متزامن ولا يمكنها عرض نتيجة. يتم أيضًا تنفيذ الطرق أحادية الاتجاه من سلسلة المحادثات نفسها إلى الرابط نفسه بشكل تسلسلي (على الرغم من أنّها قد تكون على سلاسل محادثات مختلفة). للاطّلاع على مناقشة حول كيفية إعداد سلاسل المحادثات، راجِع إدارة سلاسل المحادثات في الخلفيات المستندة إلى AIDL.

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

يمكن أن تتضمّن الطرق وسيطة واحدة أو أكثر. يمكن أن تكون وسيطات الإجراءات in أو out أو inout. للاطّلاع على مناقشة حول كيفية تأثير ذلك في أنواع الوسيطات، راجِع اتجاهات الخلفيات في AIDL.

Parcelables

للحصول على وصف حول كيفية إنشاء عناصر قابلة للتسلسل خاصة بالخادم الخلفي، يُرجى الاطّلاع على العناصر القابلة للتسلسل المخصّصة للخوادم الخلفية في AIDL.

يتيح الإصدار 10 من نظام التشغيل Android والإصدارات الأحدث تعريفات قابلة للتسلسل مباشرةً في لغة تعريف واجهة Android (AIDL). يُطلق على هذا النوع من العناصر القابلة للتسلسل اسم "عنصر قابل للتسلسل منظَّم". لمزيد من المعلومات حول العلاقة بين AIDL المنظَّمة والثابتة في برنامج ترجمة AIDL ونظام الإصدار، يُرجى الاطّلاع على مقارنة بين AIDL المنظَّمة والثابتة.

مثلاً:

    package my.package;

    import my.package.Boo;

    parcelable Baz {
        @utf8InCpp String name = "baz";
        Boo boo;
    }

الاتحادات

يتوافق الإصدار 12 من نظام التشغيل Android والإصدارات الأحدث مع تعريفات "الاتحاد الموسوم". مثلاً:

    package my.package;

    import my.package.FooSettings;
    import my.package.BarSettings;

    union Settings {
        FooSettings fooSettings;
        BarSettings barSettings;
        @utf8InCpp String str;
        int number;
    }

راجِع اتحادات الخلفيات في AIDL للحصول على تفاصيل خاصة بالخلفية.

تعدادات

يتيح الإصدار 11 من نظام التشغيل Android والإصدارات الأحدث إمكانية تعريف التعدادات. مثلاً:

    package my.package;

    enum Boo {
        A = 1 * 4,
        B = 3,
    }

تعريفات الأنواع المتداخلة

يتيح نظام التشغيل Android 13 والإصدارات الأحدث إمكانية استخدام تعريفات الأنواع المتداخلة. مثلاً:

    package my.package;

    import my.package.Baz;

    interface IFoo {
        void doFoo(Baz.Nested nested);  // defined in my/package/Baz.aidl
        void doBar(Bar bar);            // defined below

        parcelable Bar { ... }          // nested type definition
    }

الثوابت

يمكن أن تحتوي واجهات AIDL المخصّصة وعناصر parcelable وعناصر الاتحاد أيضًا على ثوابت عددية وثوابت سلاسل، مثل:

    const @utf8InCpp String HAPPY = ":)";
    const String SAD = ":(";
    const byte BYTE_ME = 1;
    const int ANSWER = 6 * 7;

التعبيرات الثابتة

يمكن تحديد ثوابت AIDL وأحجام المصفوفات والمعدِّدات باستخدام تعبيرات ثابتة. يمكن أن تستخدم التعبيرات الأقواس لتضمين العمليات. يمكن استخدام قيم التعبيرات الثابتة مع القيم الصحيحة أو قيم الفاصلة العائمة.

تمثّل القيم الحرفية true وfalse القيم المنطقية. يتم اعتبار القيم التي تتضمّن . ولكن بدون لاحقة، مثل 3.8، قيمًا مزدوجة. تحتوي قيم الفاصلة العائمة على اللاحقة f، مثل 2.4f. تشير القيمة المتكاملة التي تتضمّن اللاحقة l أو L إلى قيمة طويلة 64 بت. بخلاف ذلك، تحصل قيم الأعداد الصحيحة على أصغر نوع موقّع يحافظ على القيمة بين 8 بت (بايت) و32 بت (عدد صحيح) و64 بت (طويل). لذا، يُعدّ 256 int، ولكن 255 + 1 يفيض ليصبح byte 0. يتم أولاً تفسير القيم السداسية العشرية، مثل 0x3، كأصغر نوع غير موقّع يحافظ على القيمة بين 32 بت و64 بت، ثم يتم إعادة تفسيرها كقيم غير موقّعة. إذًا، 0xffffffff لها القيمة int -1. بدءًا من نظام التشغيل Android 13، يمكن إضافة اللاحقة u8 إلى الثوابت، مثل 3u8، لتمثيل قيمة byte. هذه اللاحقة مهمة حتى يتم تفسير عملية حسابية، مثل 0xffu8 * 3، على أنّها -3 من النوع byte، بينما 0xff * 3 هي 765 من النوع int.

تتضمّن عوامل التشغيل المتوافقة دلالات C++ وJava. يتم ترتيب عوامل التشغيل الثنائية من الأولوية الأدنى إلى الأعلى كما يلي: || && | ^ & == != < > <= >= << >> + - * / %. عوامل التشغيل الأحادية هي + - ! ~.