إذا كنت تبحث عن دعم AIDL، يمكنك أيضًا FMQ مع AIDL
تستخدم البنية الأساسية لاستدعاء الإجراء عن بُعد (RPC) في HIDL آليات Binder، مما يعني أن الاتصالات تتضمن أعباء عامة وتتطلب عمليات نواة وقد تؤدي إجراء الجدولة. ومع ذلك، في الحالات التي يجب فيها نقل البيانات بين بأقل عبء أو مشاركة في النواة، فإن قائمة انتظار الرسائل السريعة (FMQ).
ينشئ FMQ قوائم انتظار الرسائل باستخدام الخصائص المطلوبة. إنّ
يمكن استخدام الكائن MQDescriptorSync
أو MQDescriptorUnsync
يتم إرسالها عبر مكالمة HIDL RPC واستخدامها من قِبل عملية الاستلام للوصول إلى
قائمة انتظار الرسائل.
لا تتوفّر قوائم انتظار الرسائل السريعة إلا في لغة C++ وعلى الأجهزة. يعمل بنظام التشغيل Android 8.0 أو إصدار أحدث.
أنواع قائمة انتظار الرسائل
يتيح Android استخدام نوعَين من قوائم الانتظار (المعروفة باسم النكهات):
- يُسمح للقوائم غير المتزامنة بالتجاوز، ويمكن أن تحتوي على العديد القرّاء يجب على كل قارئ قراءة البيانات في الوقت المناسب أو فقدانها.
- لا يُسمح بالتجاوز سعة قوائم الانتظار المتزامنة، ويمكن أن تتضمن فقط قارئ واحد
لا يُسمح لكلا النوعين من قوائم الانتظار بمواصلة العمل (القراءة من قائمة انتظار فارغة). فشل) ويمكن أن يكون لها كاتب واحد فقط.
غير متزامن
تتضمن قائمة الانتظار غير المتزامنة كاتبًا واحدًا فقط، ولكن يمكن أن تحتوي على أي عدد من للقرّاء هناك موضع كتابة واحد لقائمة الانتظار؛ مع ذلك، يحتفظ كل قارئ تتبع موضع القراءة المستقل الخاص بها.
نجاح الكتابة في قائمة الانتظار دائمًا (لا يتم التحقق منها بحثًا عن وجود تجاوز) ما دامت وهي ليست أكبر من سعة قائمة الانتظار المهيأة (تكتب بحجم أكبر من تفشل سعة قائمة الانتظار على الفور). ولأنّ كل قارئ قد يكون له قراءة مختلفة بدلاً من انتظار أن يقرأ كل قارئ كل جزء من البيانات يُسمح له بالسقوط خارج قائمة الانتظار كلما احتاجت عمليات الكتابة الجديدة إلى مساحة.
القراء هم مسئولون عن استرداد البيانات قبل أن تخرج من نهاية قائمة الانتظار. يشير هذا المصطلح إلى عملية قراءة تحاول قراءة بيانات أكثر من المتاحة. يتوقف على الفور (إذا كان لا يؤدي إلى الحظر) أو ينتظر توفير بيانات كافية (إذا حظر). يشير هذا المصطلح إلى قراءة تحاول قراءة بيانات أكبر من سعة قائمة الانتظار دائمًا. فشل على الفور.
إذا فشل القارئ في متابعة الكاتب، بحيث تكون كمية البيانات التي يكتبها ذلك القارئ ولم يقرأها بعد يتجاوز سعة قائمة الانتظار، القراءة التالية لا تُرجع البيانات؛ بل يعيد ضبط قراءة موضعًا يساوي آخر موضع كتابة ثم يعرض الفشل. إذا كانت يتم التحقق من البيانات المتاحة للقراءة بعد تجاوز السعة ولكن قبل القراءة التالية، تعرض بيانات متوفرة للقراءة أكثر من سعة قائمة الانتظار، مما يشير إلى حدث الفائض. (إذا كانت قائمة الانتظار تتجاوز التحقق من البيانات المتاحة ومحاولة قراءة تلك البيانات، فإن المؤشر الوحيد على تجاوز القيمة هو أن فشلت القراءة.)
من المحتمل ألا يريد قرّاء قائمة الانتظار غير المتزامنة إعادة ضبط مؤشرات القراءة والكتابة لقائمة الانتظار. لذلك، عند إنشاء قائمة الانتظار من يجب أن يستخدم قرّاء الواصف الوسيطة "false" في "resetPointers" .
متزامن
تتضمّن قائمة المحتوى التالي المتزامنة كاتبًا واحدًا وقارئًا واحدًا يتضمّن كتابة واحدة. موضعًا وموضع قراءة واحد. من المستحيل كتابة بيانات أكثر من تحتوي قائمة الانتظار على مساحة أو تقرأ بيانات أكثر مما تحتفظ به قائمة الانتظار حاليًا. اعتمادًا على ما إذا كانت دالة المنع أو القراءة أو التي لا تحظر يحاول تجاوز المساحة المتوفرة أو فشل إرجاع البيانات فورًا أو منعه حتى يتم إكمال العملية المطلوبة. محاولات يخفق دائمًا على الفور قراءة أو كتابة بيانات أكثر من سعة قائمة الانتظار.
إعداد جهاز FMQ
تتطلّب لائحة الرسائل عدة كائنات MessageQueue
: واحد
أن تتم كتابتها إليه وواحدة أو أكثر لتتم قراءتها منها. لا توجد موسيقى فاضحة
تحديد الكائن المستخدَم للكتابة أو القراءة الأمر يعود إلى
المستخدم للتأكد من عدم استخدام أي كائن للقراءة والكتابة، وأن
كاتب واحد على الأكثر، وفي قوائم الانتظار المتزامنة، أنه يوجد واحد
قارئ البطاقات.
إنشاء أول كائن Messageplaylist
يتم إنشاء قائمة انتظار الرسائل وإعدادها بمكالمة واحدة:
#include <fmq/MessageQueue.h> using android::hardware::kSynchronizedReadWrite; using android::hardware::kUnsynchronizedWrite; using android::hardware::MQDescriptorSync; using android::hardware::MQDescriptorUnsync; using android::hardware::MessageQueue; .... // For a synchronized non-blocking FMQ mFmqSynchronized = new (std::nothrow) MessageQueue<uint16_t, kSynchronizedReadWrite> (kNumElementsInQueue); // For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite> (kNumElementsInQueue, true /* enable blocking operations */);
- أداة إعداد "
MessageQueue<T, flavor>(numElements)
" ينشئ ويهيئ كائنًا يدعم وظيفة قائمة انتظار الرسائل. - ينشئ جهاز إعداد "
MessageQueue<T, flavor>(numElements, configureEventFlagWord)
" عنصرًا ويضبطه. يتوافق مع وظيفة قائمة انتظار الرسائل مع الحظر. - يمكن أن تكون قيمة الحقل "
flavor
" إماkSynchronizedReadWrite
قائمة انتظار متزامنة أوkUnsynchronizedWrite
لقائمة غير متزامنة قائمة الانتظار. - يمكن أن يكون
uint16_t
(في هذا المثال) أي نوع محدد HIDL الذي لا تتضمن مخازن مؤقتة متداخلة (لا تتضمنstring
أوvec
وأنواعها أو مقابضها أو واجهاتها. - تشير السمة
kNumElementsInQueue
إلى حجم قائمة الانتظار بعدد الإدخالات يحدد حجم المخزن المؤقت المشترك المخصص للذاكرة لقائمة الانتظار.
إنشاء كائن Messageplaylist الثاني
يتم إنشاء الجانب الثاني من قائمة انتظار الرسائل باستخدام
الكائن MQDescriptor
الذي تم الحصول عليه من الجانب الأول. تشير رسالة الأشكال البيانية
تم إرسال عنصر واحد (MQDescriptor
) من خلال استدعاء HIDL أو AIDL RPC إلى العملية.
تحتوي على الطرف الثاني من قائمة انتظار الرسائل. تشير رسالة الأشكال البيانية
يتضمن MQDescriptor
معلومات حول قائمة الانتظار، بما في ذلك:
- معلومات لتعيين المخزن المؤقت وكتابة المؤشر
- معلومات لربط مؤشر القراءة (إذا تمت مزامنة قائمة الانتظار)
- معلومات لتعيين كلمة علامة الحدث (إذا كانت قائمة الانتظار محظورة)
- نوع الكائن (
<T, flavor>
)، والذي يتضمّن نوع محدد HIDL من عناصر قائمة الانتظار ونكهة قائمة الانتظار (متزامنة أو غير متزامنة).
يمكن استخدام الكائن MQDescriptor
لإنشاء
كائن MessageQueue
:
MessageQueue<T, flavor>::MessageQueue(const MQDescriptor<T, flavor>& Desc, bool resetPointers)
تحدّد مَعلمة resetPointers
ما إذا كان يجب إعادة ضبط القراءة.
واكتب المواضع على 0 أثناء إنشاء هذا الكائن MessageQueue
.
في قائمة انتظار غير متزامنة، يكون موضع القراءة (المحلي لكل منها)
يتم دائمًا ضبط الكائن MessageQueue
في قوائم الانتظار غير المتزامنة) على القيمة 0.
أثناء عملية الإنشاء يتم عادةً إعداد MQDescriptor
أثناء
إنشاء أول كائن قائمة انتظار الرسائل. لمزيد من التحكم في البيانات المشتركة،
يمكنك إعداد MQDescriptor
يدويًا
(يتم تحديد MQDescriptor
في
system/libhidl/base/include/hidl/MQDescriptor.h
)
ثم إنشاء كل كائن MessageQueue
كما هو موضح في هذا القسم.
حظر قوائم الانتظار وعلامات الأحداث
حسب الإعدادات التلقائية، لا تتيح قوائم الانتظار حظر عمليات القراءة/الكتابة. هناك نوعان حظر استدعاءات القراءة/الكتابة:
- الصيغة القصيرة، تتضمن ثلاث معلَمات (مؤشر البيانات، عدد العناصر،
المهلة). يتيح الحظر في عمليات القراءة/الكتابة الفردية على
قائمة الانتظار. عند استخدام هذا النموذج، تتعامل قائمة الانتظار مع علامة الحدث وأقنعة البت
داخليًا، ويجب أن يكون كائن قائمة انتظار الرسالة الأولى
باستخدام المعلمة الثانية
true
. مثل:// For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite> (kNumElementsInQueue, true /* enable blocking operations */);
- الصيغة الطويلة، تتضمّن ست مَعلمات (بما في ذلك علامات الحدث وأقنعة البت).
تتيح استخدام عنصر
EventFlag
مشترك بين قوائم انتظار متعدّدة. ويسمح بتحديد أقنعة بت الإشعار المراد استخدامها. في هذه الحالة، يجب تقديم علامة الحدث وأقنعة البت لكل استدعاء قراءة وكتابة.
وبالنسبة إلى النموذج الطويل، يمكن تقديم EventFlag
صراحةً في
كل مكالمة readBlocking()
وwriteBlocking()
. أحد
قد تتم تهيئة قوائم الانتظار بعلامة حدث داخلية، والتي يجب
تم استخلاصها من كائنات MessageQueue
في قائمة الانتظار هذه باستخدام
تم استخدام getEventFlagWord()
لإنشاء EventFlag
.
في كل عملية لاستخدامها مع FMQs الأخرى. بدلاً من ذلك،
يمكن إعداد EventFlag
عنصرًا باستخدام أي عناصر مشتركة مناسبة
الذاكرة.
بشكل عام، يجب أن تستخدم كل قائمة انتظار واحدة فقط من الأشكال القصيرة أو حظر المحتوى أو حظر المحتوى الطويل ليس من الخطأ مزجها، ولكن كن حذرًا البرمجة مطلوبة للحصول على النتيجة المرجوّة.
وضع علامة "للقراءة فقط" على الذكرى
تمتلك الذاكرة المشتركة أذونات القراءة والكتابة تلقائيًا. غير المتزامنة
قوائم الانتظار (kUnsynchronizedWrite
)، قد يحتاج الكاتب إلى إزالة أذونات الكتابة لجميع
القرّاء قبل توزيع عناصر MQDescriptorUnsync
. يضمن ذلك عدم وجود
لا يمكن للعمليات الكتابة في قائمة الانتظار، وهو ما يوصى به للحماية من الأخطاء أو السلوك السيئ في
عمليات القارئ.
إذا أراد الكاتب أن يتمكن القراء من إعادة تعيين قائمة الانتظار عندما استخدموا
MQDescriptorUnsync
لإنشاء جانب القراءة من قائمة الانتظار، ثم لا يمكن وضع علامة على الذكرى
للقراءة فقط. هذا هو السلوك الافتراضي للدالة الإنشائية `Messageplaylist`. لذلك، إذا كان هناك بالفعل
المستخدمين الحاليين في قائمة الانتظار هذه، يجب تغيير الكود الخاص بهم لإنشاء قائمة الانتظار باستخدام
resetPointer=false
- كاتب: طلب
ashmem_set_prot_region
باستخدام واصف ملفMQDescriptor
والمنطقة التي تم ضبطها للقراءة فقط (PROT_READ
):int res = ashmem_set_prot_region(mqDesc->handle->data[0], PROT_READ)
- القارئ: إنشاء قائمة انتظار رسائل باستخدام
resetPointer=false
( القيمة التلقائية هيtrue
):mFmq = new (std::nothrow) MessageQueue(mqDesc, false);
استخدام قائمة انتظار الرسائل
واجهة برمجة التطبيقات العامة للعنصر MessageQueue
هي:
size_t availableToWrite() // Space available (number of elements). size_t availableToRead() // Number of elements available. size_t getQuantumSize() // Size of type T in bytes. size_t getQuantumCount() // Number of items of type T that fit in the FMQ. bool isValid() // Whether the FMQ is configured correctly. const MQDescriptor<T, flavor>* getDesc() // Return info to send to other process. bool write(const T* data) // Write one T to FMQ; true if successful. bool write(const T* data, size_t count) // Write count T's; no partial writes. bool read(T* data); // read one T from FMQ; true if successful. bool read(T* data, size_t count); // Read count T's; no partial reads. bool writeBlocking(const T* data, size_t count, int64_t timeOutNanos = 0); bool readBlocking(T* data, size_t count, int64_t timeOutNanos = 0); // Allows multiple queues to share a single event flag word std::atomic<uint32_t>* getEventFlagWord(); bool writeBlocking(const T* data, size_t count, uint32_t readNotification, uint32_t writeNotification, int64_t timeOutNanos = 0, android::hardware::EventFlag* evFlag = nullptr); // Blocking write operation for count Ts. bool readBlocking(T* data, size_t count, uint32_t readNotification, uint32_t writeNotification, int64_t timeOutNanos = 0, android::hardware::EventFlag* evFlag = nullptr) // Blocking read operation for count Ts; //APIs to allow zero copy read/write operations bool beginWrite(size_t nMessages, MemTransaction* memTx) const; bool commitWrite(size_t nMessages); bool beginRead(size_t nMessages, MemTransaction* memTx) const; bool commitRead(size_t nMessages);
يمكن استخدام availableToWrite()
وavailableToRead()
.
لتحديد مقدار البيانات التي يمكن نقلها في عملية واحدة. في
قائمة انتظار غير متزامنة:
- تعرض الدالة
availableToWrite()
دائمًا سعة قائمة الانتظار. - لكل قارئ موضع قراءة خاص به ويقوم بعمليته الحسابية
availableToRead()
- من منظور القارئ البطيء، يُسمَح بعرض قائمة الانتظار بالتجاوز.
قد يؤدي ذلك إلى عرض
availableToRead()
لقيمة أكبر من حجم قائمة الانتظار. القراءة الأولى بعد فشل التجاوز وينتج عن ذلك موضع القراءة لهذا القارئ الذي يتم ضبطه على قيمة مساوية لمؤشر الكتابة الحالي، ما إذا كان تم الإبلاغ عن التجاوز من خلالavailableToRead()
تعرض الطريقتان read()
وwrite()
true
إذا كان من الممكن نقل جميع البيانات المطلوبة (ونقلها) من/إلى
قائمة الانتظار. وهذه الطرق لا تحظر إما أن تنجح (وترجع
true
) أو تعذُّر عملية الإرجاع (false
) على الفور.
تنتظر الطريقتان readBlocking()
وwriteBlocking()
حتى اكتمال العملية المطلوبة أو إلى أن تنتهي مهلتها (
تعني قيمة timeOutNanos
التي قيمتها 0 عدم انتهاء المهلة أبدًا).
يتم تنفيذ عمليات الحظر باستخدام كلمة علامة حدث. بشكل افتراضي،
تنشئ كل قائمة انتظار وتستخدم كلمة العلامة الخاصة بها لدعم الشكل المختصَر
"readBlocking()
" وwriteBlocking()
" من الممكن
قوائم انتظار متعددة لمشاركة كلمة واحدة، بحيث يمكن للعملية الانتظار حتى عمليات الكتابة أو
إلى أي من قوائم الانتظار. يمكن أن يكون المؤشر الذي تشير إلى كلمة علامة حدث في قائمة انتظار
تم الحصول عليه من خلال استدعاء getEventFlagWord()
، وهذا المؤشر (أو أي
يشير إلى موقع ذاكرة مشترك مناسب) يمكن استخدامه لإنشاء
كائن EventFlag
لتمريره إلى الشكل الطويل من
readBlocking()
وwriteBlocking()
لاختيار
قائمة الانتظار. readNotification
وwriteNotification
تخبر المعلمات وحدات البت في علامة الحدث التي يجب استخدامها للإشارة إلى القراءات
ويكتب في تلك القائمة. readNotification
و
writeNotification
هي أقنعة بت ذات 32 بت.
ينتظر readBlocking()
على writeNotification
بت؛
إذا كانت هذه المعلمة هي 0، يفشل الاستدعاء دائمًا. إذا كانت
قيمة readNotification
هي 0، ويتعذَّر الاتصال، ولكن
القراءة الناجحة لن يؤدي إلى تعيين أي وحدات بت للإشعارات. في قائمة انتظار متزامنة،
فهذا يعني أنّ طلب writeBlocking()
المقابل
لا يستيقظ أبدًا ما لم يتم تعيين البت في مكان آخر. في قائمة انتظار غير متزامنة،
لا ينتظر "writeBlocking()
" (يجب أن يتم استخدامه لضبط
وكتابة بت الإشعار)، ومن المناسب أن لا يتم تعيين أي
وحدات بت الإشعارات. وبالمثل، يتعذّر تنفيذ writeblocking()
في حال
readNotification
هي 0، وتضبط الكتابة الناجحة القيم المحددة
writeNotification
بت.
للانتظار في قوائم انتظار متعددة في الوقت نفسه، يُرجى استخدام عنصر EventFlag
wait()
طريقة للانتظار على قناع الإشعارات. تشير رسالة الأشكال البيانية
تُرجع طريقة wait()
كلمة حالة تتضمن وحدات البت التي تسببت في
ميزة الاستيقاظ. يتم بعد ذلك استخدام هذه المعلومات للتحقق من احتواء قائمة الانتظار المقابلة على
مساحة أو بيانات كافية لعملية الكتابة/القراءة المطلوبة
لا يحظر write()
/read()
. للحصول على عملية نشر
يُرجى استخدام مكالمة أخرى مع رقم EventFlag
wake()
. للاطّلاع على تعريف السمة EventFlag
التجريد، راجع
system/libfmq/include/fmq/EventFlag.h
عمليات عدم نسخ البيانات
تشير رسالة الأشكال البيانية
read
/write
/readBlocking
/writeBlocking()
تنقل واجهات برمجة التطبيقات مؤشرًا إلى مخزن مؤقت للإدخال/الإخراج كوسيطة وتستخدم
memcpy()
يتصل داخليًا لنسخ البيانات بين
المخزن المؤقت لحلقة FMQ لتحسين الأداء، يتضمن الإصدار 8.0 من نظام التشغيل Android والإصدارات الأحدث مجموعة من
توفر واجهات برمجة التطبيقات التي توفر الدخول المباشر للمؤشر إلى المخزن المؤقت الدائري،
بحاجة إلى استخدام مكالمات memcpy
.
يمكنك استخدام واجهات برمجة التطبيقات العامة التالية لإجراء عمليات FMQ بدون نسخة:
bool beginWrite(size_t nMessages, MemTransaction* memTx) const; bool commitWrite(size_t nMessages); bool beginRead(size_t nMessages, MemTransaction* memTx) const; bool commitRead(size_t nMessages);
- توفّر الطريقة
beginWrite
مؤشرات أساسية في حلقة FMQ. المورد الاحتياطي. بعد كتابة البيانات، عليك الالتزام بها باستخدامcommitWrite()
. تعمل الطريقتانbeginRead
/commitRead
بالطريقة نفسها. - يتم استخدام الطريقتَين
beginRead
/Write
كإدخال عدد الرسائل المراد قراءتها/كتابتها وعرض قيمة منطقية تشير إلى ما إذا كانت القراءة/الكتابة ممكنة. إذا كانت القراءة أو الكتابة ممكنةmemTx
تتمّ تعبئة البنية بالمؤشرات الأساسية التي يمكن استخدامها للمؤشر المباشر. الوصول إلى الذاكرة المشتركة للمخزن المؤقت الدائري. - تحتوي البنية
MemRegion
على تفاصيل حول كتلة من الذاكرة، بما في ذلك المؤشر الأساسي (العنوان الأساسي لكتلة الذاكرة) والطول في مصطلحT
(طول كتلة الذاكرة من حيث تحديد HIDL قائمة انتظار الرسائل). - تحتوي بنية
MemTransaction
علىMemRegion
التراكيب،first
وsecond
كقراءة أو كتابة قد يتطلب المخزن المؤقت الدائري التفافًا حتى بداية قائمة الانتظار. هذا النمط أن هناك حاجة إلى مؤشرين أساسيين لقراءة/كتابة البيانات في FMQ المخزن المؤقت للرنين.
للحصول على العنوان الأساسي والطول من بنية MemRegion
:
T* getAddress(); // gets the base address size_t getLength(); // gets the length of the memory region in terms of T size_t getLengthInBytes(); // gets the length of the memory region in bytes
للحصول على إشارات إلى أول وثانيتَين MemRegion
داخل
كائن MemTransaction
:
const MemRegion& getFirstRegion(); // get a reference to the first MemRegion const MemRegion& getSecondRegion(); // get a reference to the second MemRegion
مثال على الكتابة في FMQ باستخدام واجهات برمجة التطبيقات المتاحة بدون نسخ:
MessageQueueSync::MemTransaction tx; if (mQueue->beginRead(dataLen, &tx)) { auto first = tx.getFirstRegion(); auto second = tx.getSecondRegion(); foo(first.getAddress(), first.getLength()); // method that performs the data write foo(second.getAddress(), second.getLength()); // method that performs the data write if(commitWrite(dataLen) == false) { // report error } } else { // report error }
تشكّل طرق المساعدة التالية جزءًا من MemTransaction
أيضًا:
T* getSlot(size_t idx);
عرض مؤشر في موضعidx
داخلMemRegions
التي تشكّل جزءًا منMemTransaction
الخاص بك. إذا كان الكائنMemTransaction
يمثّل الذكرى مناطق لقراءة/كتابة عدد N من العناصر من النوع T، ثم النطاق الصالحidx
بين 0 وN-1.bool copyTo(const T* data, size_t startIdx, size_t nMessages = 1);
كتابةnMessages
عنصر من النوع T في مناطق الذاكرة يصفها الكائن، بدءًا من الفهرسstartIdx
. هذه الطريقة يستخدمmemcpy()
ولا يهدف إلى استخدامه في نسخة الصفر العملية. إذا كان العنصرMemTransaction
يمثّل الذاكرة قراءة/كتابة عدد N من العناصر من النوع T، فإن النطاق الصالح لـidx
هو بين 0 وN-1.bool copyFrom(T* data, size_t startIdx, size_t nMessages = 1);
طريقة مساعِدة لقراءةnMessages
عنصر من النوع T من مناطق الذاكرة التي يصفها الكائن بدءًا منstartIdx
. هذا النمط تستخدم الطريقةmemcpy()
ولا يُقصد استخدامها العملية.
إرسال قائمة المحتوى التالي عبر HIDL
بالنسبة إلى صناعة المحتوى:
- أنشئ كائن قائمة انتظار الرسائل كما هو موضّح أعلاه.
- تحقَّق من صلاحية العنصر من خلال
isValid()
. - إذا كنت تنتظر في عدة قوائم انتظار من خلال تمرير
EventFlag
في الصيغة الطويلة منreadBlocking()
/writeBlocking()
، يمكنك استخراج مؤشر علامة الحدث (باستخدامgetEventFlagWord()
) منMessageQueue
الكائن الذي تم إعداده لإنشاء العلامة واستخدِم هذه العلامة لإنشاء كائنEventFlag
اللازم. - استخدِم طريقة
MessageQueue
getDesc()
للحصول على واصف البيانات. - في ملف
.hal
، أدخِل مَعلمة من النوع للطريقة.fmq_sync
أوfmq_unsync
حيثT
نوع مناسب محدد HIDL. استخدم هذا الخيار لإرسال الكائن الذي تم إرجاعه بواسطةgetDesc()
إلى عملية الاستلام.
على الجانب المستقبِل:
- استخدِم كائن الوصف لإنشاء كائن
MessageQueue
. كن فتأكد من استخدام نفس صيغة قائمة الانتظار ونوع البيانات، وإلا فسيفشل القالب تجميع. - إذا كنت قد استخرجت علامة حدث، استخرج العلامة من العلامة
عنصر واحد (
MessageQueue
) قيد الاستلام. - استخدِم عنصر
MessageQueue
لنقل البيانات.