Adding AidlMessageQueue

This adds an AIDL compatible version of MessageQueue that returns an
AIDL parcelable to be passed between processes. The returned parcelable
is used to create a new instance of the MessageQueue.

Tests were run on 32-bit Cuttlefish as well as 64-bit Flame device.

Test: atest fmq_unit_tests && system/tools/hidl/test/run_all_device_tests.sh
Bug: 142326204

Change-Id: I0fac5065c6d5d0686aa6fd48ca1109417246718c
diff --git a/Android.bp b/Android.bp
index e2cb961..3930742 100644
--- a/Android.bp
+++ b/Android.bp
@@ -31,6 +31,12 @@
     ],
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
+    header_libs: [
+        "libfmq-base",
+    ],
+    export_header_lib_headers: [
+        "libfmq-base",
+    ],
     srcs: [
         "EventFlag.cpp",
         "FmqInternal.cpp",
@@ -48,3 +54,18 @@
     double_loadable: true,
     min_sdk_version: "29",
 }
+
+// Header only lib to share type between HIDL and AIDL MQDescriptor
+cc_library_headers {
+    name: "libfmq-base",
+    host_supported: true,
+    vendor_available: true,
+    native_bridge_supported: true,
+    recovery_available: true,
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
+    export_include_dirs: ["base"],
+    min_sdk_version: "29",
+}
diff --git a/base/fmq/MQDescriptorBase.h b/base/fmq/MQDescriptorBase.h
new file mode 100644
index 0000000..8d49bc8
--- /dev/null
+++ b/base/fmq/MQDescriptorBase.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <assert.h>
+
+namespace android {
+namespace hardware {
+
+enum MQFlavor : uint32_t {
+    /*
+     * kSynchronizedReadWrite represents the wait-free synchronized flavor of the
+     * FMQ. It is intended to be have a single reader and single writer.
+     * Attempts to overflow/underflow returns a failure.
+     */
+    kSynchronizedReadWrite = 0x01,
+    /*
+     * kUnsynchronizedWrite represents the flavor of FMQ where writes always
+     * succeed. This flavor allows one writer and many readers. A read operation
+     * can detect an overwrite and reset the read counter.
+     */
+    kUnsynchronizedWrite = 0x02
+};
+
+namespace details {
+
+typedef uint64_t RingBufferPosition;
+enum GrantorType : int { READPTRPOS = 0, WRITEPTRPOS, DATAPTRPOS, EVFLAGWORDPOS };
+/*
+ * There should at least be GrantorDescriptors for the read counter, write
+ * counter and data buffer. A GrantorDescriptor for an EventFlag word is
+ * not required if there is no need for blocking FMQ operations.
+ */
+static constexpr int32_t kMinGrantorCount = DATAPTRPOS + 1;
+
+/*
+ * Minimum number of GrantorDescriptors required if EventFlag support is
+ * needed for blocking FMQ operations.
+ */
+static constexpr int32_t kMinGrantorCountForEvFlagSupport = EVFLAGWORDPOS + 1;
+
+static inline size_t alignToWordBoundary(size_t length) {
+    constexpr size_t kAlignmentSize = 64;
+    if (kAlignmentSize % __WORDSIZE != 0) {
+#ifdef __BIONIC__
+        __assert(__FILE__, __LINE__, "Incompatible word size");
+#endif
+    }
+
+    /*
+     * Check if alignment to word boundary would cause an overflow.
+     */
+    if (length > SIZE_MAX - kAlignmentSize / 8 + 1) {
+#ifdef __BIONIC__
+        __assert(__FILE__, __LINE__, "Queue size too large");
+#endif
+    }
+
+    return (length + kAlignmentSize / 8 - 1) & ~(kAlignmentSize / 8 - 1U);
+}
+
+static inline size_t isAlignedToWordBoundary(size_t offset) {
+    constexpr size_t kAlignmentSize = 64;
+    return (offset & (kAlignmentSize / 8 - 1)) == 0;
+}
+
+}  // namespace details
+}  // namespace hardware
+}  // namespace android
diff --git a/include/fmq/AidlMQDescriptorShim.h b/include/fmq/AidlMQDescriptorShim.h
new file mode 100644
index 0000000..aad5be3
--- /dev/null
+++ b/include/fmq/AidlMQDescriptorShim.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/hardware/common/MQDescriptor.h>
+#include <cutils/native_handle.h>
+#include <fmq/MQDescriptorBase.h>
+
+using aidl::android::hardware::common::GrantorDescriptor;
+using aidl::android::hardware::common::MQDescriptor;
+using android::hardware::MQFlavor;
+
+namespace android {
+namespace details {
+
+template <typename T, MQFlavor flavor>
+struct AidlMQDescriptorShim {
+    // Takes ownership of handle
+    AidlMQDescriptorShim(const MQDescriptor& desc);
+
+    // Takes ownership of handle
+    AidlMQDescriptorShim(size_t bufferSize, native_handle_t* nHandle, size_t messageSize,
+                         bool configureEventFlag = false);
+
+    explicit AidlMQDescriptorShim(const AidlMQDescriptorShim& other)
+        : AidlMQDescriptorShim(0, nullptr, 0) {
+        *this = other;
+    }
+    AidlMQDescriptorShim& operator=(const AidlMQDescriptorShim& other);
+
+    ~AidlMQDescriptorShim();
+
+    size_t getSize() const;
+
+    size_t getQuantum() const;
+
+    int32_t getFlags() const;
+
+    bool isHandleValid() const { return mHandle != nullptr; }
+    size_t countGrantors() const { return mGrantors.size(); }
+
+    inline const std::vector<GrantorDescriptor>& grantors() const { return mGrantors; }
+
+    inline const ::native_handle_t* handle() const { return mHandle; }
+
+    inline ::native_handle_t* handle() { return mHandle; }
+
+    static const size_t kOffsetOfGrantors;
+    static const size_t kOffsetOfHandle;
+
+  private:
+    std::vector<GrantorDescriptor> mGrantors;
+    native_handle_t* mHandle = nullptr;
+    int32_t mQuantum = 0;
+    int32_t mFlags = 0;
+};
+
+template <typename T, MQFlavor flavor>
+AidlMQDescriptorShim<T, flavor>::AidlMQDescriptorShim(const MQDescriptor& desc)
+    : mQuantum(desc.quantum), mFlags(desc.flags) {
+    mHandle = native_handle_create(1 /* num fds */, 0 /* num ints */);
+    mHandle->data[0] = dup(desc.fileDescriptor.get());
+
+    mGrantors.resize(desc.grantors.size());
+    for (size_t i = 0; i < desc.grantors.size(); ++i) {
+        mGrantors[i] = desc.grantors[i];
+    }
+}
+
+template <typename T, MQFlavor flavor>
+AidlMQDescriptorShim<T, flavor>& AidlMQDescriptorShim<T, flavor>::operator=(
+        const AidlMQDescriptorShim& other) {
+    mGrantors = other.mGrantors;
+    if (mHandle != nullptr) {
+        native_handle_close(mHandle);
+        native_handle_delete(mHandle);
+        mHandle = nullptr;
+    }
+    mQuantum = other.mQuantum;
+    mFlags = other.mFlags;
+
+    if (other.mHandle != nullptr) {
+        mHandle = native_handle_create(other.mHandle->numFds, other.mHandle->numInts);
+
+        for (int i = 0; i < other.mHandle->numFds; ++i) {
+            mHandle->data[i] = dup(other.mHandle->data[i]);
+        }
+
+        memcpy(&mHandle->data[other.mHandle->numFds], &other.mHandle->data[other.mHandle->numFds],
+               static_cast<size_t>(other.mHandle->numInts) * sizeof(int));
+    }
+
+    return *this;
+}
+
+template <typename T, MQFlavor flavor>
+AidlMQDescriptorShim<T, flavor>::AidlMQDescriptorShim(size_t bufferSize, native_handle_t* nHandle,
+                                                      size_t messageSize, bool configureEventFlag) {
+    mHandle = nHandle;
+    mQuantum = messageSize;
+    mFlags = flavor;
+    /*
+     * If configureEventFlag is true, allocate an additional spot in mGrantor
+     * for containing the fd and offset for mmapping the EventFlag word.
+     */
+    mGrantors.resize(configureEventFlag ? hardware::details::kMinGrantorCountForEvFlagSupport
+                                        : hardware::details::kMinGrantorCount);
+
+    size_t memSize[] = {
+            sizeof(hardware::details::RingBufferPosition), /* memory to be allocated for read
+                                                            * pointer counter
+                                                            */
+            sizeof(hardware::details::RingBufferPosition), /* memory to be allocated for write
+                                                     pointer counter */
+            bufferSize,                   /* memory to be allocated for data buffer */
+            sizeof(std::atomic<uint32_t>) /* memory to be allocated for EventFlag word */
+    };
+
+    /*
+     * Create a default grantor descriptor for read, write pointers and
+     * the data buffer. fdIndex parameter is set to 0 by default and
+     * the offset for each grantor is contiguous.
+     */
+    for (size_t grantorPos = 0, offset = 0; grantorPos < mGrantors.size();
+         offset += memSize[grantorPos++]) {
+        mGrantors[grantorPos] = {
+                0 /* grantor flags */, 0 /* fdIndex */,
+                static_cast<int32_t>(hardware::details::alignToWordBoundary(offset)),
+                static_cast<int64_t>(memSize[grantorPos])};
+    }
+}
+
+template <typename T, MQFlavor flavor>
+AidlMQDescriptorShim<T, flavor>::~AidlMQDescriptorShim() {
+    if (mHandle != nullptr) {
+        native_handle_close(mHandle);
+        native_handle_delete(mHandle);
+    }
+}
+
+template <typename T, MQFlavor flavor>
+size_t AidlMQDescriptorShim<T, flavor>::getSize() const {
+    return mGrantors[hardware::details::DATAPTRPOS].extent;
+}
+
+template <typename T, MQFlavor flavor>
+size_t AidlMQDescriptorShim<T, flavor>::getQuantum() const {
+    return mQuantum;
+}
+
+template <typename T, MQFlavor flavor>
+int32_t AidlMQDescriptorShim<T, flavor>::getFlags() const {
+    return mFlags;
+}
+
+template <typename T, MQFlavor flavor>
+std::string toString(const AidlMQDescriptorShim<T, flavor>& q) {
+    std::string os;
+    if (flavor & hardware::kSynchronizedReadWrite) {
+        os += "fmq_sync";
+    }
+    if (flavor & hardware::kUnsynchronizedWrite) {
+        os += "fmq_unsync";
+    }
+    os += " {" + toString(q.grantors().size()) + " grantor(s), " +
+          "size = " + toString(q.getSize()) + ", .handle = " + toString(q.handle()) +
+          ", .quantum = " + toString(q.getQuantum()) + "}";
+    return os;
+}
+
+}  // namespace details
+}  // namespace android
diff --git a/include/fmq/AidlMessageQueue.h b/include/fmq/AidlMessageQueue.h
new file mode 100644
index 0000000..f650442
--- /dev/null
+++ b/include/fmq/AidlMessageQueue.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/common/MQDescriptor.h>
+#include <cutils/native_handle.h>
+#include <fmq/AidlMQDescriptorShim.h>
+#include <fmq/MessageQueueBase.h>
+#include <utils/Log.h>
+
+using aidl::android::hardware::common::MQDescriptor;
+using android::details::AidlMQDescriptorShim;
+using android::hardware::MQFlavor;
+
+namespace android {
+
+typedef uint64_t RingBufferPosition;
+
+template <typename T, MQFlavor flavor>
+struct AidlMessageQueue final : public MessageQueueBase<AidlMQDescriptorShim, T, flavor> {
+    typedef AidlMQDescriptorShim<T, flavor> Descriptor;
+    /**
+     * This constructor uses the external descriptor used with AIDL interfaces.
+     * It will create an FMQ based on the descriptor that was obtained from
+     * another FMQ instance for communication.
+     *
+     * @param desc Descriptor from another FMQ that contains all of the
+     * information required to create a new instance of that queue.
+     * @param resetPointers Boolean indicating whether the read/write pointers
+     * should be reset or not.
+     */
+    AidlMessageQueue(const MQDescriptor& desc, bool resetPointers = true);
+    ~AidlMessageQueue() = default;
+
+    /**
+     * This constructor uses Ashmem shared memory to create an FMQ
+     * that can contain a maximum of 'numElementsInQueue' elements of type T.
+     *
+     * @param numElementsInQueue Capacity of the AidlMessageQueue in terms of T.
+     * @param configureEventFlagWord Boolean that specifies if memory should
+     * also be allocated and mapped for an EventFlag word.
+     */
+    AidlMessageQueue(size_t numElementsInQueue, bool configureEventFlagWord = false);
+    MQDescriptor dupeDesc();
+
+  private:
+    AidlMessageQueue(const AidlMessageQueue& other) = delete;
+    AidlMessageQueue& operator=(const AidlMessageQueue& other) = delete;
+    AidlMessageQueue() = delete;
+};
+
+template <typename T, MQFlavor flavor>
+AidlMessageQueue<T, flavor>::AidlMessageQueue(const MQDescriptor& desc, bool resetPointers)
+    : MessageQueueBase<AidlMQDescriptorShim, T, flavor>(Descriptor(desc), resetPointers) {}
+
+template <typename T, MQFlavor flavor>
+AidlMessageQueue<T, flavor>::AidlMessageQueue(size_t numElementsInQueue,
+                                              bool configureEventFlagWord)
+    : MessageQueueBase<AidlMQDescriptorShim, T, flavor>(numElementsInQueue,
+                                                        configureEventFlagWord) {}
+
+template <typename T, MQFlavor flavor>
+MQDescriptor AidlMessageQueue<T, flavor>::dupeDesc() {
+    auto* shim = MessageQueueBase<AidlMQDescriptorShim, T, flavor>::getDesc();
+    if (shim) {
+        return MQDescriptor{
+                .quantum = static_cast<int32_t>(shim->getQuantum()),
+                .grantors = shim->grantors(),
+                .flags = shim->getFlags(),
+                .fileDescriptor = ndk::ScopedFileDescriptor(dup(shim->handle()->data[0])),
+        };
+    } else {
+        return MQDescriptor();
+    }
+}
+
+}  // namespace android
diff --git a/include/fmq/MessageQueueBase.h b/include/fmq/MessageQueueBase.h
index cdd7202..49d74d6 100644
--- a/include/fmq/MessageQueueBase.h
+++ b/include/fmq/MessageQueueBase.h
@@ -24,6 +24,10 @@
 #include <atomic>
 #include <new>
 
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::kUnsynchronizedWrite;
+using android::hardware::MQFlavor;
+
 namespace android {
 
 namespace hardware {
@@ -33,8 +37,7 @@
 }  // namespace details
 }  // namespace hardware
 
