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

از Android 12، صف پیام سریع (FMQ) می‌تواند با میاناهای AIDL بااستفاده از پس‌بک NDK استفاده شود. این کار به فرایندها امکان می‌دهد بدون سربار و محدودیت‌های تراکنش‌های پیونددهنده پس‌از راه‌اندازی کوتاهی با هم ارتباط برقرار کنند. استفاده از AIDL پایدار امکان برقراری ارتباط بین سیستم و فرایندهای فروشنده را فراهم می‌کند.

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

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

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

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

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

انواع 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 را برمی‌گرداند.