لغة تعريف واجهة نظام 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 والإصدارات الأحدث تعريفات قابلة للتسلسل مباشرةً في 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. بدءًا من الإصدار 13 من نظام التشغيل Android، يمكن إضافة اللاحقة u8 إلى الثوابت، مثل 3u8، لتمثيل قيمة byte. هذه اللاحقة مهمة حتى يتم تفسير عملية حسابية، مثل 0xffu8 * 3، على أنّها -3 من النوع byte، بينما 0xff * 3 هي 765 من النوع int.

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