-template <template <typename, hardware::MQFlavor> class MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> class MQDescriptorType, typename T, MQFlavor flavor>
 struct MessageQueueBase {
     typedef MQDescriptorType<T, flavor> Descriptor;
 
@@ -138,7 +141,7 @@
      * EventFlag bit mask 'readNotification' is is waited upon.
      *
      * This method should only be used with a MessageQueue of the flavor
-     * 'hardware::kSynchronizedReadWrite'.
+     * 'kSynchronizedReadWrite'.
      *
      * Upon a successful write, wake is called on 'writeNotification' (if
      * non-zero).
@@ -190,7 +193,7 @@
      * -If 'count' is greater than the FMQ size.
      *
      * This method should only be used with a MessageQueue of the flavor
-     * 'hardware::kSynchronizedReadWrite'.
+     * 'kSynchronizedReadWrite'.
 
      * If FMQ does not contain 'count' items, the eventFlag bit mask
      * 'writeNotification' is waited upon. Upon a successful read from the FMQ,
@@ -448,8 +451,7 @@
     android::hardware::EventFlag* mEventFlag = nullptr;
 };
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 T* MessageQueueBase<MQDescriptorType, T, flavor>::MemTransaction::getSlot(size_t idx) {
     size_t firstRegionLength = first.getLength();
     size_t secondRegionLength = second.getLength();
@@ -465,8 +467,7 @@
     return second.getAddress() + idx - firstRegionLength;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::MemTransaction::getMemRegionInfo(
         size_t startIdx, size_t nMessages, size_t& firstCount, size_t& secondCount,
         T** firstBaseAddress, T** secondBaseAddress) {
@@ -500,8 +501,7 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::MemTransaction::copyFrom(T* data,
                                                                              size_t startIdx,
                                                                              size_t nMessages) {
@@ -532,8 +532,7 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::MemTransaction::copyTo(const T* data,
                                                                            size_t startIdx,
                                                                            size_t nMessages) {
@@ -564,22 +563,27 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 void MessageQueueBase<MQDescriptorType, T, flavor>::initMemory(bool resetPointers) {
     /*
      * Verify that the Descriptor contains the minimum number of grantors
      * the native_handle is valid and T matches quantum size.
      */
     if ((mDesc == nullptr) || !mDesc->isHandleValid() ||
-        (mDesc->countGrantors() < Descriptor::kMinGrantorCount) ||
+        (mDesc->countGrantors() < hardware::details::kMinGrantorCount) ||
         (mDesc->getQuantum() != sizeof(T))) {
         return;
     }
+    const auto& grantors = mDesc->grantors();
+    for (const auto& grantor : grantors) {
+        if (hardware::details::isAlignedToWordBoundary(grantor.offset) == false) {
+            __assert(__FILE__, __LINE__, "Grantor offsets need to be aligned");
+        }
+    }
 
-    if (flavor == hardware::kSynchronizedReadWrite) {
-        mReadPtr =
-                reinterpret_cast<std::atomic<uint64_t>*>(mapGrantorDescr(Descriptor::READPTRPOS));
+    if (flavor == kSynchronizedReadWrite) {
+        mReadPtr = reinterpret_cast<std::atomic<uint64_t>*>(
+                mapGrantorDescr(hardware::details::READPTRPOS));
     } else {
         /*
          * The unsynchronized write flavor of the FMQ may have multiple readers
@@ -590,28 +594,29 @@
 
     hardware::details::check(mReadPtr != nullptr);
 
-    mWritePtr = reinterpret_cast<std::atomic<uint64_t>*>(mapGrantorDescr(Descriptor::WRITEPTRPOS));
+    mWritePtr = reinterpret_cast<std::atomic<uint64_t>*>(
+            mapGrantorDescr(hardware::details::WRITEPTRPOS));
     hardware::details::check(mWritePtr != nullptr);
 
     if (resetPointers) {
         mReadPtr->store(0, std::memory_order_release);
         mWritePtr->store(0, std::memory_order_release);
-    } else if (flavor != hardware::kSynchronizedReadWrite) {
+    } else if (flavor != kSynchronizedReadWrite) {
         // Always reset the read pointer.
         mReadPtr->store(0, std::memory_order_release);
     }
 
-    mRing = reinterpret_cast<uint8_t*>(mapGrantorDescr(Descriptor::DATAPTRPOS));
+    mRing = reinterpret_cast<uint8_t*>(mapGrantorDescr(hardware::details::DATAPTRPOS));
     hardware::details::check(mRing != nullptr);
 
-    mEvFlagWord = static_cast<std::atomic<uint32_t>*>(mapGrantorDescr(Descriptor::EVFLAGWORDPOS));
+    mEvFlagWord =
+            static_cast<std::atomic<uint32_t>*>(mapGrantorDescr(hardware::details::EVFLAGWORDPOS));
     if (mEvFlagWord != nullptr) {
         android::hardware::EventFlag::createEventFlag(mEvFlagWord, &mEventFlag);
     }
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 MessageQueueBase<MQDescriptorType, T, flavor>::MessageQueueBase(const Descriptor& Desc,
                                                                 bool resetPointers) {
     mDesc = std::unique_ptr<Descriptor>(new (std::nothrow) Descriptor(Desc));
@@ -622,8 +627,7 @@
     initMemory(resetPointers);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 MessageQueueBase<MQDescriptorType, T, flavor>::MessageQueueBase(size_t numElementsInQueue,
                                                                 bool configureEventFlagWord) {
     // Check if the buffer size would not overflow size_t
@@ -636,7 +640,7 @@
      * we also need to allocate memory for the same/
      */
     size_t kQueueSizeBytes = numElementsInQueue * sizeof(T);
-    size_t kMetaDataSize = 2 * sizeof(android::hardware::RingBufferPosition);
+    size_t kMetaDataSize = 2 * sizeof(android::hardware::details::RingBufferPosition);
 
     if (configureEventFlagWord) {
         kMetaDataSize += sizeof(std::atomic<uint32_t>);
@@ -647,9 +651,9 @@
      * kQueueSizeBytes needs to be aligned to word boundary so that all offsets
      * in the grantorDescriptor will be word aligned.
      */
-    size_t kAshmemSizePageAligned =
-            (Descriptor::alignToWordBoundary(kQueueSizeBytes) + kMetaDataSize + PAGE_SIZE - 1) &
-            ~(PAGE_SIZE - 1);
+    size_t kAshmemSizePageAligned = (hardware::details::alignToWordBoundary(kQueueSizeBytes) +
+                                     kMetaDataSize + PAGE_SIZE - 1) &
+                                    ~(PAGE_SIZE - 1);
 
     /*
      * Create an ashmem region to map the memory for the ringbuffer,
@@ -675,58 +679,53 @@
     initMemory(true);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 MessageQueueBase<MQDescriptorType, T, flavor>::~MessageQueueBase() {
-    if (flavor == hardware::kUnsynchronizedWrite) {
+    if (flavor == kUnsynchronizedWrite) {
         delete mReadPtr;
     } else {
-        unmapGrantorDescr(mReadPtr, Descriptor::READPTRPOS);
+        unmapGrantorDescr(mReadPtr, hardware::details::READPTRPOS);
     }
     if (mWritePtr != nullptr) {
-        unmapGrantorDescr(mWritePtr, Descriptor::WRITEPTRPOS);
+        unmapGrantorDescr(mWritePtr, hardware::details::WRITEPTRPOS);
     }
     if (mRing != nullptr) {
-        unmapGrantorDescr(mRing, Descriptor::DATAPTRPOS);
+        unmapGrantorDescr(mRing, hardware::details::DATAPTRPOS);
     }
     if (mEvFlagWord != nullptr) {
-        unmapGrantorDescr(mEvFlagWord, Descriptor::EVFLAGWORDPOS);
+        unmapGrantorDescr(mEvFlagWord, hardware::details::EVFLAGWORDPOS);
         android::hardware::EventFlag::deleteEventFlag(&mEventFlag);
     }
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::write(const T* data) {
     return write(data, 1);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::read(T* data) {
     return read(data, 1);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::write(const T* data, size_t nMessages) {
     MemTransaction tx;
     return beginWrite(nMessages, &tx) && tx.copyTo(data, 0 /* startIdx */, nMessages) &&
            commitWrite(nMessages);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::writeBlocking(
         const T* data, size_t count, uint32_t readNotification, uint32_t writeNotification,
         int64_t timeOutNanos, android::hardware::EventFlag* evFlag) {
-    static_assert(flavor == hardware::kSynchronizedReadWrite,
+    static_assert(flavor == kSynchronizedReadWrite,
                   "writeBlocking can only be used with the "
-                  "hardware::kSynchronizedReadWrite flavor.");
+                  "kSynchronizedReadWrite flavor.");
     /*
      * If evFlag is null and the FMQ does not have its own EventFlag object
      * return false;
-     * If the flavor is hardware::kSynchronizedReadWrite and the readNotification
+     * If the flavor is kSynchronizedReadWrite and the readNotification
      * bit mask is zero return false;
      * If the count is greater than queue size, return false
      * to prevent blocking until timeOut.
@@ -826,21 +825,19 @@
     return result;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::writeBlocking(const T* data, size_t count,
                                                                   int64_t timeOutNanos) {
     return writeBlocking(data, count, FMQ_NOT_FULL, FMQ_NOT_EMPTY, timeOutNanos);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::readBlocking(
         T* data, size_t count, uint32_t readNotification, uint32_t writeNotification,
         int64_t timeOutNanos, android::hardware::EventFlag* evFlag) {
-    static_assert(flavor == hardware::kSynchronizedReadWrite,
+    static_assert(flavor == kSynchronizedReadWrite,
                   "readBlocking can only be used with the "
-                  "hardware::kSynchronizedReadWrite flavor.");
+                  "kSynchronizedReadWrite flavor.");
 
     /*
      * If evFlag is null and the FMQ does not own its own EventFlag object
@@ -944,33 +941,28 @@
     return result;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::readBlocking(T* data, size_t count,
                                                                  int64_t timeOutNanos) {
     return readBlocking(data, count, FMQ_NOT_FULL, FMQ_NOT_EMPTY, timeOutNanos);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::availableToWriteBytes() const {
     return mDesc->getSize() - availableToReadBytes();
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::availableToWrite() const {
     return availableToWriteBytes() / sizeof(T);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::availableToRead() const {
     return availableToReadBytes() / sizeof(T);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::beginWrite(size_t nMessages,
                                                                MemTransaction* result) const {
     /*
@@ -978,7 +970,7 @@
      * FMQ flavor, if there is not enough space to write nMessages, then return
      * result with null addresses.
      */
-    if ((flavor == hardware::kSynchronizedReadWrite && (availableToWrite() < nMessages)) ||
+    if ((flavor == kSynchronizedReadWrite && (availableToWrite() < nMessages)) ||
         nMessages > getQuantumCount()) {
         *result = MemTransaction();
         return false;
@@ -1013,8 +1005,7 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 /*
  * Disable integer sanitization since integer overflow here is allowed
  * and legal.
@@ -1032,8 +1023,7 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::availableToReadBytes() const {
     /*
      * This method is invoked by implementations of both read() and write() and
@@ -1043,16 +1033,14 @@
     return mWritePtr->load(std::memory_order_acquire) - mReadPtr->load(std::memory_order_acquire);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::read(T* data, size_t nMessages) {
     MemTransaction tx;
     return beginRead(nMessages, &tx) && tx.copyFrom(data, 0 /* startIdx */, nMessages) &&
            commitRead(nMessages);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 /*
  * Disable integer sanitization since integer overflow here is allowed
  * and legal.
@@ -1115,8 +1103,7 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 /*
  * Disable integer sanitization since integer overflow here is allowed
  * and legal.
@@ -1141,26 +1128,22 @@
     return true;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::getQuantumSize() const {
     return mDesc->getQuantum();
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 size_t MessageQueueBase<MQDescriptorType, T, flavor>::getQuantumCount() const {
     return mDesc->getSize() / mDesc->getQuantum();
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 bool MessageQueueBase<MQDescriptorType, T, flavor>::isValid() const {
     return mRing != nullptr && mReadPtr != nullptr && mWritePtr != nullptr;
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 void* MessageQueueBase<MQDescriptorType, T, flavor>::mapGrantorDescr(uint32_t grantorIdx) {
     const native_handle_t* handle = mDesc->handle();
     auto grantors = mDesc->grantors();
@@ -1191,8 +1174,7 @@
     return reinterpret_cast<uint8_t*>(address) + (grantors[grantorIdx].offset - mapOffset);
 }
 
-template <template <typename, hardware::MQFlavor> typename MQDescriptorType, typename T,
-          hardware::MQFlavor flavor>
+template <template <typename, MQFlavor> typename MQDescriptorType, typename T, MQFlavor flavor>
 void MessageQueueBase<MQDescriptorType, T, flavor>::unmapGrantorDescr(void* address,
                                                                       uint32_t grantorIdx) {
     auto grantors = mDesc->grantors();
diff --git a/tests/Android.bp b/tests/Android.bp
index 1268c2d..6cd53ec 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -30,6 +30,7 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libbinder_ndk",
     ],
 
     // Allow dlsym'ing self for statically linked passthrough implementations
@@ -37,8 +38,15 @@
 
     // These are static libs only for testing purposes and portability. Shared
     // libs should be used on device.
-    static_libs: ["android.hardware.tests.msgq@1.0"],
-    whole_static_libs: ["android.hardware.tests.msgq@1.0-impl"],
+    static_libs: [
+        "android.hardware.tests.msgq@1.0",
+        "android.fmq.test-ndk_platform",
+        "android.hardware.common-unstable-ndk_platform",
+    ],
+    whole_static_libs: [
+        "android.hardware.tests.msgq@1.0-impl",
+        "android.fmq.test-impl"
+    ],
 }
 
 cc_test {
@@ -53,6 +61,9 @@
         "liblog",
         "libutils",
     ],
+    static_libs: [
+        "android.hardware.common-unstable-ndk_platform",
+    ],
 
     cflags: [
         "-Wall",
diff --git a/tests/aidl/Android.bp b/tests/aidl/Android.bp
new file mode 100644
index 0000000..27b9827
--- /dev/null
+++ b/tests/aidl/Android.bp
@@ -0,0 +1,24 @@
+aidl_interface {
+    name: "android.fmq.test",
+    host_supported: true,
+    vendor_available: true,
+    unstable: true,
+    srcs: [
+        "android/fmq/test/*.aidl",
+    ],
+    imports: [
+        "android.hardware.common",
+    ],
+    gen_trace: true,
+    backend: {
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: true,
+        },
+        cpp: {
+            enabled: false,
+        }
+    },
+}
diff --git a/tests/aidl/android/fmq/test/EventFlagBits.aidl b/tests/aidl/android/fmq/test/EventFlagBits.aidl
new file mode 100644
index 0000000..202a67c
--- /dev/null
+++ b/tests/aidl/android/fmq/test/EventFlagBits.aidl
@@ -0,0 +1,9 @@
+// FIXME: license file if you have one
+
+package android.fmq.test;
+
+@Backing(type="int")
+enum EventFlagBits {
+    FMQ_NOT_EMPTY = 1 << 0,
+    FMQ_NOT_FULL = 1 << 1,
+}
diff --git a/tests/aidl/android/fmq/test/ITestAidlMsgQ.aidl b/tests/aidl/android/fmq/test/ITestAidlMsgQ.aidl
new file mode 100644
index 0000000..7b57e8c
--- /dev/null
+++ b/tests/aidl/android/fmq/test/ITestAidlMsgQ.aidl
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.fmq.test;
+
+import android.hardware.common.MQDescriptor;
+
+/**
+ * Test interface for MQDescriptor.
+ */
+interface ITestAidlMsgQ {
+    /**
+     * This method requests the service to set up a synchronous read/write
+     * wait-free FMQ using the input descriptor with the client as reader.
+     *
+     * @param mqDesc This structure describes the FMQ that was set up by the
+     * client. Server uses this descriptor to set up a FMQ object at its end.
+     *
+     * @return True if the setup is successful.
+     */
+    boolean configureFmqSyncReadWrite(in MQDescriptor mqDesc);
+
+    /**
+     * This method requests the service to return an MQDescriptor to
+     * an unsynchronized FMQ set up by the server. If 'configureFmq' is
+     * true, then the server sets up a new unsynchronized FMQ. This
+     * method is to be used to test multiple reader processes.
+     *
+     * @param configureFmq The server sets up a new unsynchronized FMQ if
+     * this parameter is true.
+     *
+     * @param out ret True if successful.
+     * @param out mqDesc This structure describes the unsynchronized FMQ that was
+     * set up by the service. Client can use it to set up the FMQ at its end.
+     */
+    boolean getFmqUnsyncWrite(in boolean configureFmq,
+        out MQDescriptor mqDesc);
+
+    /**
+     * This method requests the service to trigger a blocking read.
+     *
+     * @param count Number of messages to read.
+     *
+     */
+    oneway void requestBlockingRead(in int count);
+
+    /**
+     * This method requests the service to trigger a blocking read using
+     * default Event Flag notification bits defined by the MessageQueue class.
+     *
+     * @param count Number of messages to read.
+     *
+     */
+    oneway void requestBlockingReadDefaultEventFlagBits(in int count);
+
+    /**
+     * This method requests the service to repeatedly trigger blocking reads.
+     *
+     * @param count Number of messages to read in a single blocking read.
+     * @param numIter Number of blocking reads to trigger.
+     *
+     */
+    oneway void requestBlockingReadRepeat(in int count, in int numIter);
+
+    /**
+     * This method request the service to read from the synchronized read/write
+     * FMQ.
+     *
+     * @param count Number to messages to read.
+     *
+     * @return True if the read operation was successful.
+     */
+    boolean requestReadFmqSync(in int count);
+
+    /**
+     * This method request the service to read from the unsynchronized flavor of
+     * FMQ.
+     *
+     * @param count Number to messages to read.
+     *
+     * @return Will be True if the read operation was successful.
+     */
+    boolean requestReadFmqUnsync(in int count);
+
+    /**
+     * This method request the service to write into the synchronized read/write
+     * flavor of the FMQ.
+     *
+     * @param count Number to messages to write.
+     *
+     * @return True if the write operation was successful.
+     */
+    boolean requestWriteFmqSync(in int count);
+
+    /**
+     * This method request the service to write into the unsynchronized flavor
+     * of FMQ.
+     *
+     * @param count Number to messages to write.
+     *
+     * @return True if the write operation was successful.
+     */
+    boolean requestWriteFmqUnsync(in int count);
+}
diff --git a/tests/aidl/default/Android.bp b/tests/aidl/default/Android.bp
new file mode 100644
index 0000000..54660e4
--- /dev/null
+++ b/tests/aidl/default/Android.bp
@@ -0,0 +1,16 @@
+cc_library_static {
+    name: "android.fmq.test-impl",
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libfmq",
+        "android.hardware.common-unstable-ndk_platform",
+    ],
+    static_libs: [
+        "android.fmq.test-ndk_platform",
+    ],
+    export_include_dirs: ["."],
+    srcs: [
+        "TestAidlMsgQ.cpp",
+    ],
+}
diff --git a/tests/aidl/default/TestAidlMsgQ.cpp b/tests/aidl/default/TestAidlMsgQ.cpp
new file mode 100644
index 0000000..0d6153e
--- /dev/null
+++ b/tests/aidl/default/TestAidlMsgQ.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestAidlMsgQ.h"
+
+namespace aidl {
+namespace android {
+namespace fmq {
+namespace test {
+
+// Methods from ::aidl::android::fmq::test::ITestAidlMsgQ follow.
+ndk::ScopedAStatus TestAidlMsgQ::configureFmqSyncReadWrite(const MQDescriptor& mqDesc,
+                                                           bool* _aidl_return) {
+    mFmqSynchronized.reset(new (std::nothrow) TestAidlMsgQ::MessageQueueSync(mqDesc));
+    if ((mFmqSynchronized == nullptr) || (mFmqSynchronized->isValid() == false)) {
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    /*
+     * Initialize the EventFlag word with bit FMQ_NOT_FULL.
+     */
+    auto evFlagWordPtr = mFmqSynchronized->getEventFlagWord();
+    if (evFlagWordPtr != nullptr) {
+        std::atomic_init(evFlagWordPtr, static_cast<uint32_t>(EventFlagBits::FMQ_NOT_FULL));
+    }
+    *_aidl_return = true;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::getFmqUnsyncWrite(bool configureFmq, MQDescriptor* mqDesc,
+                                                   bool* _aidl_return) {
+    if (configureFmq) {
+        static constexpr size_t kNumElementsInQueue = 1024;
+        mFmqUnsynchronized.reset(new (std::nothrow)
+                                         TestAidlMsgQ::MessageQueueUnsync(kNumElementsInQueue));
+    }
+
+    if ((mFmqUnsynchronized == nullptr) || (mFmqUnsynchronized->isValid() == false) ||
+        (mqDesc == nullptr)) {
+        *_aidl_return = false;
+    } else {
+        *mqDesc = std::move(mFmqUnsynchronized->dupeDesc());
+        *_aidl_return = true;
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestBlockingRead(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->readBlocking(
+            &data[0], count, static_cast<uint32_t>(EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(EventFlagBits::FMQ_NOT_EMPTY), 5000000000 /* timeOutNanos */);
+
+    if (result == false) {
+        ALOGE("Blocking read fails");
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestBlockingReadDefaultEventFlagBits(int32_t count) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->readBlocking(&data[0], count);
+
+    if (result == false) {
+        ALOGE("Blocking read fails");
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestBlockingReadRepeat(int32_t count, int32_t numIter) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < numIter; i++) {
+        bool result = mFmqSynchronized->readBlocking(
+                &data[0], count, static_cast<uint32_t>(EventFlagBits::FMQ_NOT_FULL),
+                static_cast<uint32_t>(EventFlagBits::FMQ_NOT_EMPTY), 5000000000 /* timeOutNanos */);
+
+        if (result == false) {
+            ALOGE("Blocking read fails");
+            break;
+        }
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestReadFmqSync(int32_t count, bool* _aidl_return) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqSynchronized->read(&data[0], count) && verifyData(&data[0], count);
+    *_aidl_return = result;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestReadFmqUnsync(int32_t count, bool* _aidl_return) {
+    std::vector<uint16_t> data(count);
+    bool result = mFmqUnsynchronized->read(&data[0], count) && verifyData(&data[0], count);
+    *_aidl_return = result;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestWriteFmqSync(int32_t count, bool* _aidl_return) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < count; i++) {
+        data[i] = i;
+    }
+    bool result = mFmqSynchronized->write(&data[0], count);
+    *_aidl_return = result;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus TestAidlMsgQ::requestWriteFmqUnsync(int32_t count, bool* _aidl_return) {
+    std::vector<uint16_t> data(count);
+    for (int i = 0; i < count; i++) {
+        data[i] = i;
+    }
+    if (!mFmqUnsynchronized) {
+        ALOGE("Unsynchronized queue is not configured.");
+        *_aidl_return = false;
+        return ndk::ScopedAStatus::ok();
+    }
+    bool result = mFmqUnsynchronized->write(&data[0], count);
+    *_aidl_return = result;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace test
+}  // namespace fmq
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/aidl/default/TestAidlMsgQ.h b/tests/aidl/default/TestAidlMsgQ.h
new file mode 100644
index 0000000..92cc956
--- /dev/null
+++ b/tests/aidl/default/TestAidlMsgQ.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/fmq/test/BnTestAidlMsgQ.h>
+#include <aidl/android/fmq/test/EventFlagBits.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+
+namespace aidl {
+namespace android {
+namespace fmq {
+namespace test {
+
+using ::aidl::android::fmq::test::EventFlagBits;
+using ::aidl::android::fmq::test::ITestAidlMsgQ;
+
+using ::aidl::android::hardware::common::MQDescriptor;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::kUnsynchronizedWrite;
+using ::android::hardware::MQFlavor;
+
+using ::android::AidlMessageQueue;
+
+struct TestAidlMsgQ : public BnTestAidlMsgQ {
+    typedef AidlMessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
+    typedef AidlMessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+
+    TestAidlMsgQ() : mFmqSynchronized(nullptr), mFmqUnsynchronized(nullptr) {}
+
+    // Methods from ::aidl::android::fmq::test::ITestAidlMsgQ follow.
+    ndk::ScopedAStatus configureFmqSyncReadWrite(const MQDescriptor& mqDesc,
+                                                 bool* _aidl_return) override;
+    ndk::ScopedAStatus getFmqUnsyncWrite(bool configureFmq, MQDescriptor* mqDesc,
+                                         bool* _aidl_return) override;
+    ndk::ScopedAStatus requestBlockingRead(int32_t count) override;
+    ndk::ScopedAStatus requestBlockingReadDefaultEventFlagBits(int32_t count) override;
+    ndk::ScopedAStatus requestBlockingReadRepeat(int32_t count, int32_t numIter) override;
+    ndk::ScopedAStatus requestReadFmqSync(int32_t count, bool* _aidl_return) override;
+    ndk::ScopedAStatus requestReadFmqUnsync(int32_t count, bool* _aidl_return) override;
+    ndk::ScopedAStatus requestWriteFmqSync(int32_t count, bool* _aidl_return) override;
+    ndk::ScopedAStatus requestWriteFmqUnsync(int32_t count, bool* _aidl_return) override;
+
+  private:
+    std::unique_ptr<MessageQueueSync> mFmqSynchronized;
+    std::unique_ptr<MessageQueueUnsync> mFmqUnsynchronized;
+
+    /*
+     * Utility function to verify data read from the fast message queue.
+     */
+    bool verifyData(uint16_t* data, int count) {
+        for (int i = 0; i < count; i++) {
+            if (data[i] != i) return false;
+        }
+        return true;
+    }
+};
+
+}  // namespace test
+}  // namespace fmq
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/fmq_unit_tests.cpp b/tests/fmq_unit_tests.cpp
index 96528d3..6d8ad8b 100644
--- a/tests/fmq_unit_tests.cpp
+++ b/tests/fmq_unit_tests.cpp
@@ -15,70 +15,97 @@
  */
 
 #include <asm-generic/mman.h>
+#include <fmq/AidlMessageQueue.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
 #include <gtest/gtest.h>
 #include <atomic>
 #include <cstdlib>
 #include <sstream>
 #include <thread>
-#include <fmq/MessageQueue.h>
-#include <fmq/EventFlag.h>
+
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::kUnsynchronizedWrite;
 
 enum EventFlagBits : uint32_t {
     kFmqNotEmpty = 1 << 0,
     kFmqNotFull = 1 << 1,
 };
 
-typedef android::hardware::MessageQueue<uint8_t, android::hardware::kSynchronizedReadWrite>
-          MessageQueueSync;
-typedef android::hardware::MessageQueue<uint8_t, android::hardware::kUnsynchronizedWrite>
-            MessageQueueUnsync;
+typedef android::AidlMessageQueue<uint8_t, kSynchronizedReadWrite> AidlMessageQueueSync;
+typedef android::AidlMessageQueue<uint8_t, kUnsynchronizedWrite> AidlMessageQueueUnsync;
+typedef android::hardware::MessageQueue<uint8_t, kSynchronizedReadWrite> MessageQueueSync;
+typedef android::hardware::MessageQueue<uint8_t, kUnsynchronizedWrite> MessageQueueUnsync;
+typedef android::AidlMessageQueue<uint16_t, kSynchronizedReadWrite> AidlMessageQueueSync16;
+typedef android::hardware::MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync16;
 
-class SynchronizedReadWrites : public ::testing::Test {
-protected:
+// Run everything on both the AIDL and HIDL versions with sync and unsync flavors
+typedef ::testing::Types<AidlMessageQueueSync, MessageQueueSync> SyncTypes;
+typedef ::testing::Types<AidlMessageQueueUnsync, MessageQueueUnsync> UnsyncTypes;
+typedef ::testing::Types<AidlMessageQueueSync16, MessageQueueSync16> BadConfigTypes;
+
+template <typename T>
+class TestBase : public ::testing::Test {
+  public:
+    static void ReaderThreadBlocking(T* fmq, std::atomic<uint32_t>* fwAddr);
+    static void ReaderThreadBlocking2(T* fmq, std::atomic<uint32_t>* fwAddr);
+};
+
+TYPED_TEST_CASE(SynchronizedReadWrites, SyncTypes);
+
+template <typename T>
+class SynchronizedReadWrites : public TestBase<T> {
+  protected:
     virtual void TearDown() {
         delete mQueue;
     }
 
     virtual void SetUp() {
         static constexpr size_t kNumElementsInQueue = 2048;
-        mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue);
+        mQueue = new (std::nothrow) T(kNumElementsInQueue);
         ASSERT_NE(nullptr, mQueue);
         ASSERT_TRUE(mQueue->isValid());
         mNumMessagesMax = mQueue->getQuantumCount();
         ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax);
     }
 
-    MessageQueueSync* mQueue = nullptr;
+    T* mQueue = nullptr;
     size_t mNumMessagesMax = 0;
 };
 
-class UnsynchronizedWrite : public ::testing::Test {
-protected:
+TYPED_TEST_CASE(UnsynchronizedWrite, UnsyncTypes);
+
+template <typename T>
+class UnsynchronizedWrite : public TestBase<T> {
+  protected:
     virtual void TearDown() {
         delete mQueue;
     }
 
     virtual void SetUp() {
         static constexpr size_t kNumElementsInQueue = 2048;
-        mQueue = new (std::nothrow) MessageQueueUnsync(kNumElementsInQueue);
+        mQueue = new (std::nothrow) T(kNumElementsInQueue);
         ASSERT_NE(nullptr, mQueue);
         ASSERT_TRUE(mQueue->isValid());
         mNumMessagesMax = mQueue->getQuantumCount();
         ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax);
     }
 
-    MessageQueueUnsync* mQueue = nullptr;
+    T* mQueue = nullptr;
     size_t mNumMessagesMax = 0;
 };
 
-class BlockingReadWrites : public ::testing::Test {
-protected:
+TYPED_TEST_CASE(BlockingReadWrites, SyncTypes);
+
+template <typename T>
+class BlockingReadWrites : public TestBase<T> {
+  protected:
     virtual void TearDown() {
         delete mQueue;
     }
     virtual void SetUp() {
         static constexpr size_t kNumElementsInQueue = 2048;
-        mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue);
+        mQueue = new (std::nothrow) T(kNumElementsInQueue);
         ASSERT_NE(nullptr, mQueue);
         ASSERT_TRUE(mQueue->isValid());
         mNumMessagesMax = mQueue->getQuantumCount();
@@ -89,38 +116,40 @@
         std::atomic_init(&mFw, static_cast<uint32_t>(kFmqNotFull));
     }
 
-    MessageQueueSync* mQueue;
+    T* mQueue;
     std::atomic<uint32_t> mFw;
     size_t mNumMessagesMax = 0;
 };
 
-class QueueSizeOdd : public ::testing::Test {
-protected:
-  virtual void TearDown() {
-      delete mQueue;
-  }
-  virtual void SetUp() {
-      static constexpr size_t kNumElementsInQueue = 2049;
-      mQueue = new (std::nothrow) MessageQueueSync(kNumElementsInQueue,
-                                                   true /* configureEventFlagWord */);
-      ASSERT_NE(nullptr, mQueue);
-      ASSERT_TRUE(mQueue->isValid());
-      mNumMessagesMax = mQueue->getQuantumCount();
-      ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax);
-      auto evFlagWordPtr = mQueue->getEventFlagWord();
-      ASSERT_NE(nullptr, evFlagWordPtr);
-      /*
-       * Initialize the EventFlag word to indicate Queue is not full.
-       */
-      std::atomic_init(evFlagWordPtr, static_cast<uint32_t>(kFmqNotFull));
-  }
+TYPED_TEST_CASE(QueueSizeOdd, SyncTypes);
 
-  MessageQueueSync* mQueue;
-  size_t mNumMessagesMax = 0;
+template <typename T>
+class QueueSizeOdd : public TestBase<T> {
+  protected:
+    virtual void TearDown() { delete mQueue; }
+    virtual void SetUp() {
+        static constexpr size_t kNumElementsInQueue = 2049;
+        mQueue = new (std::nothrow) T(kNumElementsInQueue, true /* configureEventFlagWord */);
+        ASSERT_NE(nullptr, mQueue);
+        ASSERT_TRUE(mQueue->isValid());
+        mNumMessagesMax = mQueue->getQuantumCount();
+        ASSERT_EQ(kNumElementsInQueue, mNumMessagesMax);
+        auto evFlagWordPtr = mQueue->getEventFlagWord();
+        ASSERT_NE(nullptr, evFlagWordPtr);
+        /*
+         * Initialize the EventFlag word to indicate Queue is not full.
+         */
+        std::atomic_init(evFlagWordPtr, static_cast<uint32_t>(kFmqNotFull));
+    }
+
+    T* mQueue;
+    size_t mNumMessagesMax = 0;
 };
 
-class BadQueueConfig: public ::testing::Test {
-};
+TYPED_TEST_CASE(BadQueueConfig, BadConfigTypes);
+
+template <typename T>
+class BadQueueConfig : public TestBase<T> {};
 
 /*
  * Utility function to initialize data to be written to the FMQ
@@ -136,10 +165,8 @@
  * it checks if the kFmqNotEmpty bit is actually set.
  * If the read is succesful, it signals Wake to kFmqNotFull.
  */
-void ReaderThreadBlocking(
-        android::hardware::MessageQueue<uint8_t,
-        android::hardware::kSynchronizedReadWrite>* fmq,
-        std::atomic<uint32_t>* fwAddr) {
+template <typename T>
+void TestBase<T>::ReaderThreadBlocking(T* fmq, std::atomic<uint32_t>* fwAddr) {
     const size_t dataLen = 64;
     uint8_t data[dataLen];
     android::hardware::EventFlag* efGroup = nullptr;
@@ -171,10 +198,8 @@
  * This thread will attempt to read and block using the readBlocking() API and
  * passes in a pointer to an EventFlag object.
  */
-void ReaderThreadBlocking2(
-        android::hardware::MessageQueue<uint8_t,
-        android::hardware::kSynchronizedReadWrite>* fmq,
-        std::atomic<uint32_t>* fwAddr) {
+template <typename T>
+void TestBase<T>::ReaderThreadBlocking2(T* fmq, std::atomic<uint32_t>* fwAddr) {
     const size_t dataLen = 64;
     uint8_t data[dataLen];
     android::hardware::EventFlag* efGroup = nullptr;
@@ -192,12 +217,9 @@
     ASSERT_EQ(android::NO_ERROR, status);
 }
 
-
-TEST_F(BadQueueConfig, QueueSizeTooLarge) {
-    typedef android::hardware::MessageQueue<uint16_t, android::hardware::kSynchronizedReadWrite>
-            MessageQueueSync16;
+TYPED_TEST(BadQueueConfig, QueueSizeTooLarge) {
     size_t numElementsInQueue = SIZE_MAX / sizeof(uint16_t) + 1;
-    MessageQueueSync16 * fmq = new (std::nothrow) MessageQueueSync16(numElementsInQueue);
+    TypeParam* fmq = new (std::nothrow) TypeParam(numElementsInQueue);
     ASSERT_NE(nullptr, fmq);
     /*
      * Should fail due to size being too large to fit into size_t.
@@ -209,12 +231,12 @@
  * Test that basic blocking works. This test uses the non-blocking read()/write()
  * APIs.
  */
-TEST_F(BlockingReadWrites, SmallInputTest1) {
+TYPED_TEST(BlockingReadWrites, SmallInputTest1) {
     const size_t dataLen = 64;
     uint8_t data[dataLen] = {0};
 
     android::hardware::EventFlag* efGroup = nullptr;
-    android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup);
+    android::status_t status = android::hardware::EventFlag::createEventFlag(&this->mFw, &efGroup);
 
     ASSERT_EQ(android::NO_ERROR, status);
     ASSERT_NE(nullptr, efGroup);
@@ -222,7 +244,8 @@
     /*
      * Start a thread that will try to read and block on kFmqNotEmpty.
      */
-    std::thread Reader(ReaderThreadBlocking, mQueue, &mFw);
+    std::thread Reader(BlockingReadWrites<TypeParam>::ReaderThreadBlocking, this->mQueue,
+                       &this->mFw);
     struct timespec waitTime = {0, 100 * 1000000};
     ASSERT_EQ(0, nanosleep(&waitTime, NULL));
 
@@ -230,7 +253,7 @@
      * After waiting for some time write into the FMQ
      * and call Wake on kFmqNotEmpty.
      */
-    ASSERT_TRUE(mQueue->write(data, dataLen));
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
     status = efGroup->wake(kFmqNotEmpty);
     ASSERT_EQ(android::NO_ERROR, status);
 
@@ -245,12 +268,12 @@
  * Test that basic blocking works. This test uses the
  * writeBlocking()/readBlocking() APIs.
  */
-TEST_F(BlockingReadWrites, SmallInputTest2) {
+TYPED_TEST(BlockingReadWrites, SmallInputTest2) {
     const size_t dataLen = 64;
     uint8_t data[dataLen] = {0};
 
     android::hardware::EventFlag* efGroup = nullptr;
-    android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup);
+    android::status_t status = android::hardware::EventFlag::createEventFlag(&this->mFw, &efGroup);
 
     ASSERT_EQ(android::NO_ERROR, status);
     ASSERT_NE(nullptr, efGroup);
@@ -259,13 +282,11 @@
      * Start a thread that will try to read and block on kFmqNotEmpty. It will
      * call wake() on kFmqNotFull when the read is successful.
      */
-    std::thread Reader(ReaderThreadBlocking2, mQueue, &mFw);
-    bool ret = mQueue->writeBlocking(data,
-                                     dataLen,
-                                     static_cast<uint32_t>(kFmqNotFull),
-                                     static_cast<uint32_t>(kFmqNotEmpty),
-                                     5000000000 /* timeOutNanos */,
-                                     efGroup);
+    std::thread Reader(BlockingReadWrites<TypeParam>::ReaderThreadBlocking2, this->mQueue,
+                       &this->mFw);
+    bool ret = this->mQueue->writeBlocking(data, dataLen, static_cast<uint32_t>(kFmqNotFull),
+                                           static_cast<uint32_t>(kFmqNotEmpty),
+                                           5000000000 /* timeOutNanos */, efGroup);
     ASSERT_TRUE(ret);
     Reader.join();
 
@@ -276,9 +297,9 @@
 /*
  * Test that basic blocking times out as intended.
  */
-TEST_F(BlockingReadWrites, BlockingTimeOutTest) {
+TYPED_TEST(BlockingReadWrites, BlockingTimeOutTest) {
     android::hardware::EventFlag* efGroup = nullptr;
-    android::status_t status = android::hardware::EventFlag::createEventFlag(&mFw, &efGroup);
+    android::status_t status = android::hardware::EventFlag::createEventFlag(&this->mFw, &efGroup);
 
     ASSERT_EQ(android::NO_ERROR, status);
     ASSERT_NE(nullptr, efGroup);
@@ -301,31 +322,29 @@
  * Test that odd queue sizes do not cause unaligned error
  * on access to EventFlag object.
  */
-TEST_F(QueueSizeOdd, EventFlagTest) {
+TYPED_TEST(QueueSizeOdd, EventFlagTest) {
     const size_t dataLen = 64;
     uint8_t data[dataLen] = {0};
 
-    bool ret = mQueue->writeBlocking(data,
-                                     dataLen,
-                                     static_cast<uint32_t>(kFmqNotFull),
-                                     static_cast<uint32_t>(kFmqNotEmpty),
-                                     5000000000 /* timeOutNanos */);
+    bool ret = this->mQueue->writeBlocking(data, dataLen, static_cast<uint32_t>(kFmqNotFull),
+                                           static_cast<uint32_t>(kFmqNotEmpty),
+                                           5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
 }
 
 /*
  * Verify that a few bytes of data can be successfully written and read.
  */
-TEST_F(SynchronizedReadWrites, SmallInputTest1) {
+TYPED_TEST(SynchronizedReadWrites, SmallInputTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
 
-    ASSERT_TRUE(mQueue->write(data, dataLen));
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
     uint8_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_EQ(0, memcmp(data, readData, dataLen));
 }
 
@@ -333,27 +352,27 @@
  * Verify that a few bytes of data can be successfully written and read using
  * beginRead/beginWrite/CommitRead/CommitWrite
  */
-TEST_F(SynchronizedReadWrites, SmallInputTest2) {
+TYPED_TEST(SynchronizedReadWrites, SmallInputTest2) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(dataLen, &tx));
 
     ASSERT_TRUE(tx.copyTo(data, 0 /* startIdx */, dataLen));
 
-    ASSERT_TRUE(mQueue->commitWrite(dataLen));
+    ASSERT_TRUE(this->mQueue->commitWrite(dataLen));
 
     uint8_t readData[dataLen] = {};
 
-    ASSERT_TRUE(mQueue->beginRead(dataLen, &tx));
+    ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
 
     ASSERT_TRUE(tx.copyFrom(readData, 0 /* startIdx */, dataLen));
 
-    ASSERT_TRUE(mQueue->commitRead(dataLen));
+    ASSERT_TRUE(this->mQueue->commitRead(dataLen));
 
     ASSERT_EQ(0, memcmp(data, readData, dataLen));
 }
@@ -362,14 +381,14 @@
  * Verify that a few bytes of data can be successfully written and read using
  * beginRead/beginWrite/CommitRead/CommitWrite as well as getSlot().
  */
-TEST_F(SynchronizedReadWrites, SmallInputTest3) {
+TYPED_TEST(SynchronizedReadWrites, SmallInputTest3) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(dataLen, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -380,11 +399,11 @@
         *ptr = data[i];
     }
 
-    ASSERT_TRUE(mQueue->commitWrite(dataLen));
+    ASSERT_TRUE(this->mQueue->commitWrite(dataLen));
 
     uint8_t readData[dataLen] = {};
 
-    ASSERT_TRUE(mQueue->beginRead(dataLen, &tx));
+    ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
 
     first = tx.getFirstRegion();
     second = tx.getSecondRegion();
@@ -396,7 +415,7 @@
         readData[i] = *ptr;
     }
 
-    ASSERT_TRUE(mQueue->commitRead(dataLen));
+    ASSERT_TRUE(this->mQueue->commitRead(dataLen));
 
     ASSERT_EQ(0, memcmp(data, readData, dataLen));
 }
@@ -404,25 +423,25 @@
 /*
  * Verify that read() returns false when trying to read from an empty queue.
  */
-TEST_F(SynchronizedReadWrites, ReadWhenEmpty1) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWrites, ReadWhenEmpty1) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 2;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t readData[dataLen];
-    ASSERT_FALSE(mQueue->read(readData, dataLen));
+    ASSERT_FALSE(this->mQueue->read(readData, dataLen));
 }
 
 /*
  * Verify that beginRead() returns a MemTransaction object with null pointers when trying
  * to read from an empty queue.
  */
-TEST_F(SynchronizedReadWrites, ReadWhenEmpty2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWrites, ReadWhenEmpty2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 2;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_FALSE(mQueue->beginRead(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_FALSE(this->mQueue->beginRead(dataLen, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -435,17 +454,17 @@
  * Write the queue until full. Verify that another write is unsuccessful.
  * Verify that availableToWrite() returns 0 as expected.
  */
-TEST_F(SynchronizedReadWrites, WriteWhenFull1) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    std::vector<uint8_t> data(mNumMessagesMax);
+TYPED_TEST(SynchronizedReadWrites, WriteWhenFull1) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    std::vector<uint8_t> data(this->mNumMessagesMax);
 
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_FALSE(mQueue->write(&data[0], 1));
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_FALSE(this->mQueue->write(&data[0], 1));
 
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
 
@@ -453,16 +472,16 @@
  * Write the queue until full. Verify that beginWrite() returns
  * a MemTransaction object with null base pointers.
  */
-TEST_F(SynchronizedReadWrites, WriteWhenFull2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    std::vector<uint8_t> data(mNumMessagesMax);
+TYPED_TEST(SynchronizedReadWrites, WriteWhenFull2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    std::vector<uint8_t> data(this->mNumMessagesMax);
 
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_FALSE(mQueue->beginWrite(1, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_FALSE(this->mQueue->beginWrite(1, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -476,12 +495,12 @@
  * Verify that the write is successful and the subsequent read
  * returns the expected data.
  */
-TEST_F(SynchronizedReadWrites, LargeInputTest1) {
-    std::vector<uint8_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+TYPED_TEST(SynchronizedReadWrites, LargeInputTest1) {
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
 
@@ -490,18 +509,18 @@
  * Verify that it fails. Verify that a subsequent read fails and
  * the queue is still empty.
  */
-TEST_F(SynchronizedReadWrites, LargeInputTest2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWrites, LargeInputTest2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 4096;
-    ASSERT_GT(dataLen, mNumMessagesMax);
+    ASSERT_GT(dataLen, this->mNumMessagesMax);
     std::vector<uint8_t> data(dataLen);
 
     initData(&data[0], dataLen);
-    ASSERT_FALSE(mQueue->write(&data[0], dataLen));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+    ASSERT_FALSE(this->mQueue->write(&data[0], dataLen));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_NE(data, readData);
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
 }
 
 /*
@@ -509,13 +528,13 @@
  * the attempt returns false. Verify that the attempt did not
  * affect the pre-existing data in the queue.
  */
-TEST_F(SynchronizedReadWrites, LargeInputTest3) {
-    std::vector<uint8_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_FALSE(mQueue->write(&data[0], 1));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+TYPED_TEST(SynchronizedReadWrites, LargeInputTest3) {
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_FALSE(this->mQueue->write(&data[0], 1));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
 
@@ -524,13 +543,13 @@
  * null base pointers when attempting to write data larger
  * than the queue size.
  */
-TEST_F(SynchronizedReadWrites, LargeInputTest4) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWrites, LargeInputTest4) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 4096;
-    ASSERT_GT(dataLen, mNumMessagesMax);
+    ASSERT_GT(dataLen, this->mNumMessagesMax);
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_FALSE(mQueue->beginWrite(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_FALSE(this->mQueue->beginWrite(dataLen, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -542,18 +561,18 @@
 /*
  * Verify that multiple reads one after the other return expected data.
  */
-TEST_F(SynchronizedReadWrites, MultipleRead) {
+TYPED_TEST(SynchronizedReadWrites, MultipleRead) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t dataLen = chunkSize * chunkNum;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
-    ASSERT_TRUE(mQueue->write(data, dataLen));
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
     uint8_t readData[dataLen] = {};
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
     }
     ASSERT_EQ(0, memcmp(readData, data, dataLen));
 }
@@ -561,37 +580,37 @@
 /*
  * Verify that multiple writes one after the other happens correctly.
  */
-TEST_F(SynchronizedReadWrites, MultipleWrite) {
+TYPED_TEST(SynchronizedReadWrites, MultipleWrite) {
     const int chunkSize = 100;
     const int chunkNum = 5;
     const size_t dataLen = chunkSize * chunkNum;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
     for (unsigned int i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
     }
     uint8_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_EQ(0, memcmp(readData, data, dataLen));
 }
 
 /*
  * Write enough messages into the FMQ to fill half of it
  * and read back the same.
- * Write mNumMessagesMax messages into the queue. This will cause a
+ * Write this->mNumMessagesMax messages into the queue. This will cause a
  * wrap around. Read and verify the data.
  */
-TEST_F(SynchronizedReadWrites, ReadWriteWrapAround1) {
-    size_t numMessages = mNumMessagesMax - 1;
-    std::vector<uint8_t> data(mNumMessagesMax);
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], numMessages));
-    ASSERT_TRUE(mQueue->read(&readData[0], numMessages));
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+TYPED_TEST(SynchronizedReadWrites, ReadWriteWrapAround1) {
+    size_t numMessages = this->mNumMessagesMax - 1;
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
+    ASSERT_TRUE(this->mQueue->read(&readData[0], numMessages));
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
 
@@ -603,38 +622,38 @@
  * Write mNumMessagesMax messages into the queue. This will cause a
  * wrap around. Read and verify the data.
  */
-TEST_F(SynchronizedReadWrites, ReadWriteWrapAround2) {
-    size_t dataLen = mNumMessagesMax - 1;
-    std::vector<uint8_t> data(mNumMessagesMax);
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], dataLen));
-    ASSERT_TRUE(mQueue->read(&readData[0], dataLen));
+TYPED_TEST(SynchronizedReadWrites, ReadWriteWrapAround2) {
+    size_t dataLen = this->mNumMessagesMax - 1;
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], dataLen));
+    ASSERT_TRUE(this->mQueue->read(&readData[0], dataLen));
 
     /*
      * The next write and read will have to deal with with wrap arounds.
      */
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(mNumMessagesMax, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(this->mNumMessagesMax, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
 
-    ASSERT_EQ(first.getLength() + second.getLength(), mNumMessagesMax);
+    ASSERT_EQ(first.getLength() + second.getLength(), this->mNumMessagesMax);
 
-    ASSERT_TRUE(tx.copyTo(&data[0], 0 /* startIdx */,  mNumMessagesMax));
+    ASSERT_TRUE(tx.copyTo(&data[0], 0 /* startIdx */, this->mNumMessagesMax));
 
-    ASSERT_TRUE(mQueue->commitWrite(mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->commitWrite(this->mNumMessagesMax));
 
-    ASSERT_TRUE(mQueue->beginRead(mNumMessagesMax, &tx));
+    ASSERT_TRUE(this->mQueue->beginRead(this->mNumMessagesMax, &tx));
 
     first = tx.getFirstRegion();
     second = tx.getSecondRegion();
 
-    ASSERT_EQ(first.getLength() + second.getLength(), mNumMessagesMax);
+    ASSERT_EQ(first.getLength() + second.getLength(), this->mNumMessagesMax);
 
-    ASSERT_TRUE(tx.copyFrom(&readData[0], 0 /* startIdx */, mNumMessagesMax));
-    ASSERT_TRUE(mQueue->commitRead(mNumMessagesMax));
+    ASSERT_TRUE(tx.copyFrom(&readData[0], 0 /* startIdx */, this->mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->commitRead(this->mNumMessagesMax));
 
     ASSERT_EQ(data, readData);
 }
@@ -642,44 +661,44 @@
 /*
  * Verify that a few bytes of data can be successfully written and read.
  */
-TEST_F(UnsynchronizedWrite, SmallInputTest1) {
+TYPED_TEST(UnsynchronizedWrite, SmallInputTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
-    ASSERT_TRUE(mQueue->write(data, dataLen));
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
     uint8_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_EQ(0, memcmp(data, readData, dataLen));
 }
 
 /*
  * Verify that read() returns false when trying to read from an empty queue.
  */
-TEST_F(UnsynchronizedWrite, ReadWhenEmpty) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(UnsynchronizedWrite, ReadWhenEmpty) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 2;
-    ASSERT_TRUE(dataLen < mNumMessagesMax);
+    ASSERT_TRUE(dataLen < this->mNumMessagesMax);
     uint8_t readData[dataLen];
-    ASSERT_FALSE(mQueue->read(readData, dataLen));
+    ASSERT_FALSE(this->mQueue->read(readData, dataLen));
 }
 
 /*
  * Write the queue when full. Verify that a subsequent writes is succesful.
  * Verify that availableToWrite() returns 0 as expected.
  */
-TEST_F(UnsynchronizedWrite, WriteWhenFull1) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    std::vector<uint8_t> data(mNumMessagesMax);
+TYPED_TEST(UnsynchronizedWrite, WriteWhenFull1) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    std::vector<uint8_t> data(this->mNumMessagesMax);
 
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_TRUE(mQueue->write(&data[0], 1));
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_TRUE(this->mQueue->write(&data[0], 1));
 
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
 }
 
 /*
@@ -687,22 +706,22 @@
  * using beginRead()/commitRead() is succesful.
  * Verify that the next read fails as expected for unsynchronized flavor.
  */
-TEST_F(UnsynchronizedWrite, WriteWhenFull2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    std::vector<uint8_t> data(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
+TYPED_TEST(UnsynchronizedWrite, WriteWhenFull2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
 
-    MessageQueueUnsync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(1, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(1, &tx));
 
     ASSERT_EQ(tx.getFirstRegion().getLength(), 1U);
 
     ASSERT_TRUE(tx.copyTo(&data[0], 0 /* startIdx */));
 
-    ASSERT_TRUE(mQueue->commitWrite(1));
+    ASSERT_TRUE(this->mQueue->commitWrite(1));
 
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
 }
 
 /*
@@ -710,12 +729,12 @@
  * Verify that the write is successful and the subsequent read
  * returns the expected data.
  */
-TEST_F(UnsynchronizedWrite, LargeInputTest1) {
-    std::vector<uint8_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+TYPED_TEST(UnsynchronizedWrite, LargeInputTest1) {
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
 
@@ -724,17 +743,17 @@
  * Verify that it fails. Verify that a subsequent read fails and
  * the queue is still empty.
  */
-TEST_F(UnsynchronizedWrite, LargeInputTest2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(UnsynchronizedWrite, LargeInputTest2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t dataLen = 4096;
-    ASSERT_GT(dataLen, mNumMessagesMax);
+    ASSERT_GT(dataLen, this->mNumMessagesMax);
     std::vector<uint8_t> data(dataLen);
     initData(&data[0], dataLen);
-    ASSERT_FALSE(mQueue->write(&data[0], dataLen));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+    ASSERT_FALSE(this->mQueue->write(&data[0], dataLen));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_NE(data, readData);
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
 }
 
 /*
@@ -742,29 +761,29 @@
  * the attempt is succesful. Verify that the read fails
  * as expected.
  */
-TEST_F(UnsynchronizedWrite, LargeInputTest3) {
-    std::vector<uint8_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_TRUE(mQueue->write(&data[0], 1));
-    std::vector<uint8_t> readData(mNumMessagesMax);
-    ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+TYPED_TEST(UnsynchronizedWrite, LargeInputTest3) {
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->write(&data[0], 1));
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
+    ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
 }
 
 /*
  * Verify that multiple reads one after the other return expected data.
  */
-TEST_F(UnsynchronizedWrite, MultipleRead) {
+TYPED_TEST(UnsynchronizedWrite, MultipleRead) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t dataLen = chunkSize * chunkNum;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
     initData(data, dataLen);
-    ASSERT_TRUE(mQueue->write(data, dataLen));
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
     uint8_t readData[dataLen] = {};
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
     }
     ASSERT_EQ(0, memcmp(readData, data, dataLen));
 }
@@ -772,20 +791,20 @@
 /*
  * Verify that multiple writes one after the other happens correctly.
  */
-TEST_F(UnsynchronizedWrite, MultipleWrite) {
+TYPED_TEST(UnsynchronizedWrite, MultipleWrite) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t dataLen = chunkSize * chunkNum;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint8_t data[dataLen];
 
     initData(data, dataLen);
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
     }
 
     uint8_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_EQ(0, memcmp(readData, data, dataLen));
 }
 
@@ -795,15 +814,15 @@
  * Write mNumMessagesMax messages into the queue. This will cause a
  * wrap around. Read and verify the data.
  */
-TEST_F(UnsynchronizedWrite, ReadWriteWrapAround) {
-    size_t numMessages = mNumMessagesMax - 1;
-    std::vector<uint8_t> data(mNumMessagesMax);
-    std::vector<uint8_t> readData(mNumMessagesMax);
+TYPED_TEST(UnsynchronizedWrite, ReadWriteWrapAround) {
+    size_t numMessages = this->mNumMessagesMax - 1;
+    std::vector<uint8_t> data(this->mNumMessagesMax);
+    std::vector<uint8_t> readData(this->mNumMessagesMax);
 
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], numMessages));
-    ASSERT_TRUE(mQueue->read(&readData[0], numMessages));
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
+    ASSERT_TRUE(this->mQueue->read(&readData[0], numMessages));
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     ASSERT_EQ(data, readData);
 }
diff --git a/tests/msgq_test_client.cpp b/tests/msgq_test_client.cpp
index a3d50a5..2277624 100644
--- a/tests/msgq_test_client.cpp
+++ b/tests/msgq_test_client.cpp
@@ -19,7 +19,12 @@
 #error "GTest did not detect pthread library."
 #endif
 
+#include <aidl/android/fmq/test/ITestAidlMsgQ.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
+#include <fmq/AidlMessageQueue.h>
 #include <fmq/EventFlag.h>
 #include <fmq/MessageQueue.h>
 #include <hidl/ServiceManagement.h>
@@ -30,6 +35,7 @@
 using android::status_t;
 
 // generated
+using ::aidl::android::fmq::test::ITestAidlMsgQ;
 using android::hardware::tests::msgq::V1_0::ITestMsgQ;
 
 // libhidl
@@ -40,81 +46,220 @@
 using android::hardware::MQDescriptorUnsync;
 using android::hardware::details::waitForHwService;
 
-typedef MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
-typedef MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::kUnsynchronizedWrite;
 
-static sp<ITestMsgQ> waitGetTestService() {
-    android::hardware::details::setTrebleTestingOverride(true);
-    // waitForHwService is required because ITestMsgQ is not in manifest.xml.
-    // "Real" HALs shouldn't be doing this.
-    waitForHwService(ITestMsgQ::descriptor, "default");
-    return ITestMsgQ::getService();
-}
+typedef android::AidlMessageQueue<uint16_t, kSynchronizedReadWrite> AidlMessageQueueSync;
+typedef android::AidlMessageQueue<uint16_t, kUnsynchronizedWrite> AidlMessageQueueUnsync;
+typedef android::hardware::MessageQueue<uint16_t, kSynchronizedReadWrite> MessageQueueSync;
+typedef android::hardware::MessageQueue<uint16_t, kUnsynchronizedWrite> MessageQueueUnsync;
+static const std::string kServiceName = "BnTestAidlMsgQ";
 
-class UnsynchronizedWriteClientMultiProcess : public ::testing::Test {
-   protected:
-    void getQueue(MessageQueueUnsync** fmq, sp<ITestMsgQ>* service, bool setupQueue) {
-        *service = waitGetTestService();
-        *fmq = nullptr;
-        if (*service == nullptr) return;
-        if (!(*service)->isRemote()) return;
-        (*service)->getFmqUnsyncWrite(setupQueue,
-                                      [fmq](bool ret, const MQDescriptorUnsync<uint16_t>& in) {
-                                          ASSERT_TRUE(ret);
-                                          *fmq = new (std::nothrow) MessageQueueUnsync(in);
-                                      });
+// Run everything on both the AIDL and HIDL versions
+typedef ::testing::Types<AidlMessageQueueSync, MessageQueueSync> SyncTypes;
+typedef ::testing::Types<AidlMessageQueueUnsync, MessageQueueUnsync> UnsyncTypes;
+
+template <typename T>
+class ClientSyncTestBase : public ::testing::Test {};
+
+// Specialize for AIDL
+template <>
+class ClientSyncTestBase<AidlMessageQueueSync> : public ::testing::Test {
+  protected:
+    static std::shared_ptr<ITestAidlMsgQ> waitGetTestService() {
+        const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
+        ndk::SpAIBinder binder(AServiceManager_getService(instance.c_str()));
+        return ITestAidlMsgQ::fromBinder(binder);
     }
+    bool configureFmqSyncReadWrite(AidlMessageQueueSync* mq) {
+        bool result = false;
+        auto ret = mService->configureFmqSyncReadWrite(mq->dupeDesc(), &result);
+        return result && ret.isOk();
+    }
+    bool requestReadFmqSync(size_t dataLen) {
+        bool result = false;
+        auto ret = mService->requestReadFmqSync(dataLen, &result);
+        return result && ret.isOk();
+    }
+    bool requestWriteFmqSync(size_t dataLen) {
+        bool result = false;
+        auto ret = mService->requestWriteFmqSync(dataLen, &result);
+        return result && ret.isOk();
+    }
+
+    std::shared_ptr<ITestAidlMsgQ> mService;
 };
 
-class SynchronizedReadWriteClient : public ::testing::Test {
-protected:
+// Specialize for HIDL
+template <>
+class ClientSyncTestBase<MessageQueueSync> : public ::testing::Test {
+  protected:
+    static sp<ITestMsgQ> waitGetTestService() {
+        android::hardware::details::setTrebleTestingOverride(true);
+        // waitForHwService is required because ITestMsgQ is not in manifest.xml.
+        // "Real" HALs shouldn't be doing this.
+        waitForHwService(ITestMsgQ::descriptor, "default");
+        return ITestMsgQ::getService();
+    }
+    bool configureFmqSyncReadWrite(MessageQueueSync* mq) {
+        auto ret = mService->configureFmqSyncReadWrite(*mq->getDesc());
+        return ret && ret.isOk();
+    }
+    bool requestReadFmqSync(size_t dataLen) {
+        auto ret = mService->requestReadFmqSync(dataLen);
+        return ret && ret.isOk();
+    }
+    bool requestWriteFmqSync(size_t dataLen) {
+        auto ret = mService->requestWriteFmqSync(dataLen);
+        return ret && ret.isOk();
+    }
+
+    sp<ITestMsgQ> mService;
+};
+
+template <typename T>
+class ClientUnsyncTestBase : public ::testing::Test {};
+
+// Specialize for AIDL
+template <>
+class ClientUnsyncTestBase<AidlMessageQueueUnsync> : public ::testing::Test {
+  protected:
+    static std::shared_ptr<ITestAidlMsgQ> waitGetTestService() {
+        const std::string instance = std::string() + ITestAidlMsgQ::descriptor + "/default";
+        ndk::SpAIBinder binder(AServiceManager_getService(instance.c_str()));
+        return ITestAidlMsgQ::fromBinder(binder);
+    }
+    bool getFmqUnsyncWrite(bool configureFmq, std::shared_ptr<ITestAidlMsgQ> service,
+                           AidlMessageQueueUnsync** queue) {
+        bool result = false;
+        aidl::android::hardware::common::MQDescriptor desc;
+        auto ret = service->getFmqUnsyncWrite(configureFmq, &desc, &result);
+        *queue = new (std::nothrow) AidlMessageQueueUnsync(desc);
+        return result && ret.isOk();
+    }
+
+    std::shared_ptr<ITestAidlMsgQ> getQueue(AidlMessageQueueUnsync** fmq, bool setupQueue) {
+        std::shared_ptr<ITestAidlMsgQ> service = waitGetTestService();
+        if (service == nullptr) return nullptr;
+        getFmqUnsyncWrite(setupQueue, service, fmq);
+        return service;
+    }
+
+    bool requestReadFmqUnsync(size_t dataLen, std::shared_ptr<ITestAidlMsgQ> service) {
+        bool result = false;
+        auto ret = service->requestReadFmqUnsync(dataLen, &result);
+        return result && ret.isOk();
+    }
+    bool requestWriteFmqUnsync(size_t dataLen, std::shared_ptr<ITestAidlMsgQ> service) {
+        bool result = false;
+        auto ret = service->requestWriteFmqUnsync(dataLen, &result);
+        return result && ret.isOk();
+    }
+    AidlMessageQueueUnsync* newQueue() {
+        if (mQueue->isValid())
+            return new (std::nothrow) AidlMessageQueueUnsync(mQueue->dupeDesc());
+        else
+            return nullptr;
+    }
+
+    std::shared_ptr<ITestAidlMsgQ> mService;
+    AidlMessageQueueUnsync* mQueue = nullptr;
+};
+
+// Specialize for HIDL
+template <>
+class ClientUnsyncTestBase<MessageQueueUnsync> : public ::testing::Test {
+  protected:
+    static sp<ITestMsgQ> waitGetTestService() {
+        android::hardware::details::setTrebleTestingOverride(true);
+        // waitForHwService is required because ITestMsgQ is not in manifest.xml.
+        // "Real" HALs shouldn't be doing this.
+        waitForHwService(ITestMsgQ::descriptor, "default");
+        return ITestMsgQ::getService();
+    }
+    bool getFmqUnsyncWrite(bool configureFmq, sp<ITestMsgQ> service, MessageQueueUnsync** queue) {
+        if (!service) {
+            return false;
+        }
+        service->getFmqUnsyncWrite(configureFmq /* configureFmq */,
+                                   [queue](bool ret, const MQDescriptorUnsync<uint16_t>& in) {
+                                       ASSERT_TRUE(ret);
+                                       *queue = new (std::nothrow) MessageQueueUnsync(in);
+                                   });
+        return true;
+    }
+
+    sp<ITestMsgQ> getQueue(MessageQueueUnsync** fmq, bool setupQueue) {
+        sp<ITestMsgQ> service = waitGetTestService();
+        if (service == nullptr) return nullptr;
+        getFmqUnsyncWrite(setupQueue, service, fmq);
+        return service;
+    }
+
+    bool requestReadFmqUnsync(size_t dataLen, sp<ITestMsgQ> service) {
+        auto ret = service->requestReadFmqUnsync(dataLen);
+        return ret && ret.isOk();
+    }
+    bool requestWriteFmqUnsync(size_t dataLen, sp<ITestMsgQ> service) {
+        auto ret = service->requestWriteFmqUnsync(dataLen);
+        return ret && ret.isOk();
+    }
+
+    MessageQueueUnsync* newQueue() {
+        return new (std::nothrow) MessageQueueUnsync(*mQueue->getDesc());
+    }
+
+    sp<ITestMsgQ> mService;
+    MessageQueueUnsync* mQueue = nullptr;
+};
+
+TYPED_TEST_CASE(UnsynchronizedWriteClientMultiProcess, UnsyncTypes);
+template <typename T>
+class UnsynchronizedWriteClientMultiProcess : public ClientUnsyncTestBase<T> {};
+
+TYPED_TEST_CASE(SynchronizedReadWriteClient, SyncTypes);
+template <typename T>
+class SynchronizedReadWriteClient : public ClientSyncTestBase<T> {
+  protected:
     virtual void TearDown() {
         delete mQueue;
     }
 
     virtual void SetUp() {
         static constexpr size_t kNumElementsInQueue = 1024;
-        mService = waitGetTestService();
-        ASSERT_NE(mService, nullptr);
-        ASSERT_TRUE(mService->isRemote());
+        this->mService = this->waitGetTestService();
+        ASSERT_NE(this->mService, nullptr);
+        ASSERT_TRUE(this->mService->isRemote());
         // create a queue on the client side
-        mQueue = new (std::nothrow)
-            MessageQueueSync(kNumElementsInQueue, true /* configure event flag word */);
+        mQueue = new (std::nothrow) T(kNumElementsInQueue, true /* configure event flag word */);
         ASSERT_NE(nullptr, mQueue);
         ASSERT_TRUE(mQueue->isValid());
         mNumMessagesMax = mQueue->getQuantumCount();
 
         // tell server to set up the queue on its end
-        ASSERT_TRUE(mService->configureFmqSyncReadWrite(*mQueue->getDesc()));
+        ASSERT_TRUE(this->configureFmqSyncReadWrite(mQueue));
     }
 
-    sp<ITestMsgQ> mService;
-    MessageQueueSync* mQueue = nullptr;
+    T* mQueue = nullptr;
     size_t mNumMessagesMax = 0;
 };
 
-class UnsynchronizedWriteClient : public ::testing::Test {
-protected:
-    virtual void TearDown() {
-        delete mQueue;
-    }
+TYPED_TEST_CASE(UnsynchronizedWriteClient, UnsyncTypes);
+template <typename T>
+class UnsynchronizedWriteClient : public ClientUnsyncTestBase<T> {
+  protected:
+    virtual void TearDown() { delete this->mQueue; }
 
     virtual void SetUp() {
-        mService = waitGetTestService();
-        ASSERT_NE(mService, nullptr);
-        ASSERT_TRUE(mService->isRemote());
-        mService->getFmqUnsyncWrite(true /* configureFmq */,
-                                    [this](bool ret, const MQDescriptorUnsync<uint16_t>& in) {
-                                        ASSERT_TRUE(ret);
-                                        mQueue = new (std::nothrow) MessageQueueUnsync(in);
-                                    });
-        ASSERT_NE(nullptr, mQueue);
-        ASSERT_TRUE(mQueue->isValid());
-        mNumMessagesMax = mQueue->getQuantumCount();
+        this->mService = this->waitGetTestService();
+        ASSERT_NE(this->mService, nullptr);
+        ASSERT_TRUE(this->mService->isRemote());
+        this->getFmqUnsyncWrite(true, this->mService, &this->mQueue);
+        ASSERT_NE(nullptr, this->mQueue);
+        ASSERT_TRUE(this->mQueue->isValid());
+        mNumMessagesMax = this->mQueue->getQuantumCount();
     }
 
-    sp<ITestMsgQ> mService;
-    MessageQueueUnsync*  mQueue = nullptr;
     size_t mNumMessagesMax = 0;
 };
 
@@ -141,29 +286,26 @@
  * Verify that for an unsynchronized flavor of FMQ, multiple readers
  * can recover from a write overflow condition.
  */
-TEST_F(UnsynchronizedWriteClientMultiProcess, MultipleReadersAfterOverflow) {
+TYPED_TEST(UnsynchronizedWriteClientMultiProcess, MultipleReadersAfterOverflow) {
     const size_t dataLen = 16;
 
     pid_t pid;
     /* creating first reader process */
     if ((pid = fork()) == 0) {
-        sp<ITestMsgQ> testService;
-        MessageQueueUnsync*  queue = nullptr;
-        getQueue(&queue, &testService, true /* setupQueue */);
-        ASSERT_NE(testService, nullptr);
-        ASSERT_TRUE(testService->isRemote());
+        TypeParam* queue = nullptr;
+        auto service = this->getQueue(&queue, true /* setupQueue */);
+        ASSERT_NE(service, nullptr);
+        ASSERT_TRUE(service->isRemote());
         ASSERT_NE(queue, nullptr);
         ASSERT_TRUE(queue->isValid());
 
         size_t numMessagesMax = queue->getQuantumCount();
 
         // The following two writes will cause a write overflow.
-        auto ret = testService->requestWriteFmqUnsync(numMessagesMax);
-        ASSERT_TRUE(ret.isOk());
+        auto ret = this->requestWriteFmqUnsync(numMessagesMax, service);
         ASSERT_TRUE(ret);
 
-        ret = testService->requestWriteFmqUnsync(1);
-        ASSERT_TRUE(ret.isOk());
+        ret = this->requestWriteFmqUnsync(1, service);
         ASSERT_TRUE(ret);
 
         // The following read should fail due to the overflow.
@@ -175,8 +317,7 @@
          * overflow condition.
          */
         ASSERT_LT(dataLen, numMessagesMax);
-        ret = testService->requestWriteFmqUnsync(dataLen);
-        ASSERT_TRUE(ret.isOk());
+        ret = this->requestWriteFmqUnsync(dataLen, service);
         ASSERT_TRUE(ret);
 
         // Verify that the read is successful.
@@ -195,12 +336,10 @@
 
     // creating second reader process.
     if ((pid = fork()) == 0) {
-        sp<ITestMsgQ> testService;
-        MessageQueueUnsync* queue = nullptr;
-
-        getQueue(&queue, &testService, false /* setupQueue */);
-        ASSERT_NE(testService, nullptr);
-        ASSERT_TRUE(testService->isRemote());
+        TypeParam* queue = nullptr;
+        auto service = this->getQueue(&queue, false /* setupQueue */);
+        ASSERT_NE(service, nullptr);
+        ASSERT_TRUE(service->isRemote());
         ASSERT_NE(queue, nullptr);
         ASSERT_TRUE(queue->isValid());
 
@@ -212,8 +351,7 @@
          * Request another write to verify that the process that recover from
          * the overflow condition.
          */
-        auto ret = testService->requestWriteFmqUnsync(dataLen);
-        ASSERT_TRUE(ret.isOk());
+        auto ret = this->requestWriteFmqUnsync(dataLen, service);
         ASSERT_TRUE(ret);
 
         // verify that the read is successful.
@@ -232,25 +370,24 @@
  * Test that basic blocking works using readBlocking()/writeBlocking() APIs
  * using the EventFlag object owned by FMQ.
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWrite1) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWrite1) {
     const size_t dataLen = 64;
     uint16_t data[dataLen] = {0};
-
     /*
      * Request service to perform a blocking read. This call is oneway and will
      * return immediately.
      */
-    mService->requestBlockingRead(dataLen);
-    bool ret = mQueue->writeBlocking(data,
-                                     dataLen,
-                                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                     static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                     5000000000 /* timeOutNanos */);
+    this->mService->requestBlockingRead(dataLen);
+    bool ret = this->mQueue->writeBlocking(
+            data, dataLen, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
-    ret = mQueue->writeBlocking(data, mNumMessagesMax,
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                5000000000 /* timeOutNanos */);
+    ret = this->mQueue->writeBlocking(
+            data, this->mNumMessagesMax,
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
 }
 
@@ -259,29 +396,29 @@
  * using the EventFlag object owned by FMQ and using the default EventFlag
  * notification bit mask.
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWrite2) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWrite2) {
     const size_t dataLen = 64;
-    std::vector<uint16_t> data(mNumMessagesMax);
+    std::vector<uint16_t> data(this->mNumMessagesMax);
 
     /*
      * Request service to perform a blocking read using default EventFlag
      * notification bit mask. This call is oneway and will
      * return immediately.
      */
-    mService->requestBlockingReadDefaultEventFlagBits(dataLen);
+    this->mService->requestBlockingReadDefaultEventFlagBits(dataLen);
 
     /* Cause a context switch to allow service to block */
     sched_yield();
 
-    bool ret = mQueue->writeBlocking(&data[0],
-                                     dataLen);
+    bool ret = this->mQueue->writeBlocking(&data[0], dataLen);
     ASSERT_TRUE(ret);
 
     /*
      * If the blocking read was successful, another write of size
-     * mNumMessagesMax will succeed.
+     * this->mNumMessagesMax will succeed.
      */
-    ret = mQueue->writeBlocking(&data[0], mNumMessagesMax, 5000000000 /* timeOutNanos */);
+    ret = this->mQueue->writeBlocking(&data[0], this->mNumMessagesMax,
+                                      5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
 }
 
@@ -291,7 +428,7 @@
  * Each write operation writes the same amount of data as a single read
  * operation.
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat1) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat1) {
     const size_t dataLen = 64;
     uint16_t data[dataLen] = {0};
     bool ret = false;
@@ -301,20 +438,21 @@
      * return immediately.
      */
     const size_t writeCount = 1024;
-    mService->requestBlockingReadRepeat(dataLen, writeCount);
+    this->mService->requestBlockingReadRepeat(dataLen, writeCount);
 
     for (size_t i = 0; i < writeCount; i++) {
-        ret = mQueue->writeBlocking(data, dataLen,
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                    5000000000 /* timeOutNanos */);
+        ret = this->mQueue->writeBlocking(
+                data, dataLen, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+                5000000000 /* timeOutNanos */);
         ASSERT_TRUE(ret);
     }
 
-    ret = mQueue->writeBlocking(data, mNumMessagesMax,
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                5000000000 /* timeOutNanos */);
+    ret = this->mQueue->writeBlocking(
+            data, this->mNumMessagesMax,
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
 
     ASSERT_TRUE(ret);
 }
@@ -325,30 +463,30 @@
  * amount of data as a single write.
  *
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat2) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat2) {
     const size_t dataLen = 64;
     uint16_t data[dataLen] = {0};
     bool ret = false;
-
     /*
      * Request service to perform a blocking read. This call is oneway and will
      * return immediately.
      */
     const size_t writeCount = 1024;
-    mService->requestBlockingReadRepeat(dataLen*2, writeCount/2);
+    this->mService->requestBlockingReadRepeat(dataLen * 2, writeCount / 2);
 
     for (size_t i = 0; i < writeCount; i++) {
-        ret = mQueue->writeBlocking(data, dataLen,
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                    5000000000 /* timeOutNanos */);
+        ret = this->mQueue->writeBlocking(
+                data, dataLen, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+                5000000000 /* timeOutNanos */);
         ASSERT_TRUE(ret);
     }
 
-    ret = mQueue->writeBlocking(data, mNumMessagesMax,
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                5000000000 /* timeOutNanos */);
+    ret = this->mQueue->writeBlocking(
+            data, this->mNumMessagesMax,
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
 }
 
@@ -357,7 +495,7 @@
  * using the EventFlag object owned by FMQ. Each write operation writes twice
  * the amount of data as a single read.
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWriteRepeat3) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteRepeat3) {
     const size_t dataLen = 64;
     uint16_t data[dataLen] = {0};
     bool ret = false;
@@ -367,19 +505,20 @@
      * return immediately.
      */
     size_t writeCount = 1024;
-    mService->requestBlockingReadRepeat(dataLen/2, writeCount*2);
+    this->mService->requestBlockingReadRepeat(dataLen / 2, writeCount * 2);
 
     for (size_t i = 0; i < writeCount; i++) {
-        ret = mQueue->writeBlocking(data, dataLen,
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                    static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                    5000000000 /* timeOutNanos */);
+        ret = this->mQueue->writeBlocking(
+                data, dataLen, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+                5000000000 /* timeOutNanos */);
         ASSERT_TRUE(ret);
     }
-    ret = mQueue->writeBlocking(data, mNumMessagesMax,
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                                static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
-                                5000000000 /* timeOutNanos */);
+    ret = this->mQueue->writeBlocking(
+            data, this->mNumMessagesMax,
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY),
+            5000000000 /* timeOutNanos */);
     ASSERT_TRUE(ret);
 }
 
@@ -387,26 +526,23 @@
  * Test that writeBlocking()/readBlocking() APIs do not block on
  * attempts to write/read 0 messages and return true.
  */
-TEST_F(SynchronizedReadWriteClient, BlockingReadWriteZeroMessages) {
+TYPED_TEST(SynchronizedReadWriteClient, BlockingReadWriteZeroMessages) {
     uint16_t data = 0;
 
     /*
      * Trigger a blocking write for zero messages with no timeout.
      */
-    bool ret = mQueue->writeBlocking(
-            &data,
-            0,
-            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+    bool ret = this->mQueue->writeBlocking(
+            &data, 0, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
             static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
     ASSERT_TRUE(ret);
 
     /*
      * Trigger a blocking read for zero messages with no timeout.
      */
-    ret = mQueue->readBlocking(&data,
-                               0,
-                               static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
-                               static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
+    ret = this->mQueue->readBlocking(
+            &data, 0, static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL),
+            static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_EMPTY));
     ASSERT_TRUE(ret);
 }
 
@@ -414,13 +550,13 @@
  * Request mService to write a small number of messages
  * to the FMQ. Read and verify data.
  */
-TEST_F(SynchronizedReadWriteClient, SmallInputReaderTest1) {
+TYPED_TEST(SynchronizedReadWriteClient, SmallInputReaderTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
-    bool ret = mService->requestWriteFmqSync(dataLen);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
+    bool ret = this->requestWriteFmqSync(dataLen);
     ASSERT_TRUE(ret);
     uint16_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_TRUE(verifyData(readData, dataLen));
 }
 
@@ -429,16 +565,16 @@
  * to the FMQ. Read and verify each message using
  * beginRead/Commit read APIs.
  */
-TEST_F(SynchronizedReadWriteClient, SmallInputReaderTest2) {
+TYPED_TEST(SynchronizedReadWriteClient, SmallInputReaderTest2) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
-    auto ret = mService->requestWriteFmqSync(dataLen);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
+    auto ret = this->requestWriteFmqSync(dataLen);
 
-    ASSERT_TRUE(ret.isOk());
+    // ASSERT_TRUE(ret.isOk());
     ASSERT_TRUE(ret);
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginRead(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -452,39 +588,39 @@
         }
     }
 
-    ASSERT_TRUE(mQueue->commitRead(dataLen));
+    ASSERT_TRUE(this->mQueue->commitRead(dataLen));
 }
 
 /*
  * Write a small number of messages to FMQ. Request
- * mService to read and verify that the write was succesful.
+ * mService to read and verify that the write was successful.
  */
-TEST_F(SynchronizedReadWriteClient, SmallInputWriterTest1) {
+TYPED_TEST(SynchronizedReadWriteClient, SmallInputWriterTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
-    size_t originalCount = mQueue->availableToWrite();
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
+    size_t originalCount = this->mQueue->availableToWrite();
     uint16_t data[dataLen];
     initData(data, dataLen);
-    ASSERT_TRUE(mQueue->write(data, dataLen));
-    bool ret = mService->requestReadFmqSync(dataLen);
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
+    bool ret = this->requestReadFmqSync(dataLen);
     ASSERT_TRUE(ret);
-    size_t availableCount = mQueue->availableToWrite();
+    size_t availableCount = this->mQueue->availableToWrite();
     ASSERT_EQ(originalCount, availableCount);
 }
 
 /*
  * Write a small number of messages to FMQ using the beginWrite()/CommitWrite()
- * APIs. Request mService to read and verify that the write was succesful.
+ * APIs. Request mService to read and verify that the write was successful.
  */
-TEST_F(SynchronizedReadWriteClient, SmallInputWriterTest2) {
+TYPED_TEST(SynchronizedReadWriteClient, SmallInputWriterTest2) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
-    size_t originalCount = mQueue->availableToWrite();
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
+    size_t originalCount = this->mQueue->availableToWrite();
     uint16_t data[dataLen];
     initData(data, dataLen);
 
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(dataLen, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(dataLen, &tx));
 
     auto first = tx.getFirstRegion();
     auto second = tx.getSecondRegion();
@@ -501,24 +637,24 @@
         }
     }
 
-    ASSERT_TRUE(mQueue->commitWrite(dataLen));
+    ASSERT_TRUE(this->mQueue->commitWrite(dataLen));
 
-    auto ret = mService->requestReadFmqSync(dataLen);
-    ASSERT_TRUE(ret.isOk());
+    auto ret = this->requestReadFmqSync(dataLen);
+    // ASSERT_TRUE(ret.isOk());
     ASSERT_TRUE(ret);
-    size_t availableCount = mQueue->availableToWrite();
+    size_t availableCount = this->mQueue->availableToWrite();
     ASSERT_EQ(originalCount, availableCount);
 }
 
 /*
  * Verify that the FMQ is empty and read fails when it is empty.
  */
-TEST_F(SynchronizedReadWriteClient, ReadWhenEmpty) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWriteClient, ReadWhenEmpty) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t numMessages = 2;
-    ASSERT_LE(numMessages, mNumMessagesMax);
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
     uint16_t readData[numMessages];
-    ASSERT_FALSE(mQueue->read(readData, numMessages));
+    ASSERT_FALSE(this->mQueue->read(readData, numMessages));
 }
 
 /*
@@ -526,17 +662,17 @@
  * Write enough messages to fill it.
  * Verify availableToWrite() method returns is zero.
  * Try writing another message and verify that
- * the attempted write was unsuccesful. Request mService
+ * the attempted write was unsuccessful. Request mService
  * to read and verify the messages in the FMQ.
  */
 
-TEST_F(SynchronizedReadWriteClient, WriteWhenFull) {
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_FALSE(mQueue->write(&data[0], 1));
-    bool ret = mService->requestReadFmqSync(mNumMessagesMax);
+TYPED_TEST(SynchronizedReadWriteClient, WriteWhenFull) {
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_FALSE(this->mQueue->write(&data[0], 1));
+    bool ret = this->requestReadFmqSync(this->mNumMessagesMax);
     ASSERT_TRUE(ret);
 }
 
@@ -545,12 +681,12 @@
  * Request mService to write data equal to queue size.
  * Read and verify data in mQueue.
  */
-TEST_F(SynchronizedReadWriteClient, LargeInputTest1) {
-    bool ret = mService->requestWriteFmqSync(mNumMessagesMax);
+TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest1) {
+    bool ret = this->requestWriteFmqSync(this->mNumMessagesMax);
     ASSERT_TRUE(ret);
-    std::vector<uint16_t> readData(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&readData[0], mNumMessagesMax));
-    ASSERT_TRUE(verifyData(&readData[0], mNumMessagesMax));
+    std::vector<uint16_t> readData(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
+    ASSERT_TRUE(verifyData(&readData[0], this->mNumMessagesMax));
 }
 
 /*
@@ -558,15 +694,15 @@
  * Verify that the write fails. Verify that availableToRead() method
  * still returns 0 and verify that attempt to read fails.
  */
-TEST_F(SynchronizedReadWriteClient, LargeInputTest2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t numMessages = 2048;
-    ASSERT_GT(numMessages, mNumMessagesMax);
-    bool ret = mService->requestWriteFmqSync(numMessages);
+    ASSERT_GT(numMessages, this->mNumMessagesMax);
+    bool ret = this->requestWriteFmqSync(numMessages);
     ASSERT_FALSE(ret);
     uint16_t readData;
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    ASSERT_FALSE(mQueue->read(&readData, 1));
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    ASSERT_FALSE(this->mQueue->read(&readData, 1));
 }
 
 /*
@@ -577,14 +713,14 @@
  * Request mService to read. Verify read count.
  */
 
-TEST_F(SynchronizedReadWriteClient, LargeInputTest3) {
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_FALSE(mQueue->write(&data[0], 1));
+TYPED_TEST(SynchronizedReadWriteClient, LargeInputTest3) {
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_FALSE(this->mQueue->write(&data[0], 1));
 
-    bool ret = mService->requestReadFmqSync(mNumMessagesMax);
+    bool ret = this->requestReadFmqSync(this->mNumMessagesMax);
     ASSERT_TRUE(ret);
 }
 
@@ -592,19 +728,19 @@
  * Confirm that the FMQ is empty. Request mService to write to FMQ.
  * Do multiple reads to empty FMQ and verify data.
  */
-TEST_F(SynchronizedReadWriteClient, MultipleRead) {
+TYPED_TEST(SynchronizedReadWriteClient, MultipleRead) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t numMessages = chunkSize * chunkNum;
-    ASSERT_LE(numMessages, mNumMessagesMax);
-    size_t availableToRead = mQueue->availableToRead();
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
+    size_t availableToRead = this->mQueue->availableToRead();
     size_t expectedCount = 0;
     ASSERT_EQ(expectedCount, availableToRead);
-    bool ret = mService->requestWriteFmqSync(numMessages);
+    bool ret = this->requestWriteFmqSync(numMessages);
     ASSERT_TRUE(ret);
     uint16_t readData[numMessages] = {};
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
     }
     ASSERT_TRUE(verifyData(readData, numMessages));
 }
@@ -613,18 +749,18 @@
  * Write to FMQ in bursts.
  * Request mService to read data. Verify the read was successful.
  */
-TEST_F(SynchronizedReadWriteClient, MultipleWrite) {
+TYPED_TEST(SynchronizedReadWriteClient, MultipleWrite) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t numMessages = chunkSize * chunkNum;
-    ASSERT_LE(numMessages, mNumMessagesMax);
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
     uint16_t data[numMessages];
     initData(&data[0], numMessages);
 
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
     }
-    bool ret = mService->requestReadFmqSync(numMessages);
+    bool ret = this->requestReadFmqSync(numMessages);
     ASSERT_TRUE(ret);
 }
 
@@ -634,15 +770,15 @@
  * Write mNumMessagesMax messages into the queue. This should cause a
  * wrap around. Request mService to read and verify the data.
  */
-TEST_F(SynchronizedReadWriteClient, ReadWriteWrapAround) {
-    size_t numMessages = mNumMessagesMax / 2;
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], numMessages));
-    bool ret = mService->requestReadFmqSync(numMessages);
+TYPED_TEST(SynchronizedReadWriteClient, ReadWriteWrapAround) {
+    size_t numMessages = this->mNumMessagesMax / 2;
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
+    bool ret = this->requestReadFmqSync(numMessages);
     ASSERT_TRUE(ret);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ret = mService->requestReadFmqSync(mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ret = this->requestReadFmqSync(this->mNumMessagesMax);
     ASSERT_TRUE(ret);
 }
 
@@ -654,74 +790,73 @@
  * Write mNumMessagesMax messages into the queue. This will cause a
  * wrap around. Read and verify the data.
  */
-TEST_F(SynchronizedReadWriteClient, ReadWriteWrapAround2) {
-    size_t numMessages = mNumMessagesMax / 2;
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], numMessages));
-    auto ret = mService->requestReadFmqSync(numMessages);
+TYPED_TEST(SynchronizedReadWriteClient, ReadWriteWrapAround2) {
+    size_t numMessages = this->mNumMessagesMax / 2;
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
+    auto ret = this->requestReadFmqSync(numMessages);
 
-    ASSERT_TRUE(ret.isOk());
+    // ASSERT_TRUE(ret.isOk());
     ASSERT_TRUE(ret);
 
     /*
      * The next write and read will have to deal with with wrap arounds.
      */
-    MessageQueueSync::MemTransaction tx;
-    ASSERT_TRUE(mQueue->beginWrite(mNumMessagesMax, &tx));
+    typename TypeParam::MemTransaction tx;
+    ASSERT_TRUE(this->mQueue->beginWrite(this->mNumMessagesMax, &tx));
 
-    ASSERT_EQ(tx.getFirstRegion().getLength() + tx.getSecondRegion().getLength(),  mNumMessagesMax);
+    ASSERT_EQ(tx.getFirstRegion().getLength() + tx.getSecondRegion().getLength(),
+              this->mNumMessagesMax);
 
-    for (size_t i = 0; i < mNumMessagesMax; i++) {
+    for (size_t i = 0; i < this->mNumMessagesMax; i++) {
         uint16_t* ptr = tx.getSlot(i);
         *ptr = data[i];
     }
 
-    ASSERT_TRUE(mQueue->commitWrite(mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->commitWrite(this->mNumMessagesMax));
 
-    ret = mService->requestReadFmqSync(mNumMessagesMax);
-
-    ASSERT_TRUE(ret.isOk());
+    ret = this->requestReadFmqSync(this->mNumMessagesMax);
     ASSERT_TRUE(ret);
 }
 
 /*
- * Request mService to write a small number of messages
+ * Request this->mService to write a small number of messages
  * to the FMQ. Read and verify data.
  */
-TEST_F(UnsynchronizedWriteClient, SmallInputReaderTest1) {
+TYPED_TEST(UnsynchronizedWriteClient, SmallInputReaderTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
-    bool ret = mService->requestWriteFmqUnsync(dataLen);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
+    bool ret = this->requestWriteFmqUnsync(dataLen, this->mService);
     ASSERT_TRUE(ret);
     uint16_t readData[dataLen] = {};
-    ASSERT_TRUE(mQueue->read(readData, dataLen));
+    ASSERT_TRUE(this->mQueue->read(readData, dataLen));
     ASSERT_TRUE(verifyData(readData, dataLen));
 }
 
 /*
  * Write a small number of messages to FMQ. Request
- * mService to read and verify that the write was succesful.
+ * this->mService to read and verify that the write was successful.
  */
-TEST_F(UnsynchronizedWriteClient, SmallInputWriterTest1) {
+TYPED_TEST(UnsynchronizedWriteClient, SmallInputWriterTest1) {
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
     uint16_t data[dataLen];
     initData(data, dataLen);
-    ASSERT_TRUE(mQueue->write(data, dataLen));
-    bool ret = mService->requestReadFmqUnsync(dataLen);
+    ASSERT_TRUE(this->mQueue->write(data, dataLen));
+    bool ret = this->requestReadFmqUnsync(dataLen, this->mService);
     ASSERT_TRUE(ret);
 }
 
 /*
  * Verify that the FMQ is empty and read fails when it is empty.
  */
-TEST_F(UnsynchronizedWriteClient, ReadWhenEmpty) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
+TYPED_TEST(UnsynchronizedWriteClient, ReadWhenEmpty) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
     const size_t numMessages = 2;
-    ASSERT_LE(numMessages, mNumMessagesMax);
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
     uint16_t readData[numMessages];
-    ASSERT_FALSE(mQueue->read(readData, numMessages));
+    ASSERT_FALSE(this->mQueue->read(readData, numMessages));
 }
 
 /*
@@ -729,144 +864,143 @@
  * Write enough messages to fill it.
  * Verify availableToWrite() method returns is zero.
  * Try writing another message and verify that
- * the attempted write was successful. Request mService
- * to read the messages in the FMQ and verify that it is unsuccesful.
+ * the attempted write was successful. Request this->mService
+ * to read the messages in the FMQ and verify that it is unsuccessful.
  */
 
-TEST_F(UnsynchronizedWriteClient, WriteWhenFull) {
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_TRUE(mQueue->write(&data[0], 1));
-    bool ret = mService->requestReadFmqUnsync(mNumMessagesMax);
+TYPED_TEST(UnsynchronizedWriteClient, WriteWhenFull) {
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_TRUE(this->mQueue->write(&data[0], 1));
+    bool ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_FALSE(ret);
 }
 
 /*
  * Verify FMQ is empty.
- * Request mService to write data equal to queue size.
- * Read and verify data in mQueue.
+ * Request this->mService to write data equal to queue size.
+ * Read and verify data in this->mQueue.
  */
-TEST_F(UnsynchronizedWriteClient, LargeInputTest1) {
-    bool ret = mService->requestWriteFmqUnsync(mNumMessagesMax);
+TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest1) {
+    bool ret = this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_TRUE(ret);
-    std::vector<uint16_t> data(mNumMessagesMax);
-    ASSERT_TRUE(mQueue->read(&data[0], mNumMessagesMax));
-    ASSERT_TRUE(verifyData(&data[0], mNumMessagesMax));
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->read(&data[0], this->mNumMessagesMax));
+    ASSERT_TRUE(verifyData(&data[0], this->mNumMessagesMax));
 }
 
 /*
- * Request mService to write more than maximum number of messages to the FMQ.
+ * Request this->mService to write more than maximum number of messages to the FMQ.
  * Verify that the write fails. Verify that availableToRead() method
  * still returns 0 and verify that attempt to read fails.
  */
-TEST_F(UnsynchronizedWriteClient, LargeInputTest2) {
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    const size_t numMessages = mNumMessagesMax + 1;
-    bool ret = mService->requestWriteFmqUnsync(numMessages);
+TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest2) {
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    const size_t numMessages = this->mNumMessagesMax + 1;
+    bool ret = this->requestWriteFmqUnsync(numMessages, this->mService);
     ASSERT_FALSE(ret);
     uint16_t readData;
-    ASSERT_EQ(0UL, mQueue->availableToRead());
-    ASSERT_FALSE(mQueue->read(&readData, 1));
+    ASSERT_EQ(0UL, this->mQueue->availableToRead());
+    ASSERT_FALSE(this->mQueue->read(&readData, 1));
 }
 
 /*
  * Write until FMQ is full.
  * Verify that the number of messages available to write
- * is equal to mNumMessagesMax.
- * Verify that another write attempt is succesful.
- * Request mService to read. Verify that read is unsuccessful.
- * Perform another write and verify that the read is succesful
+ * is equal to this->mNumMessagesMax.
+ * Verify that another write attempt is successful.
+ * Request this->mService to read. Verify that read is unsuccessful.
+ * Perform another write and verify that the read is successful
  * to check if the reader process can recover from the error condition.
  */
-TEST_F(UnsynchronizedWriteClient, LargeInputTest3) {
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ASSERT_EQ(0UL, mQueue->availableToWrite());
-    ASSERT_TRUE(mQueue->write(&data[0], 1));
+TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest3) {
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ASSERT_EQ(0UL, this->mQueue->availableToWrite());
+    ASSERT_TRUE(this->mQueue->write(&data[0], 1));
 
-    bool ret = mService->requestReadFmqUnsync(mNumMessagesMax);
+    bool ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_FALSE(ret);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
 
-    ret = mService->requestReadFmqUnsync(mNumMessagesMax);
+    ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_TRUE(ret);
 }
 
 /*
- * Confirm that the FMQ is empty. Request mService to write to FMQ.
+ * Confirm that the FMQ is empty. Request this->mService to write to FMQ.
  * Do multiple reads to empty FMQ and verify data.
  */
-TEST_F(UnsynchronizedWriteClient, MultipleRead) {
+TYPED_TEST(UnsynchronizedWriteClient, MultipleRead) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t numMessages = chunkSize * chunkNum;
-    ASSERT_LE(numMessages, mNumMessagesMax);
-    size_t availableToRead = mQueue->availableToRead();
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
+    size_t availableToRead = this->mQueue->availableToRead();
     size_t expectedCount = 0;
     ASSERT_EQ(expectedCount, availableToRead);
-    bool ret = mService->requestWriteFmqUnsync(numMessages);
+    bool ret = this->requestWriteFmqUnsync(numMessages, this->mService);
     ASSERT_TRUE(ret);
     uint16_t readData[numMessages] = {};
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->read(readData + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->read(readData + i * chunkSize, chunkSize));
     }
     ASSERT_TRUE(verifyData(readData, numMessages));
 }
 
 /*
  * Write to FMQ in bursts.
- * Request mService to read data, verify that it was successful.
+ * Request this->mService to read data, verify that it was successful.
  */
-TEST_F(UnsynchronizedWriteClient, MultipleWrite) {
+TYPED_TEST(UnsynchronizedWriteClient, MultipleWrite) {
     const size_t chunkSize = 100;
     const size_t chunkNum = 5;
     const size_t numMessages = chunkSize * chunkNum;
-    ASSERT_LE(numMessages, mNumMessagesMax);
+    ASSERT_LE(numMessages, this->mNumMessagesMax);
     uint16_t data[numMessages];
     initData(data, numMessages);
     for (size_t i = 0; i < chunkNum; i++) {
-        ASSERT_TRUE(mQueue->write(data + i * chunkSize, chunkSize));
+        ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
     }
-    bool ret = mService->requestReadFmqUnsync(numMessages);
+    bool ret = this->requestReadFmqUnsync(numMessages, this->mService);
     ASSERT_TRUE(ret);
 }
 
 /*
  * Write enough messages into the FMQ to fill half of it.
- * Request mService to read back the same.
- * Write mNumMessagesMax messages into the queue. This should cause a
- * wrap around. Request mService to read and verify the data.
+ * Request this->mService to read back the same.
+ * Write this->mNumMessagesMax messages into the queue. This should cause a
+ * wrap around. Request this->mService to read and verify the data.
  */
-TEST_F(UnsynchronizedWriteClient, ReadWriteWrapAround) {
-    size_t numMessages = mNumMessagesMax / 2;
-    std::vector<uint16_t> data(mNumMessagesMax);
-    initData(&data[0], mNumMessagesMax);
-    ASSERT_TRUE(mQueue->write(&data[0], numMessages));
-    bool ret = mService->requestReadFmqUnsync(numMessages);
+TYPED_TEST(UnsynchronizedWriteClient, ReadWriteWrapAround) {
+    size_t numMessages = this->mNumMessagesMax / 2;
+    std::vector<uint16_t> data(this->mNumMessagesMax);
+    initData(&data[0], this->mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
+    bool ret = this->requestReadFmqUnsync(numMessages, this->mService);
     ASSERT_TRUE(ret);
-    ASSERT_TRUE(mQueue->write(&data[0], mNumMessagesMax));
-    ret = mService->requestReadFmqUnsync(mNumMessagesMax);
+    ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+    ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_TRUE(ret);
 }
 
 /*
- * Request mService to write a small number of messages
+ * Request this->mService to write a small number of messages
  * to the FMQ. Read and verify data from two threads configured
  * as readers to the FMQ.
  */
-TEST_F(UnsynchronizedWriteClient, SmallInputMultipleReaderTest) {
-    auto desc = mQueue->getDesc();
-    std::unique_ptr<MessageQueue<uint16_t, kUnsynchronizedWrite>> mQueue2(
-            new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite>(*desc));
-    ASSERT_NE(nullptr, mQueue2.get());
+TYPED_TEST(UnsynchronizedWriteClient, SmallInputMultipleReaderTest) {
+    TypeParam* mQueue2 = this->newQueue();
+
+    ASSERT_NE(nullptr, mQueue2);
 
     const size_t dataLen = 16;
-    ASSERT_LE(dataLen, mNumMessagesMax);
+    ASSERT_LE(dataLen, this->mNumMessagesMax);
 
-    bool ret = mService->requestWriteFmqUnsync(dataLen);
+    bool ret = this->requestWriteFmqUnsync(dataLen, this->mService);
     ASSERT_TRUE(ret);
 
     pid_t pid;
@@ -880,36 +1014,34 @@
         ASSERT_GT(pid,
                   0 /* parent should see PID greater than 0 for a good fork */);
         uint16_t readData[dataLen] = {};
-        ASSERT_TRUE(mQueue->read(readData, dataLen));
+        ASSERT_TRUE(this->mQueue->read(readData, dataLen));
         ASSERT_TRUE(verifyData(readData, dataLen));
     }
 }
 
 /*
- * Request mService to write into the FMQ until it is full.
- * Request mService to do another write and verify it is successful.
+ * Request this->mService to write into the FMQ until it is full.
+ * Request this->mService to do another write and verify it is successful.
  * Use two reader processes to read and verify that both fail.
  */
-TEST_F(UnsynchronizedWriteClient, OverflowNotificationTest) {
-    auto desc = mQueue->getDesc();
-    std::unique_ptr<MessageQueue<uint16_t, kUnsynchronizedWrite>> mQueue2(
-            new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite>(*desc));
-    ASSERT_NE(nullptr, mQueue2.get());
+TYPED_TEST(UnsynchronizedWriteClient, OverflowNotificationTest) {
+    TypeParam* mQueue2 = this->newQueue();
+    ASSERT_NE(nullptr, mQueue2);
 
-    bool ret = mService->requestWriteFmqUnsync(mNumMessagesMax);
+    bool ret = this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService);
     ASSERT_TRUE(ret);
-    ret = mService->requestWriteFmqUnsync(1);
+    ret = this->requestWriteFmqUnsync(1, this->mService);
     ASSERT_TRUE(ret);
 
     pid_t pid;
     if ((pid = fork()) == 0) {
         /* child process */
-        std::vector<uint16_t> readData(mNumMessagesMax);
-        ASSERT_FALSE(mQueue2->read(&readData[0], mNumMessagesMax));
+        std::vector<uint16_t> readData(this->mNumMessagesMax);
+        ASSERT_FALSE(mQueue2->read(&readData[0], this->mNumMessagesMax));
         exit(0);
     } else {
         ASSERT_GT(pid, 0/* parent should see PID greater than 0 for a good fork */);
-        std::vector<uint16_t> readData(mNumMessagesMax);
-        ASSERT_FALSE(mQueue->read(&readData[0], mNumMessagesMax));
+        std::vector<uint16_t> readData(this->mNumMessagesMax);
+        ASSERT_FALSE(this->mQueue->read(&readData[0], this->mNumMessagesMax));
     }
 }