从 Android 12 开始,快速消息队列可与采用 NDK 后端的 AIDL 接口搭配使用。这样一来,在进行简短的设置后,进程之间便可进行通信,无需任何开销,对 Binder 事务也没有任何限制。使用稳定的 AIDL 可实现系统与供应商各进程之间的通信。
支持的载荷类型
- @FixedSize AIDL
parcelable
类型 - AIDL
enum
类型 - 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
。