Coda di messaggi rapida con AIDL

A partire da Android 12, la coda di messaggi rapidi può essere utilizzata con le interfacce AIDL mediante il backend NDK. Ciò consente ai processi comunicare senza i costi generali e le restrizioni delle transazioni binder dopo alcune brevi configurazioni. L'utilizzo di AIDL stabile consente la comunicazione tra il sistema e i processi 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 oltre i confini del processo e non può contenere puntatori. Stai tentando di creare AidlMessageQueue con un tipo non supportato causerà un errore di compilazione.

Tipi di coda supportati

Gli stessi tipi di coda delle linee HIDL, spesso chiamati flavor, sono supportati con AIDL. Queste vengono usate come argomenti del modello per le code e i descrittori.

Tipi di 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 passerà il valore MQDescriptor all'altro processo. MQDescriptor può essere utilizzato ovunque possa essere un pacchetto.

Gli argomenti del modello richiesti per MQDescriptor sono il tipo di payload e la versione di coda.

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

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

Il processo di configurazione di ciascun lato della coda di messaggi è quasi identico a elaborare l'immagine con l'HIDL, usando solo 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 del dispositivo HIDL MessageQueue. Tutte le API descritte in Utilizzo di MessageQueue sono completamente supportati con AidlMessageQueue con una sola eccezione:

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