No Android 12, 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 binder após uma configuração curta. Usar a AIDL estável permite a comunicação entre processos do sistema e do fornecedor.
Tipos de payload compatíveis
- Tipos
FixedSizeAIDLparcelable(não disponíveis no back-endcpp) - Tipos
unionda AIDL (não disponíveis no back-endcpp) - Tipos
enumdo AIDL - Tipos integrais do 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 não compatível causa um erro de compilação. Os tipos parcelable e union do AIDL
no back-end cpp não podem ser usados com a fila de mensagens rápidas porque herdam
de android::Parcelable, que tem funções virtuais.
Tipos de filas compatíveis
Os mesmos tipos de fila do HIDL, geralmente chamados de variantes, são compatíveis com o 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 transmite o MQDescriptor para o outro
processo. MQDescriptor pode ser usado em qualquer lugar em que um parcelable possa ser usado.
Os argumentos de modelo obrigatórios para MQDescriptor são o tipo de payload e o sabor da 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 cria 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()) {
...
}
Usar o AidlMessageQueue após a configuração é o mesmo que o HIDL MessageQueue.
Todas as APIs descritas em Usar o MessageQueue são totalmente compatíveis
com AidlMessageQueue, com uma exceção:
const MQDescriptor<T, flavor>* getDesc() foi substituído por MQDescriptor<T, U> dupeDesc()
que retorna o AIDL MQDescriptor.