Fast Message Queue עם AIDL

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

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

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

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

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

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

איך משתמשים

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

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

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