自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
快速消息队列与 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
。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-26。"],[],[],null,["# Fast Message Queue with AIDL\n\nAs of Android 12, [Fast Message Queue](/docs/core/architecture/hidl/fmq) can be\nused with AIDL interfaces using the NDK backend. This allows processes to\ncommunicate without the overhead and restrictions of binder transactions after\nsome short setup. Using [Stable AIDL](/docs/core/architecture/aidl/stable-aidl) allows communication between system and\nvendor processes.\n\nSupported payload types\n-----------------------\n\n- [@FixedSize](/docs/core/architecture/aidl/aidl-annotations#fixedsize) AIDL `parcelable` types\n- AIDL `enum` types\n- [AIDL integral types](/docs/core/architecture/aidl/aidl-backends#types)\n\nThe messages sent between processes in the shared memory message queue must have the same\nmemory layout across process boundaries and cannot contain pointers. Attempting to create an\n`AidlMessageQueue` with a type that isn't supported will cause a compilation error.\n\nSupported queue types\n---------------------\n\nThe same [queue types](/docs/core/architecture/hidl/fmq#flavors) from HIDL, often\ncalled flavors, are supported with AIDL. These are used as template arguments for\nthe queues and descriptors.\n\n| HIDL Types | AIDL Types |\n|---------------------------------------------|-----------------------------------------------------|\n| `android::hardware::kSynchronizedReadWrite` | `android.hardware.common.fmq.SynchronizedReadWrite` |\n| `android::hardware::kUnsynchronizedWrite` | `android.hardware.common.fmq.UnsynchronizedWrite` |\n\nHow to use\n----------\n\nDefine the AIDL interface that will pass the `MQDescriptor` to the other process.\n`MQDescriptor` can be used anywhere a parcelable can be.\n\nThe required template arguments for `MQDescriptor` are payload type and queue flavor. \n\n import android.hardware.common.fmq.MQDescriptor\n import android.hardware.common.fmq.SynchronizedReadWrite\n\n void getQueue(out MQDescriptor\u003cint, SynchronizedReadWrite\u003e mqDesc);\n\nThe process of setting up each side of the message queue is nearly identical to\nthe [process using HIDL](/docs/core/architecture/hidl/fmq#setup), just using the AIDL types. \n\n #include \u003cfmq/AidlMessageQueue.h\u003e\n ...\n using ::android::AidlMessageQueue;\n using ::aidl::android::hardware::common::fmq::MQDescriptor;\n using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;\n ...\n ndk::ScopedAStatus MyInterface::getQueue(MQDescriptor\u003cint32_t, SynchronizedReadWrite\u003e* mqDesc) {\n *mqDesc = mFmqSynchronized-\u003edupeDesc();\n return ndk::ScopedAStatus::ok();\n }\n ...\n // Create the first side of the queue before servicing getQueue() in this example\n mFmqSynchronized =\n new AidlMessageQueue\u003cint32_t, SynchronizedReadWrite\u003e(kNumElementsInQueue);\n\nThe receiving process will create the other side of the queue with the descriptor received from the AIDL interface. \n\n MQDescriptor\u003cint32_t, SynchronizedReadWrite\u003e desc;\n auto ret = service-\u003egetQueue(true, &desc);\n if (!ret.isOk()) {\n ...\n }\n // By default the constructor will reset the read and write pointers of the queue.\n // Add a second `false` argument to avoid resetting the pointers.\n mQueue = new (std::nothrow) AidlMessageQueue\u003cint32_t, SynchronizedReadWrite\u003e(desc);\n if (!mQueue-\u003eisValid()) {\n ...\n }\n\nUsing the `AidlMessageQueue` after setup is the same as the HIDL `MessageQueue`.\nAll of the APIs described at [Using the MessageQueue](/docs/core/architecture/hidl/fmq#using)\nare fully supported with `AidlMessageQueue` with one exception:\n\n`const MQDescriptor\u003cT, flavor\u003e* getDesc()` is replaced by `MQDescriptor\u003cT, U\u003e dupeDesc()`\nwhich returns the AIDL `MQDescriptor`."]]