No Android 12 e versões mais recentes, a Fila de mensagens rápidas pode ser usada com interfaces AIDL usando o back-end do NDK. Isso permite que os processos se comuniquem sem a sobrecarga e as restrições das transações de vinculação após uma configuração curta. O uso da AIDL estável permite a comunicação entre os processos do sistema e do fornecedor.
Tipos de payload aceitos
- Tipos
parcelable
da AIDL @FixedSize - Tipos
enum
de AIDL - Tipos integrais AIDL
As mensagens enviadas entre processos na fila de mensagens de memória compartilhada precisam ter o mesmo
layout de memória em todos os limites de processo e não podem conter ponteiros. Tentar criar um
AidlMessageQueue
com um tipo que não tem suporte vai causar um erro de compilação.
Tipos de filas com suporte
Os mesmos tipos de fila da HIDL, muitas vezes chamados de sabores, são compatíveis com a AIDL. Eles são usados como argumentos de modelo para as filas e os descritores.
Tipos de HIDL | Tipos de AIDL |
---|---|
android::hardware::kSynchronizedReadWrite |
android.hardware.common.fmq.SynchronizedReadWrite |
android::hardware::kUnsynchronizedWrite |
android.hardware.common.fmq.UnsynchronizedWrite |
Como usar
Defina a interface AIDL que transmitirá o MQDescriptor
para o outro processo.
MQDescriptor
pode ser usado em qualquer lugar onde um parcelável possa ser usado.
Os argumentos de modelo obrigatórios para MQDescriptor
são o tipo de payload e o tipo de fila.
import android.hardware.common.fmq.MQDescriptor
import android.hardware.common.fmq.SynchronizedReadWrite
void getQueue(out MQDescriptor<int, SynchronizedReadWrite> mqDesc);
O processo de configuração de cada lado da fila de mensagens é quase idêntico ao processo usando HIDL, apenas usando os tipos 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);
O processo de recebimento vai criar o outro lado da fila com o descritor recebido da interface 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()) {
...
}
O uso do AidlMessageQueue
após a configuração é o mesmo que o MessageQueue
do HIDL.
Todas as APIs descritas em Como usar a MessageQueue
têm suporte total com AidlMessageQueue
, com uma exceção:
const MQDescriptor<T, flavor>* getDesc()
foi substituído por MQDescriptor<T, U> dupeDesc()
,
que retorna o MQDescriptor
da AIDL.