Od Androida 12 można używać szybkiej kolejki wiadomości z interfejsami AIDL korzystającymi z backendu NDK. Umożliwia to procesom komunikowanie się bez obciążenia i ograniczeń transakcji binderowych po krótkiej konfiguracji. Korzystanie ze stabilnego AIDL umożliwia komunikację między procesami systemowymi i procesami dostawcy.
Obsługiwane typy ładunków
FixedSizetypy AIDLparcelable(niedostępne w backendziecpp)- Typy AIDL
union(niedostępne w backendziecpp) - Typy AIDL
enum - Typy AIDL integral
Wiadomości wysyłane między procesami w kolejce wiadomości w pamięci współdzielonej muszą mieć ten sam układ pamięci w obrębie granic procesu i nie mogą zawierać wskaźników. Próba utworzenia AidlMessageQueue z typem, który nie jest obsługiwany, powoduje błąd kompilacji. Typów AIDL parcelable i union w backendzie cpp nie można używać z szybką kolejką wiadomości, ponieważ dziedziczą one po android::Parcelable, która ma funkcje wirtualne.
Obsługiwane typy kolejek
W AIDL są obsługiw101ane te same typy kolejek co w HIDL, często nazywane wariantami. 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 przekazuje MQDescriptor do innego procesu. MQDescriptor można używać wszędzie tam, gdzie można używać typu parcelable.
Wymagane argumenty szablonu dla MQDescriptor to typ ładunku i wariant 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 wiadomości jest prawie identyczny z procesem korzystającym z 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 odbierający tworzy drugą stronę kolejki za pomocą deskryptora otrzymanego 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 MessageQueue HIDL.
Wszystkie interfejsy API opisane w sekcji Korzystanie z MessageQueue są w pełni obsługiwane
przez AidlMessageQueue z jednym wyjątkiem:
const MQDescriptor<T, flavor>* getDesc() jest zastępowany przez MQDescriptor<T, U> dupeDesc()
który zwraca AIDL MQDescriptor.