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

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

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

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

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

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

أنواع HIDL أنواع AIDL
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

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

حدِّد واجهة AIDL التي تنقل MQDescriptor إلى العملية الأخرى. يمكن استخدام MQDescriptor في أي مكان يمكن استخدام كائن قابل للتسلسل.

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

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

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

إنّ عملية إعداد كل جانب من جوانب قائمة انتظار الرسائل تكاد تكون مطابقة للعملية التي تستخدم HIDL، ولكن باستخدام أنواع 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);

تنشئ عملية الاستلام الجانب الآخر من قائمة الانتظار باستخدام واصف تم استلامه من واجهة 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 في HIDL. تتوافق جميع واجهات برمجة التطبيقات الموضّحة في استخدام MessageQueue تمامًا مع AidlMessageQueue باستثناء ما يلي:

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