Szybka kolejka wiadomości z AIDL

Od Androida 12 szybka kolejka wiadomości może być używana z interfejsami AIDL za pomocą backendu NDK. Umożliwia to procesom komunikowanie się bez obciążenia i ograniczeń transakcji Binder po krótkiej konfiguracji. Korzystanie ze stabilnego AIDL umożliwia komunikację między procesami systemowymi a procesami dostawcy.

Obsługiwane typy ładunków

Wiadomości wysyłane między procesami w kolejce wiadomości pamięci współdzielonej muszą mieć ten sam układ pamięci w różnych procesach i nie mogą zawierać wskaźników. Próba utworzenia elementu AidlMessageQueue o typie, który nie jest obsługiwany, spowoduje błąd kompilacji.

Obsługiwane typy kolejek

W AIDL obsługiwane są te same typy kolejek z HIDL, często nazywane wersjami. Są one używane jako argumenty szablonu dla kolejek i deskryptorów.

Typy HIDL Typy AIDL
android::hardware::kSynchronizedReadWrite android.hardware.common.fmq.SynchronizedReadWrite
android::hardware::kUnsynchronizedWrite android.hardware.common.fmq.UnsynchronizedWrite

Instrukcje korzystania

Zdefiniuj interfejs AIDL, który przekaże MQDescriptor do innego procesu. MQDescriptor można używać wszędzie tam, gdzie można używać obiektu Parcelable.

Wymagane argumenty szablonu dla funkcji MQDescriptor to typ ładunku i rodzaj kolejki.

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

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

Proces konfigurowania każdej strony kolejki komunikatów jest niemal identyczny z procesem z użyciem HIDL, tylko z użyciem typów 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);

Proces odbierania utworzy drugą stronę kolejki z deskryptorem otrzymanym z interfejsu 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()) {
   ...
}

Korzystanie z AidlMessageQueue po konfiguracji jest takie samo jak w przypadku HIDL MessageQueue. Wszystkie interfejsy API opisane w artykule Korzystanie z kolejki komunikatów są w pełni obsługiwane w przypadku AidlMessageQueue z jednym wyjątkiem:

const MQDescriptor<T, flavor>* getDesc() jest zastępowany przez MQDescriptor<T, U> dupeDesc() który zwraca AIDL MQDescriptor.