AIDL을 사용한 빠른 메시지 큐

Android 12부터 NDK 백엔드를 사용하는 AIDL 인터페이스와 함께 빠른 메시지 큐를 사용할 수 있습니다. 따라서 간단한 설정 후 프로세스가 바인더 트랜잭션의 오버헤드 및 제한 없이 통신할 수 있습니다. 안정적 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);

메시지 큐의 각 측면을 설정하는 프로세스는 AIDL 유형을 사용하는 것만으로도 HIDL을 사용하는 프로세스와 거의 동일합니다.

#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()는 AIDL MQDescriptor를 반환하는 MQDescriptor<T, U> dupeDesc()로 대체됩니다.