從 Android 12 開始,快速訊息佇列可以與使用 NDK 後端的 AIDL 介面一起使用。這允許進程在進行一些簡短的設定後進行通信,而無需綁定器事務的開銷和限制。使用穩定的 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
。