"قائمة الرسائل السريعة" باستخدام لغة تعريف واجهة نظام Android ‏(AIDL)

اعتبارًا من Android 12، يمكن استخدام قائمة انتظار الرسائل السريعة (FMQ) مع واجهات لغة تعريف واجهة Android (AIDL) باستخدام وحدة NDK الخلفية. يتيح ذلك للعمليات التواصل بدون النفقات العامة والقيود المفروضة على معاملات أداة الربط بعد عملية إعداد قصيرة. يسمح استخدام لغة تعريف واجهة Android (AIDL) الثابتة بالتواصل بين عمليات النظام وعمليات مورّد الجهاز.

أنواع الحمولة المتوافقة

يجب أن يكون للرسائل المُرسَلة بين العمليات في قائمة انتظار الرسائل في الذاكرة المشترَكة تنسيق الذاكرة نفسه عبر حدود العمليات، ولا يمكن أن تحتوي على مؤشرات. تؤدي محاولة إنشاء AidlMessageQueue بنوع غير متوافق إلى حدوث خطأ في التجميع. لا يمكن استخدام أنواع parcelable وunion في لغة تعريف واجهة Android (AIDL) في وحدة cpp الخلفية مع "قائمة انتظار الرسائل السريعة" لأنّها موروثة من android::Parcelable التي تحتوي على وظائف افتراضية.

أنواع قوائم الانتظار المتوافقة

تتوافق لغة تعريف واجهة Android (AIDL) مع أنواع قوائم الانتظار نفسها من لغة تعريف واجهة Android (HIDL)، والتي غالبًا ما تُسمّى "النكهات". تُستخدَم هذه الأنواع كمعلّمات نموذجية لقوائم الانتظار والأوصاف.

أنواع لغة تعريف واجهة Android (HIDL)أنواع لغة تعريف واجهة Android (AIDL)
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

كيفية الاستخدام

حدِّد واجهة لغة تعريف واجهة Android (AIDL) التي تُرسِل MQDescriptor إلى العملية الأخرى. يمكن استخدام MQDescriptor في أي مكان يمكن فيه استخدام نوع `parcelable`.

المعلّمات النموذجية المطلوبة لـ MQDescriptor هي نوع الحمولة ونكهة قائمة الانتظار.

import android.hardware.common.fmq.MQDescriptor
import android.hardware.common.fmq.SynchronizedReadWrite

void getQueue(out MQDescriptor<int, SynchronizedReadWrite> mqDesc);

إنّ عملية إعداد كل جانب من قائمة انتظار الرسائل متطابقة تقريبًا مع العملية التي تستخدم لغة تعريف واجهة Android (HIDL)، ولكن باستخدام أنواع لغة تعريف واجهة Android (AIDL).

#include <fmq/AidlMessageQueue.h>
...
using ::android::AidlMessageQueue;
using ::aidl::android::hardware::common::fmq::MQDescriptor;
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
...
ndk::ScopedAStatus MyInterface::getQueue(MQDescriptor<int32_t, SynchronizedReadWrite>* mqDesc) {
    *mqDesc = mFmqSynchronized->dupeDesc();
    return ndk::ScopedAStatus::ok();
}
...
// Create the first side of the queue before servicing getQueue() in this example
mFmqSynchronized =
  new AidlMessageQueue<int32_t, SynchronizedReadWrite>(kNumElementsInQueue);

تنشئ العملية المُستلِمة الجانب الآخر من قائمة الانتظار باستخدام الوصف الذي تم تلقّيه من واجهة لغة تعريف واجهة Android (AIDL).

MQDescriptor<int32_t, SynchronizedReadWrite> desc;
auto ret = service->getQueue(true, &desc);
if (!ret.isOk()) {
   ...
}
// By default the constructor will reset the read and write pointers of the queue.
// Add a second `false` argument to avoid resetting the pointers.
mQueue = new (std::nothrow) AidlMessageQueue<int32_t, SynchronizedReadWrite>(desc);
if (!mQueue->isValid()) {
   ...
}

إنّ استخدام AidlMessageQueue بعد الإعداد هو نفسه استخدام MessageQueue في لغة تعريف واجهة Android (HIDL). تتوافق لغة تعريف واجهة Android (AIDL) بشكل كامل مع جميع واجهات برمجة التطبيقات الموضّحة في مقالة استخدام MessageQueue، باستثناء ما يلي:AidlMessageQueue

يتم استبدال const MQDescriptor<T, flavor>* getDesc() بـ MQDescriptor<T, U> dupeDesc() الذي يعرض MQDescriptor في لغة تعريف واجهة Android (AIDL).