صف پیام سریع با AIDL

از اندروید ۱۲، صف پیام سریع (Fast Message Queue) می‌تواند با رابط‌های AIDL با استفاده از backend NDK مورد استفاده قرار گیرد. این امر به فرآیندها اجازه می‌دهد تا پس از کمی راه‌اندازی کوتاه، بدون سربار و محدودیت‌های تراکنش‌های binder ارتباط برقرار کنند. استفاده از AIDL پایدار، امکان ارتباط بین فرآیندهای سیستم و فروشنده را فراهم می‌کند.

انواع بار داده پشتیبانی شده

  • انواع parcelable FixedSize AIDL (از backend cpp در دسترس نیست)
  • انواع union AIDL (از پشت صحنه cpp در دسترس نیست)
  • انواع enum AIDL
  • انواع انتگرال AIDL

پیام‌های ارسالی بین فرآیندها در صف پیام حافظه مشترک باید طرح‌بندی حافظه یکسانی در سراسر مرزهای فرآیند داشته باشند و نمی‌توانند حاوی اشاره‌گر باشند. تلاش برای ایجاد یک AidlMessageQueue با نوعی که پشتیبانی نمی‌شود، باعث خطای کامپایل می‌شود. انواع AIDL parcelable و union در backend cpp را نمی‌توان با Fast Message Queue استفاده کرد زیرا از android::Parcelable ارث‌بری می‌کنند که دارای توابع مجازی است.

انواع صف پشتیبانی شده

همان انواع صف در HIDL که اغلب flavors نامیده می‌شوند، توسط AIDL پشتیبانی می‌شوند. این‌ها به عنوان آرگومان‌های الگو برای صف‌ها و توصیف‌گرها استفاده می‌شوند.

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

نحوه استفاده

رابط AIDL را که MQDescriptor به فرآیند دیگر منتقل می‌کند، تعریف کنید. MQDescriptor می‌تواند در هر جایی که یک parcelable وجود دارد، استفاده شود.

آرگومان‌های الگوی مورد نیاز برای MQDescriptor نوع بار مفید (payload type) و نوع صف (queue flavor) هستند.

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 پس از راه‌اندازی، مشابه HIDL MessageQueue است. تمام APIهای شرح داده شده در Use the MessageQueue به طور کامل توسط AidlMessageQueue پشتیبانی می‌شوند، با یک استثنا:

const MQDescriptor<T, flavor>* getDesc() با MQDescriptor<T, U> dupeDesc() جایگزین شده است که AIDL MQDescriptor را برمی‌گرداند.