使用 AIDL 快速將訊息排入佇列

自 Android 12 起,快速訊息佇列可搭配使用 NDK 後端的 AIDL 介面。這樣一來,處理程序 完全不會因繫結器交易而產生的負擔和限制 一些簡單的設定使用 Stable AIDL 可在系統和 以及供應商處理程序

支援的酬載類型

共用記憶體訊息佇列中的程序之間傳送的訊息必須相同 跨程序邊界的記憶體配置,而且不能包含指標。如果嘗試建立 AidlMessageQueue 與不支援的類型會導致編譯錯誤。

支援的佇列類型

HIDL 中的相同佇列類型 (通常為) AIDL 也支援各種方法這些函式會做為 佇列和描述元

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,有一個例外狀況:

const MQDescriptor<T, flavor>* getDesc()」已由「MQDescriptor<T, U> dupeDesc()」取代 會傳回 AIDL MQDescriptor