AIDL による高速メッセージ キュー

Android 12 以降、NDK バックエンドを使用して AIDL で高速メッセージ キューを使用できます。高速メッセージ キューを使用すると、簡単なセットアップの後、バインダー トランザクションのオーバーヘッドや制限なく、プロセス間で通信を行えるようになります。安定版 AIDL を使用すると、システム プロセスとベンダー プロセス間の通信が可能になります。

サポートされているペイロードの型

共有メモリ メッセージ キュー内のプロセス間で送信されるメッセージの場合、プロセスの境界にかかわらずメモリ レイアウトを同一にする必要があり、ポインタを設定することはできません。サポートされていない型で AidlMessageQueue を作成しようとすると、コンパイル エラーとなります。

サポートされているキューの型

AIDL でサポートされているキューの型(フレーバー)は、HIDL と同じです。これらのキューの型は、キューと記述子のテンプレート引数として使用されます。

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

使用方法

MQDescriptor を他のプロセスに渡す AIDL インターフェースを定義します。MQDescriptor は、Parcelable を使用できる場所であればどこでも使用できます。

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 の場合と同じです。MessageQueue の使用に記載されているすべての API は、AidlMessageQueue で完全にサポートされますが、下記の例外が 1 つあります。

const MQDescriptor<T, flavor>* getDesc() は、AIDL MQDescriptor を返す MQDescriptor<T, U> dupeDesc() に置き換えられます。