Schnelle Nachrichtenwarteschlange mit AIDL

Ab Android 12 kann die Schnellnachrichtenwarteschlange mit AIDL-Schnittstellen über das NDK-Backend verwendet werden. Dadurch können Prozesse nach einer kurzen Einrichtung ohne den Aufwand und die Einschränkungen von Binder-Transaktionen kommunizieren. Die Verwendung von Stable AIDL ermöglicht die Kommunikation zwischen System- und Anbieterprozessen.

Unterstützte Nutzlasttypen

Die zwischen Prozessen in der geteilten Speichernachrichtenwarteschlange gesendeten Nachrichten müssen über Prozessgrenzen hinweg dasselbe Speicherlayout haben und dürfen keine Verweise enthalten. Der Versuch, eine AidlMessageQueue mit einem nicht unterstützten Typ zu erstellen, führt zu einem Kompilierungsfehler.

Unterstützte Warteschlangentypen

Die gleichen Warteschlangentypen aus HIDL, häufig als Flavors bezeichnet, werden von AIDL unterstützt. Diese 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 die MQDescriptor an den anderen Prozess übergeben wird. MQDescriptor kann überall dort verwendet werden, wo ein Paket möglich ist.

Die erforderlichen Vorlagenargumente für MQDescriptor sind „Nutzlasttyp“ und „Queue-Variante“.

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

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

Der Vorgang zum Einrichten der beiden Seiten der Nachrichtenwarteschlange ist fast identisch mit dem Prozess mit HIDL, nur mit den AIDL-Typen.

#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 Empfangsprozess erstellt die andere Seite der Warteschlange mit dem von der AIDL-Schnittstelle empfangenen Deskriptor.

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 der HIDL-MessageQueue. Alle unter MessageQueue verwenden beschriebenen APIs werden mit einer Ausnahme vollständig von AidlMessageQueue unterstützt:

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