File d'attente des messages rapide avec AIDL

Depuis Android 12, Fast Message Queue peut être utilisé avec des interfaces AIDL à l'aide du backend NDK. Cela permet aux processus de communiquer sans les frais généraux ni les restrictions des transactions de binder après une courte configuration. L'utilisation d'AIDL stable permet la communication entre les processus système et fournisseur.

Types de charge utile compatibles

  • FixedSize Types AIDL parcelable (non disponibles à partir du backend cpp)
  • Types union AIDL (non disponibles à partir du backend cpp)
  • Types enum AIDL
  • Types intégraux AIDL

Les messages envoyés entre les processus dans la file d'attente de messages de mémoire partagée doivent avoir la même disposition de mémoire sur les limites des processus et ne peuvent pas contenir de pointeurs. Toute tentative de création d'un AidlMessageQueue avec un type non compatible entraîne une erreur de compilation. Les types parcelable et union AIDL dans le backend cpp ne peuvent pas être utilisés avec Fast Message Queue, car ils héritent de android::Parcelable, qui comporte des fonctions virtuelles.

Types de files d'attente compatibles

Les mêmes types de files d'attente que dans HIDL, souvent appelés "flavors", sont compatibles avec AIDL. Ils sont utilisés comme arguments de modèle pour les files d'attente et les descripteurs.

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

Utilisation

Définissez l'interface AIDL qui transmet le MQDescriptor à l'autre processus. MQDescriptor peut être utilisé partout où un parcelable peut l'être.

Les arguments de modèle requis pour MQDescriptor sont le type de charge utile et le flavor de la file d'attente.

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

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

Le processus de configuration de chaque côté de la file d'attente de messages est presque identique à celui qui utilise HIDL, mais avec les types 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);

Le processus de réception crée l'autre côté de la file d'attente avec le descripteur reçu de l'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()) {
   ...
}

L'utilisation de AidlMessageQueue après la configuration est identique à celle de MessageQueue HIDL. Toutes les API décrites dans Utiliser MessageQueue sont entièrement compatibles avec AidlMessageQueue à une exception près :

const MQDescriptor<T, flavor>* getDesc() est remplacé par MQDescriptor<T, U> dupeDesc() qui renvoie l'AIDL MQDescriptor.