Быстрая очередь сообщений с AIDL

Начиная с Android 12, Fast Message Queue можно использовать с интерфейсами AIDL с использованием серверной части NDK. Это позволяет процессам взаимодействовать без накладных расходов и ограничений транзакций связывания после некоторой короткой настройки. Использование Stable AIDL обеспечивает связь между системой и процессами поставщика.

Поддерживаемые типы полезной нагрузки

Сообщения, отправляемые между процессами в очереди сообщений общей памяти, должны иметь одинаковую структуру памяти для всех процессов и не могут содержать указатели. Попытка создать AidlMessageQueue с типом, который не поддерживается, приведет к ошибке компиляции.

Поддерживаемые типы очередей

AIDL поддерживает те же типы очередей из HIDL, которые часто называют вариантами. Они используются в качестве аргументов шаблона для очередей и дескрипторов.

Типы HIDL Типы AIDL
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

Как использовать

Определите интерфейс AIDL, который будет передавать MQDescriptor другому процессу. MQDescriptor можно использовать везде, где может находиться земельный участок.

Обязательными аргументами шаблона для MQDescriptor являются тип полезных данных и вариант очереди.

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

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

Процесс настройки каждой стороны очереди сообщений почти идентичен процессу с использованием HIDL , только с использованием типов 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);

Принимающий процесс создаст другую сторону очереди с дескриптором, полученным от интерфейса 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()) {
   ...
}

Использование AidlMessageQueue после установки аналогично использованию HIDL MessageQueue . Все API, описанные в разделе «Использование MessageQueue», полностью поддерживаются AidlMessageQueue за одним исключением:

const MQDescriptor<T, flavor>* getDesc() заменяется на MQDescriptor<T, U> dupeDesc() который возвращает AIDL MQDescriptor .