Refactor SensorsTestSharedMemory

Extracts SensorsTestSharedMemory so that it can be used by other
versions of the sensors tests.

Bug: 111070257
Test: Build
Change-Id: I03df7462302d4ab0ea647e0d7688a46bf0e06dc1
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index 6c25e47..f603934 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -19,6 +19,7 @@
     srcs: [
         "GrallocWrapper.cpp",
         "SensorsHidlEnvironmentBase.cpp",
+        "SensorsTestSharedMemory.cpp",
     ],
     export_include_dirs: [
         "include",
@@ -33,4 +34,3 @@
         "VtsHalHidlTargetTestBase",
     ],
 }
-
diff --git a/sensors/common/vts/utils/OWNERS b/sensors/common/vts/utils/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/utils/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
new file mode 100644
index 0000000..5096498
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 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 "SensorsTestSharedMemory.h"
+
+#include <log/log.h>
+
+#include <sys/mman.h>
+#include <cinttypes>
+
+using namespace ::android::hardware::sensors::V1_0;
+
+SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
+    SharedMemInfo mem = {.type = mType,
+                         .format = SharedMemFormat::SENSORS_EVENT,
+                         .size = static_cast<uint32_t>(mSize),
+                         .memoryHandle = mNativeHandle};
+    return mem;
+}
+
+char* SensorsTestSharedMemory::getBuffer() const {
+    return mBuffer;
+}
+
+std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
+    constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+    constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
+    constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
+    constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
+    constexpr size_t kOffsetAtomicCounter =
+        static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
+    constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
+    constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
+
+    std::vector<Event> events;
+    std::vector<float> data(16);
+
+    while (offset + kEventSize <= mSize) {
+        int64_t atomicCounter =
+            *reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
+        if (atomicCounter <= lastCounter) {
+            ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
+                  lastCounter);
+            break;
+        }
+
+        int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
+        if (size != kEventSize) {
+            // unknown error, events parsed may be wrong, remove all
+            events.clear();
+            break;
+        }
+
+        int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
+        int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
+        int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
+
+        ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
+              ", timestamp %" PRId64,
+              offset, atomicCounter, token, type, timestamp);
+
+        Event event = {
+            .timestamp = timestamp,
+            .sensorHandle = token,
+            .sensorType = static_cast<SensorType>(type),
+        };
+        event.u.data = android::hardware::hidl_array<float, 16>(
+            reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
+
+        events.push_back(event);
+
+        lastCounter = atomicCounter;
+        offset += kEventSize;
+    }
+
+    return events;
+}
+
+SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
+    : mType(type), mSize(0), mBuffer(nullptr) {
+    native_handle_t* handle = nullptr;
+    char* buffer = nullptr;
+    switch (type) {
+        case SharedMemType::ASHMEM: {
+            int fd;
+            handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
+            if (handle != nullptr) {
+                handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
+                if (handle->data[0] > 0) {
+                    // memory is pinned by default
+                    buffer = static_cast<char*>(
+                        ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+                    if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
+                        break;
+                    }
+                    ::native_handle_close(handle);
+                }
+                ::native_handle_delete(handle);
+                handle = nullptr;
+            }
+            break;
+        }
+        case SharedMemType::GRALLOC: {
+            mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
+            if (mGrallocWrapper->getAllocator() == nullptr ||
+                mGrallocWrapper->getMapper() == nullptr) {
+                break;
+            }
+            using android::hardware::graphics::common::V1_0::BufferUsage;
+            using android::hardware::graphics::common::V1_0::PixelFormat;
+            mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
+                .width = static_cast<uint32_t>(size),
+                .height = 1,
+                .layerCount = 1,
+                .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
+                                               BufferUsage::CPU_READ_OFTEN),
+                .format = PixelFormat::BLOB};
+
+            handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
+            if (handle != nullptr) {
+                mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
+                                              static_cast<int32_t>(buf_desc_info.height)};
+                buffer = static_cast<char*>(
+                    mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
+                if (buffer != nullptr) {
+                    break;
+                }
+                mGrallocWrapper->freeBuffer(handle);
+                handle = nullptr;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+
+    if (buffer != nullptr) {
+        mNativeHandle = handle;
+        mSize = size;
+        mBuffer = buffer;
+    }
+}
+
+SensorsTestSharedMemory::~SensorsTestSharedMemory() {
+    switch (mType) {
+        case SharedMemType::ASHMEM: {
+            if (mSize != 0) {
+                ::munmap(mBuffer, mSize);
+                mBuffer = nullptr;
+
+                ::native_handle_close(mNativeHandle);
+                ::native_handle_delete(mNativeHandle);
+
+                mNativeHandle = nullptr;
+                mSize = 0;
+            }
+            break;
+        }
+        case SharedMemType::GRALLOC: {
+            if (mSize != 0) {
+                mGrallocWrapper->unlock(mNativeHandle);
+                mGrallocWrapper->freeBuffer(mNativeHandle);
+
+                mNativeHandle = nullptr;
+                mSize = 0;
+            }
+            break;
+        }
+        default: {
+            if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
+                ALOGE(
+                    "SensorsTestSharedMemory %p not properly destructed: "
+                    "type %d, native handle %p, size %zu, buffer %p",
+                    this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+            }
+            break;
+        }
+    }
+}
+
+SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
+    constexpr size_t kMaxSize = 128 * 1024 * 1024;  // sensor test should not need more than 128M
+    if (size == 0 || size >= kMaxSize) {
+        return nullptr;
+    }
+
+    auto m = new SensorsTestSharedMemory(type, size);
+    if (m->mSize != size || m->mBuffer == nullptr) {
+        delete m;
+        m = nullptr;
+    }
+    return m;
+}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
new file mode 100644
index 0000000..055b8e7
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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_SENSORS_TEST_SHARED_MEMORY_H
+#define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+
+#include "GrallocWrapper.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cutils/ashmem.h>
+
+class SensorsTestSharedMemory {
+    using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType;
+    using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+    using Event = ::android::hardware::sensors::V1_0::Event;
+
+   public:
+    static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
+    SharedMemInfo getSharedMemInfo() const;
+    char* getBuffer() const;
+    std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
+    virtual ~SensorsTestSharedMemory();
+
+   private:
+    SensorsTestSharedMemory(SharedMemType type, size_t size);
+
+    SharedMemType mType;
+    native_handle_t* mNativeHandle;
+    size_t mSize;
+    char* mBuffer;
+    std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
+
+    DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
+};
+
+#endif  // ANDROID_SENSORS_TEST_SHARED_MEMORY_H