Fast Message Queue עם AIDL

החל מ-Android 12, אפשר להשתמש ב-Fast Message Queue עם ממשקי AIDL באמצעות קצה העורפי של NDK. השיטה הזו מאפשרת לתהליכים לתקשר בלי התקורה וההגבלות של עסקאות binder אחרי הגדרה קצרה. שימוש ב-Stable AIDL מאפשר תקשורת בין תהליכי מערכת ותהליכי ספק.

סוגי מטען ייעודי נתמכים

ההודעות שנשלחות בין תהליכים בתור ההודעות של הזיכרון המשותף צריכות להיות בעלות פריסת זיכרון זהה בין גבולות התהליכים, ולא יכולות להכיל מצביעים. ניסיון ליצור AidlMessageQueue עם סוג שלא נתמך יגרום לשגיאת קומפילציה.

סוגי תורים נתמכים

‫AIDL תומך באותם סוגי תורים מ-HIDL, שלעתים קרובות נקראים flavors. הם משמשים כארגומנטים של תבניות לתורים ולתיאורים.

סוגי HIDL סוגי AIDL
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

איך משתמשים

מגדירים את ממשק ה-AIDL שיעביר את MQDescriptor לתהליך השני. אפשר להשתמש ב-MQDescriptor בכל מקום שבו אפשר להשתמש ב-Parcelable.

הארגומנטים הנדרשים של התבנית MQDescriptor הם סוג המטען הייעודי (payload) וסוג התור.

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. כל ממשקי ה-API שמתוארים במאמר בנושא שימוש ב-MessageQueue נתמכים באופן מלא ב-AidlMessageQueue, מלבד מקרה אחד:

const MQDescriptor<T, flavor>* getDesc() מוחלף ב-MQDescriptor<T, U> dupeDesc() שמחזיר את AIDL MQDescriptor.