快速消息队列与 AIDL

从 Android 12 开始,快速消息队列可与采用 NDK 后端的 AIDL 接口搭配使用。这样一来,在进行简短的设置后,进程之间便可进行通信,无需任何开销,对 Binder 事务也没有任何限制。使用稳定的 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 相同。 使用 AidlMessageQueue 时,使用 MessageQueue 中介绍的所有 API 都完全受支持,但有一种例外情况:

const MQDescriptor<T, flavor>* getDesc() 已替换为 MQDescriptor<T, U> dupeDesc(),后者会返回 AIDL MQDescriptor