תור הודעות מהיר באמצעות AIDL

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

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

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

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

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

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

איך משתמשים

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

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

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