Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c102a99 authored by Brian Stack's avatar Brian Stack
Browse files

Refactor SensorsTestSharedMemory

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

Bug: 111070257
Test: Build
Change-Id: I03df7462302d4ab0ea647e0d7688a46bf0e06dc1
parent 18f37015
Loading
Loading
Loading
Loading
+1 −213
Original line number Diff line number Diff line
@@ -19,237 +19,25 @@
#include "SensorsHidlEnvironmentV1_0.h"
#include "sensors-vts-utils/GrallocWrapper.h"
#include "sensors-vts-utils/SensorEventsChecker.h"
#include "sensors-vts-utils/SensorsTestSharedMemory.h"

#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
#include <cutils/ashmem.h>
#include <hardware/sensors.h>  // for sensor type strings
#include <log/log.h>
#include <utils/SystemClock.h>

#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <memory>
#include <mutex>
#include <thread>
#include <unordered_set>
#include <vector>

#include <sys/mman.h>
#include <unistd.h>

using ::android::GrallocWrapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_string;
using ::android::sp;
using namespace ::android::hardware::sensors::V1_0;

class SensorsTestSharedMemory {
 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<GrallocWrapper> mGrallocWrapper;

  DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
};

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<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;
}

// The main test class for SENSORS HIDL HAL.
class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
+1 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ cc_library_static {
    srcs: [
        "GrallocWrapper.cpp",
        "SensorsHidlEnvironmentBase.cpp",
        "SensorsTestSharedMemory.cpp",
    ],
    export_include_dirs: [
        "include",
@@ -33,4 +34,3 @@ cc_library_static {
        "VtsHalHidlTargetTestBase",
    ],
}
+7 −0
Original line number Diff line number Diff line
# Sensors team
bduddie@google.com
bstack@google.com

# VTS team
trong@google.com
yim@google.com
+206 −0
Original line number Diff line number Diff line
/*
 * 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;
}
+51 −0
Original line number Diff line number Diff line
/*
 * 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