Move FMQ benchmark/test services to hardware/interfaces

Bug: 32284445
Test: Built and ran FMQ benchmarks

Change-Id: Ia6bacf21d276b55e4e590dc96f348464f2098992
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index 692edda..16018ac 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -1,3 +1,18 @@
+//
+// Copyright (C) 2017 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.
+
 cc_library_shared {
     name: "android.hardware.tests.msgq@1.0-impl",
     defaults: ["hidl_defaults"],
@@ -5,6 +20,7 @@
     proprietary: true,
     srcs: [
         "TestMsgQ.cpp",
+        "BenchmarkMsgQ.cpp"
     ],
     shared_libs: [
         "libbase",
@@ -18,3 +34,35 @@
         "android.hidl.base@1.0",
     ],
 }
+
+cc_test {
+    name: "android.hardware.tests.msgq@1.0-service-benchmark",
+    srcs: ["mq_benchmark_service.cpp"],
+    gtest: false,
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.msgq@1.0"
+    ],
+}
+
+cc_test {
+    name: "android.hardware.tests.msgq@1.0-service-test",
+    srcs: ["mq_test_service.cpp"],
+    gtest: false,
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.msgq@1.0"
+    ],
+}
diff --git a/tests/msgq/1.0/default/BenchmarkMsgQ.cpp b/tests/msgq/1.0/default/BenchmarkMsgQ.cpp
new file mode 100644
index 0000000..43e6fcc
--- /dev/null
+++ b/tests/msgq/1.0/default/BenchmarkMsgQ.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 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 "BenchmarkMsgQ.h"
+#include <iostream>
+#include <thread>
+#include <fmq/MessageQueue.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace msgq {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ follow.
+Return<void> BenchmarkMsgQ::configureClientInboxSyncReadWrite(
+        configureClientInboxSyncReadWrite_cb _hidl_cb) {
+    static constexpr size_t kNumElementsInQueue = 16 * 1024;
+    mFmqOutbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t,
+               kSynchronizedReadWrite>(kNumElementsInQueue);
+    if (mFmqOutbox == nullptr) {
+        _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>(
+                std::vector<android::hardware::GrantorDescriptor>(),
+                nullptr /* nhandle */, 0 /* size */));
+    } else {
+        _hidl_cb(true /* ret */, *mFmqOutbox->getDesc());
+    }
+
+    return Void();
+}
+
+Return<void> BenchmarkMsgQ::configureClientOutboxSyncReadWrite(
+        configureClientOutboxSyncReadWrite_cb _hidl_cb) {
+    static constexpr size_t kNumElementsInQueue = 16 * 1024;
+    mFmqInbox = new (std::nothrow) android::hardware::MessageQueue<uint8_t,
+              kSynchronizedReadWrite>(kNumElementsInQueue);
+    if ((mFmqInbox == nullptr) || (mFmqInbox->isValid() == false)) {
+        _hidl_cb(false /* ret */, android::hardware::MQDescriptorSync<uint8_t>(
+                std::vector<android::hardware::GrantorDescriptor>(),
+                nullptr /* nhandle */, 0 /* size */));
+    } else {
+        _hidl_cb(true /* ret */, *mFmqInbox->getDesc());
+    }
+
+    return Void();
+}
+
+Return<bool> BenchmarkMsgQ::requestWrite(int32_t count) {
+    uint8_t* data = new (std::nothrow) uint8_t[count];
+    for (int i = 0; i < count; i++) {
+        data[i] = i;
+    }
+    bool result = mFmqOutbox->write(data, count);
+    delete[] data;
+    return result;
+}
+
+Return<bool> BenchmarkMsgQ::requestRead(int32_t count) {
+    uint8_t* data = new (std::nothrow) uint8_t[count];
+    bool result = mFmqInbox->read(data, count);
+    delete[] data;
+    return result;
+}
+
+Return<void> BenchmarkMsgQ::benchmarkPingPong(uint32_t numIter) {
+    std::thread(QueuePairReadWrite<kSynchronizedReadWrite>, mFmqInbox,
+                mFmqOutbox, numIter)
+            .detach();
+    return Void();
+}
+
+Return<void> BenchmarkMsgQ::benchmarkServiceWriteClientRead(uint32_t numIter) {
+    if (mTimeData) delete[] mTimeData;
+    mTimeData = new (std::nothrow) int64_t[numIter];
+    std::thread(QueueWriter<kSynchronizedReadWrite>, mFmqOutbox,
+                mTimeData, numIter).detach();
+    return Void();
+}
+
+Return<void> BenchmarkMsgQ::sendTimeData(const hidl_vec<int64_t>& clientRcvTimeArray) {
+    int64_t accumulatedTime = 0;
+
+    for (uint32_t i = 0; i < clientRcvTimeArray.size(); i++) {
+        std::chrono::time_point<std::chrono::high_resolution_clock>
+                clientRcvTime((std::chrono::high_resolution_clock::duration(
+                        clientRcvTimeArray[i])));
+        std::chrono::time_point<std::chrono::high_resolution_clock>serverSendTime(
+                (std::chrono::high_resolution_clock::duration(mTimeData[i])));
+        accumulatedTime += static_cast<int64_t>(
+                std::chrono::duration_cast<std::chrono::nanoseconds>(clientRcvTime -
+                                                                     serverSendTime).count());
+    }
+
+    accumulatedTime /= clientRcvTimeArray.size();
+    std::cout << "Average service to client write to read delay::"
+         << accumulatedTime << "ns" << std::endl;
+    return Void();
+}
+
+template <MQFlavor flavor>
+void BenchmarkMsgQ::QueueWriter(android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox,
+                                int64_t* mTimeData,
+                                uint32_t numIter) {
+    uint8_t data[kPacketSize64];
+    uint32_t numWrites = 0;
+
+    while (numWrites < numIter) {
+        do {
+            mTimeData[numWrites] =
+                    std::chrono::high_resolution_clock::now().time_since_epoch().count();
+        } while (mFmqOutbox->write(data, kPacketSize64) == false);
+        numWrites++;
+    }
+}
+
+template <MQFlavor flavor>
+void BenchmarkMsgQ::QueuePairReadWrite(
+        android::hardware::MessageQueue<uint8_t, flavor>* mFmqInbox,
+        android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox,
+        uint32_t numIter) {
+    uint8_t data[kPacketSize64];
+    uint32_t numRoundTrips = 0;
+
+    while (numRoundTrips < numIter) {
+        while (mFmqInbox->read(data, kPacketSize64) == false)
+            ;
+        while (mFmqOutbox->write(data, kPacketSize64) == false)
+            ;
+        numRoundTrips++;
+    }
+}
+
+IBenchmarkMsgQ* HIDL_FETCH_IBenchmarkMsgQ(const char* /* name */) {
+    return new BenchmarkMsgQ();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace msgq
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/msgq/1.0/default/BenchmarkMsgQ.h b/tests/msgq/1.0/default/BenchmarkMsgQ.h
new file mode 100644
index 0000000..2cbe93c
--- /dev/null
+++ b/tests/msgq/1.0/default/BenchmarkMsgQ.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_HARDWARE_TESTS_MSGQ_V1_0_BENCHMARKMSGQ_H
+#define ANDROID_HARDWARE_TESTS_MSGQ_V1_0_BENCHMARKMSGQ_H
+
+#include <android/hardware/tests/msgq/1.0/IBenchmarkMsgQ.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <fmq/MessageQueue.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace msgq {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MQFlavor;
+
+struct BenchmarkMsgQ : public IBenchmarkMsgQ {
+    /*
+     * The various packet sizes used are as follows.
+     */
+    enum PacketSizes {
+        kPacketSize64 = 64,
+        kPacketSize128 = 128,
+        kPacketSize256 = 256,
+        kPacketSize512 = 512,
+        kPacketSize1024 = 1024
+    };
+    // Methods from ::android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ follow.
+    Return<void> configureClientInboxSyncReadWrite(configureClientInboxSyncReadWrite_cb _hidl_cb) override;
+    Return<void> configureClientOutboxSyncReadWrite(configureClientOutboxSyncReadWrite_cb _hidl_cb) override;
+    Return<bool> requestWrite(int32_t count) override;
+    Return<bool> requestRead(int32_t count) override;
+    Return<void> benchmarkPingPong(uint32_t numIter) override;
+    Return<void> benchmarkServiceWriteClientRead(uint32_t numIter) override;
+    Return<void> sendTimeData(const hidl_vec<int64_t>& timeData) override;
+
+     /*
+     * This method writes numIter packets into the mFmqOutbox queue
+     * and notes the time before each write in the mTimeData array. It will
+     * be used to calculate the average server to client write to read delay.
+     */
+    template <MQFlavor flavor>
+    static void QueueWriter(android::hardware::MessageQueue<uint8_t, flavor>*
+                     mFmqOutbox, int64_t* mTimeData, uint32_t numIter);
+    /*
+     * The method reads a packet from the inbox queue and writes the same
+     * into the outbox queue. The client will calculate the average time taken
+     * for each iteration which consists of two write and two read operations.
+     */
+    template <MQFlavor flavor>
+    static void QueuePairReadWrite(
+            android::hardware::MessageQueue<uint8_t, flavor>* mFmqInbox,
+            android::hardware::MessageQueue<uint8_t, flavor>* mFmqOutbox,
+            uint32_t numIter);
+
+private:
+    android::hardware::MessageQueue<uint8_t, kSynchronizedReadWrite>* mFmqInbox;
+    android::hardware::MessageQueue<uint8_t, kSynchronizedReadWrite>* mFmqOutbox;
+    int64_t* mTimeData;
+};
+
+extern "C" IBenchmarkMsgQ* HIDL_FETCH_IBenchmarkMsgQ(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace msgq
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_MSGQ_V1_0_BENCHMARKMSGQ_H
diff --git a/tests/msgq/1.0/default/TestMsgQ.cpp b/tests/msgq/1.0/default/TestMsgQ.cpp
index 7cc4f5b..6fd4fc6 100644
--- a/tests/msgq/1.0/default/TestMsgQ.cpp
+++ b/tests/msgq/1.0/default/TestMsgQ.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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 "TestMsgQ.h"
 
 namespace android {
diff --git a/tests/msgq/1.0/default/TestMsgQ.h b/tests/msgq/1.0/default/TestMsgQ.h
index 760d931..86e4ac4 100644
--- a/tests/msgq/1.0/default/TestMsgQ.h
+++ b/tests/msgq/1.0/default/TestMsgQ.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
 #ifndef ANDROID_HARDWARE_TESTS_MSGQ_V1_0_TESTMSGQ_H
 #define ANDROID_HARDWARE_TESTS_MSGQ_V1_0_TESTMSGQ_H
 
diff --git a/tests/msgq/1.0/default/mq_benchmark_service.cpp b/tests/msgq/1.0/default/mq_benchmark_service.cpp
new file mode 100644
index 0000000..b9be81b
--- /dev/null
+++ b/tests/msgq/1.0/default/mq_benchmark_service.cpp
@@ -0,0 +1,28 @@
+/*
+* Copyright (C) 2017 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.
+*/
+
+#define LOG_TAG "FMQ_Benchmarks"
+
+#include <android/hardware/tests/msgq/1.0/IBenchmarkMsgQ.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::hardware::tests::msgq::V1_0::IBenchmarkMsgQ;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IBenchmarkMsgQ>();
+}
diff --git a/tests/msgq/1.0/default/mq_test_service.cpp b/tests/msgq/1.0/default/mq_test_service.cpp
new file mode 100644
index 0000000..b5cb662
--- /dev/null
+++ b/tests/msgq/1.0/default/mq_test_service.cpp
@@ -0,0 +1,28 @@
+/*
+* Copyright (C) 2017 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.
+*/
+
+#define LOG_TAG "FMQ_UnitTests"
+
+#include <android/hardware/tests/msgq/1.0/ITestMsgQ.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::hardware::tests::msgq::V1_0::ITestMsgQ;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<ITestMsgQ>();
+}