A partire da Android 12, la coda di messaggi veloce (FMQ) può essere utilizzata con le interfacce AIDL utilizzando il backend NDK. In questo modo, i processi possono comunicare senza il sovraccarico e le limitazioni delle transazioni binder dopo una breve configurazione. L'utilizzo di AIDL stabile consente la comunicazione tra i processi di sistema e del fornitore.
Tipi di payload supportati
FixedSizetipi AIDLparcelable(non disponibili dal backendcpp)- Tipi di
unionAIDL (non disponibili dal backendcpp) - Tipi di
enumAIDL - Tipi integrali AIDL
I messaggi inviati tra i processi nella coda di messaggi della memoria condivisa devono avere lo stesso layout di memoria tra i limiti dei processi e non possono contenere puntatori. Il tentativo di creare un AidlMessageQueue con un tipo non supportato causa un errore di compilazione. I tipi parcelable e union AIDL nel backend cpp non possono essere utilizzati con la coda di messaggi veloce perché ereditano da android::Parcelable, che ha funzioni virtuali.
Tipi di coda supportati
Con AIDL sono supportati gli stessi tipi di coda di HIDL, spesso chiamati flavor. Questi vengono utilizzati come argomenti di modello per le code e i descrittori.
| Tipi HIDL | Tipi 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 passa MQDescriptor all'altro processo. MQDescriptor può essere utilizzato ovunque sia possibile utilizzare un parcelable.
Gli argomenti di modello richiesti per MQDescriptor sono il tipo di payload e il flavor della 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 ogni lato della coda di messaggi è quasi identica a la 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 crea 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 Utilizzare MessageQueue sono completamente supportate
con AidlMessageQueue con una sola eccezione:
const MQDescriptor<T, flavor>* getDesc() viene sostituito da
MQDescriptor<T, U> dupeDesc()
che restituisce l'AIDL MQDescriptor.