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/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