Ab Android 12 kann Fast Message Queue mit AIDL-Schnittstellen über das NDK-Backend verwendet werden. So können Prozesse nach einer kurzen Einrichtung ohne den Overhead und die Einschränkungen von Binder-Transaktionen kommunizieren. Durch die Verwendung von stabilem AIDL ist die Kommunikation zwischen System- und Anbieterprozessen möglich.
Unterstützte Nutzlasttypen
FixedSizeAIDLparcelable-Typen (nicht über dascpp-Backend verfügbar)- AIDL
union-Typen (nicht über dascpp-Backend verfügbar) - AIDL
enum-Typen - AIDL-Ganzzahltypen
Die Nachrichten, die zwischen Prozessen in der Message Queue des gemeinsamen Speichers gesendet werden, müssen über Prozessgrenzen hinweg dasselbe Speicherlayout haben und dürfen keine Zeiger enthalten. Wenn Sie versuchen, eine AidlMessageQueue mit einem nicht unterstützten Typ zu erstellen, tritt ein Kompilierungsfehler auf. Die AIDL-Typen parcelable und union im cpp-Backend können nicht mit Fast Message Queue verwendet werden, da sie von android::Parcelable abgeleitet werden, das virtuelle Funktionen hat.
Unterstützte Warteschlangentypen
Dieselben Warteschlangentypen aus HIDL, oft auch als Varianten bezeichnet, werden mit AIDL unterstützt. Sie werden als Vorlagenargumente für die Warteschlangen und Deskriptoren verwendet.
| HIDL-Typen | AIDL-Typen |
|---|---|
android::hardware::kSynchronizedReadWrite |
android.hardware.common.fmq.SynchronizedReadWrite |
android::hardware::kUnsynchronizedWrite |
android.hardware.common.fmq.UnsynchronizedWrite |
Verwendung
Definieren Sie die AIDL-Schnittstelle, die den MQDescriptor an den anderen Prozess übergibt. MQDescriptor kann überall verwendet werden, wo ein Parcelable verwendet werden kann.
Die erforderlichen Vorlagenargumente für MQDescriptor sind der Nutzlasttyp und die Warteschlangenvariante.
import android.hardware.common.fmq.MQDescriptor
import android.hardware.common.fmq.SynchronizedReadWrite
void getQueue(out MQDescriptor<int, SynchronizedReadWrite> mqDesc);
Die Einrichtung der einzelnen Seiten der Message Queue ist fast identisch mit dem Prozess mit HIDL. Es werden lediglich die AIDL-Typen verwendet.
#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);
Der empfangende Prozess erstellt die andere Seite der Warteschlange mit dem Deskriptor, der von der AIDL-Schnittstelle empfangen wurde.
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()) {
...
}
Die Verwendung von AidlMessageQueue nach der Einrichtung ist dieselbe wie bei MessageQueue von HIDL.
Alle in MessageQueue verwenden beschriebenen APIs werden vollständig unterstützt
mit AidlMessageQueue Eine Ausnahme:
const MQDescriptor<T, flavor>* getDesc() wird durch MQDescriptor<T, U> dupeDesc()
ersetzt, das den AIDL-MQDescriptor zurückgibt.