Fila de mensagens rápida com AIDL

A partir do Android 12, o Fast Message Queue pode ser usado 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 do binder após uma breve configuração. O uso do Stable AIDL permite a comunicação entre os processos do sistema e do fornecedor.

Tipos de carga suportados

As mensagens enviadas entre processos na fila de mensagens de memória compartilhada devem ter o mesmo layout de memória entre os limites do processo e não podem conter ponteiros. A tentativa de criar um AidlMessageQueue com um tipo que não tem suporte causará um erro de compilação.

Tipos de filas compatíveis

Os mesmos tipos de fila do HIDL, geralmente chamados de variações, são suportados pelo AIDL. Eles são usados ​​como argumentos de modelo para filas e descritores.

Tipos 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 passará o MQDescriptor para o outro processo. MQDescriptor pode ser usado em qualquer lugar que possa ser parcelado.

Os argumentos de modelo necessários para MQDescriptor são tipo de carga útil e 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 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()) {
   ...
}

Usar o AidlMessageQueue após a configuração é o mesmo que o HIDL MessageQueue . Todas as APIs descritas em Usando o MessageQueue são totalmente suportadas pelo AidlMessageQueue , com uma exceção:

const MQDescriptor<T, flavor>* getDesc() é substituído por MQDescriptor<T, U> dupeDesc() que retorna o AIDL MQDescriptor .