Coda di messaggi rapida con AIDL

A partire da Android 12, la coda di messaggi rapida può essere utilizzata con le interfacce AIDL utilizzando il backend NDK. In questo modo, le procedure possono comunicare senza il sovraccarico e le limitazioni delle transazioni dei binder dopo una breve configurazione. L'utilizzo di Stable AIDL consente la comunicazione tra i processi del sistema e del fornitore.

Tipi di payload supportati

I messaggi inviati tra i processi nella coda di messaggi della memoria condivisa devono avere lo stesso layout della memoria nei confini dei processi e non possono contenere puntatori. Il tentativo di creare un AidlMessageQueue con un tipo non supportato causerà un errore di compilazione.

Tipi di coda supportati

Gli stessi tipi di coda di HIDL, spesso chiamati "flavor", sono supportati da AIDL. Questi vengono utilizzati come argomenti del modello per le code e i descrittori.

Tipi HIDL Tipi di AIDL
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

Modalità di utilizzo

Definisci l'interfaccia AIDL che trasmette MQDescriptor all'altro processo. MQDescriptor può essere utilizzato ovunque sia possibile utilizzare un parcelable.

Gli argomenti del modello obbligatori per MQDescriptor sono il tipo di payload e il tipo di coda.

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

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

La procedura di configurazione di ciascun lato della coda dei messaggi è quasi identica al procedura che utilizza HIDL, ma utilizza i tipi 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);

Il processo di ricezione creerà l'altro lato della coda con il descrittore ricevuto dall'interfaccia 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()) {
   ...
}

L'utilizzo di AidlMessageQueue dopo la configurazione è lo stesso di MessageQueue HIDL. Tutte le API descritte in Utilizzo di MessageQueue sono completamente supportate con AidlMessageQueue, ad eccezione di una:

const MQDescriptor<T, flavor>* getDesc() viene sostituito da MQDescriptor<T, U> dupeDesc() che restituisce l'AIDL MQDescriptor.