Schnelle Nachrichtenwarteschlange mit AIDL

Ab Android 12 kann Fast Message Queue mit AIDL-Schnittstellen mit dem NDK-Backend verwendet werden. So können Prozesse nach einer kurzen Einrichtung ohne den Overhead und die Einschränkungen von Binder-Transaktionen kommunizieren. Mit Stable AIDL kann die Kommunikation zwischen System- und Anbieterprozessen erfolgen.

Unterstützte Nutzlasttypen

Die Nachrichten, die zwischen Prozessen in der Shared-Memory-Nachrichtenwarteschlange gesendet werden, müssen über Prozessgrenzen hinweg dasselbe Speicherlayout haben und dürfen keine Zeiger enthalten. Wenn Sie versuchen, ein AidlMessageQueue mit einem nicht unterstützten Typ zu erstellen, tritt ein Kompilierungsfehler auf.

Unterstützte Warteschlangentypen

Dieselben Warteschlangentypen aus HIDL, die oft als Varianten bezeichnet werden, 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, über die MQDescriptor an den anderen Prozess übergeben wird. MQDescriptor kann überall verwendet werden, wo ein Parcelable verwendet werden kann.

Die erforderlichen Vorlagenargumente für MQDescriptor sind Nutzlasttyp und Warteschlangentyp.

import android.hardware.common.fmq.MQDescriptor
import android.hardware.common.fmq.SynchronizedReadWrite

void getQueue(out MQDescriptor<int, SynchronizedReadWrite> mqDesc);

Das Einrichten der einzelnen Seiten der Message Queue ist fast identisch mit dem Prozess mit HIDL, nur dass die AIDL-Typen verwendet werden.

#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);

Beim Empfangsprozess wird die andere Seite der Warteschlange mit dem Deskriptor erstellt, der über die 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 entspricht dem HIDL MessageQueue. Alle unter MessageQueue verwenden beschriebenen APIs werden von AidlMessageQueue vollständig unterstützt. Eine Ausnahme:

const MQDescriptor<T, flavor>* getDesc() wird durch MQDescriptor<T, U> dupeDesc() ersetzt, das die AIDL MQDescriptor zurückgibt.