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

Commit b7841f02 authored by Peng Xu's avatar Peng Xu Committed by Gerrit Code Review
Browse files

Merge "Sensor direct report test - gralloc support"

parents d429b1f9 c1fcb010
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -17,7 +17,14 @@
cc_test {
    name: "VtsHalSensorsV1_0TargetTest",
    defaults: ["VtsHalTargetTestDefaults"],
    srcs: ["VtsHalSensorsV1_0TargetTest.cpp"],
    static_libs: ["android.hardware.sensors@1.0"],
    srcs: [
        "GrallocWrapper.cpp",
        "VtsHalSensorsV1_0TargetTest.cpp"
    ],
    static_libs: [
        "android.hardware.graphics.allocator@2.0",
        "android.hardware.graphics.mapper@2.0",
        "android.hardware.sensors@1.0"
    ]
}
+232 −0
Original line number Diff line number Diff line
/*
 * 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 "GrallocWrapper"

#include "GrallocWrapper.h"

#include <utils/Log.h>

namespace android {

GrallocWrapper::GrallocWrapper() { init(); }

void GrallocWrapper::init() {
  mAllocator = allocator2::IAllocator::getService();
  if (mAllocator == nullptr) {
    ALOGE("Failed to get allocator service");
  }

  mMapper = mapper2::IMapper::getService();
  if (mMapper == nullptr) {
    ALOGE("Failed to get mapper service");
  }
  if (mMapper->isRemote()) {
    ALOGE("Mapper is not in passthrough mode");
  }
}

GrallocWrapper::~GrallocWrapper() {
  for (auto bufferHandle : mClonedBuffers) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);
    native_handle_close(buffer);
    native_handle_delete(buffer);
  }
  mClonedBuffers.clear();

  for (auto bufferHandle : mImportedBuffers) {
    auto buffer = const_cast<native_handle_t*>(bufferHandle);
    if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
      ALOGE("Failed to free buffer %p", buffer);
    }
  }
  mImportedBuffers.clear();
}

sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
  return mAllocator;
}

std::string GrallocWrapper::dumpDebugInfo() {
  std::string debugInfo;
  mAllocator->dumpDebugInfo(
      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });

  return debugInfo;
}

const native_handle_t* GrallocWrapper::cloneBuffer(
    const hardware::hidl_handle& rawHandle) {
  const native_handle_t* bufferHandle =
      native_handle_clone(rawHandle.getNativeHandle());

  if (bufferHandle) {
    mClonedBuffers.insert(bufferHandle);
  }
  return bufferHandle;
}

std::vector<const native_handle_t*> GrallocWrapper::allocate(
    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import,
    uint32_t* outStride) {
  std::vector<const native_handle_t*> bufferHandles;
  bufferHandles.reserve(count);
  mAllocator->allocate(
      descriptor, count,
      [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
        if (mapper2::Error::NONE != tmpError) {
          ALOGE("Failed to allocate buffers");
        }
        if (count != tmpBuffers.size()) {
          ALOGE("Invalid buffer array");
        }

        for (uint32_t i = 0; i < count; i++) {
          if (import) {
            bufferHandles.push_back(importBuffer(tmpBuffers[i]));
          } else {
            bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
          }
        }

        if (outStride) {
          *outStride = tmpStride;
        }
      });

  return bufferHandles;
}

const native_handle_t* GrallocWrapper::allocate(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
    uint32_t* outStride) {
  mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
  ALOGE("QQ");
  auto buffers = allocate(descriptor, 1, import, outStride);
  return buffers[0];
}

sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; }

mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
  mapper2::BufferDescriptor descriptor;
  mMapper->createDescriptor(
      descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
        if (tmpError != mapper2::Error::NONE) {
          ALOGE("Failed to create descriptor");
        }
        descriptor = tmpDescriptor;
      });

  return descriptor;
}

const native_handle_t* GrallocWrapper::importBuffer(
    const hardware::hidl_handle& rawHandle) {
  const native_handle_t* bufferHandle = nullptr;
  mMapper->importBuffer(
      rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
        if (tmpError != mapper2::Error::NONE) {
          ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
        }
        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
      });

  if (bufferHandle) {
    mImportedBuffers.insert(bufferHandle);
  }

  return bufferHandle;
}

void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
  auto buffer = const_cast<native_handle_t*>(bufferHandle);

  if (mImportedBuffers.erase(bufferHandle)) {
    mapper2::Error error = mMapper->freeBuffer(buffer);
    if (error != mapper2::Error::NONE) {
      ALOGE("Failed to free %p", buffer);
    }
  } else {
    mClonedBuffers.erase(bufferHandle);
    native_handle_close(buffer);
    native_handle_delete(buffer);
  }
}

void* GrallocWrapper::lock(const native_handle_t* bufferHandle,
                           uint64_t cpuUsage,
                           const mapper2::IMapper::Rect& accessRegion,
                           int acquireFence) {
  auto buffer = const_cast<native_handle_t*>(bufferHandle);

  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
  hardware::hidl_handle acquireFenceHandle;
  if (acquireFence >= 0) {
    auto h = native_handle_init(acquireFenceStorage, 1, 0);
    h->data[0] = acquireFence;
    acquireFenceHandle = h;
  }

  void* data = nullptr;
  mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
                [&](const auto& tmpError, const auto& tmpData) {
                  if (tmpError != mapper2::Error::NONE) {
                    ALOGE("Failed to lock buffer %p", buffer);
                  }
                  data = tmpData;
                });

  if (acquireFence >= 0) {
    close(acquireFence);
  }

  return data;
}

int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
  auto buffer = const_cast<native_handle_t*>(bufferHandle);

  int releaseFence = -1;
  mMapper->unlock(buffer, [&](const auto& tmpError,
                              const auto& tmpReleaseFence) {
    if (tmpError != mapper2::Error::NONE) {
      ALOGE("Failed to unlock buffer %p", buffer);
    }

    auto fenceHandle = tmpReleaseFence.getNativeHandle();
    if (fenceHandle) {
      if (fenceHandle->numInts != 0) {
        ALOGE("Invalid fence handle %p", fenceHandle);
      }
      if (fenceHandle->numFds == 1) {
        releaseFence = dup(fenceHandle->data[0]);
        if (releaseFence < 0){
          ALOGE("Failed to dup fence fd");
        }
      } else {
        if (fenceHandle->numFds != 0) {
          ALOGE("Invalid fence handle %p", fenceHandle);
        }
      }
    }
  });

  return releaseFence;
}

}  // namespace android
+80 −0
Original line number Diff line number Diff line
/*
 * 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 GRALLO_WRAPPER_H_
#define GRALLO_WRAPPER_H_

#include <unordered_set>

#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>

namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;

namespace android {

// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
class GrallocWrapper {
 public:
  GrallocWrapper();
  ~GrallocWrapper();

  sp<allocator2::IAllocator> getAllocator() const;
  sp<mapper2::IMapper> getMapper() const;

  std::string dumpDebugInfo();

  // When import is false, this simply calls IAllocator::allocate. When import
  // is true, the returned buffers are also imported into the mapper.
  //
  // Either case, the returned buffers must be freed with freeBuffer.
  std::vector<const native_handle_t*> allocate(
      const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true,
      uint32_t* outStride = nullptr);
  const native_handle_t* allocate(
      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
      uint32_t* outStride = nullptr);

  mapper2::BufferDescriptor createDescriptor(
      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);

  const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
  void freeBuffer(const native_handle_t* bufferHandle);

  // We use fd instead of hardware::hidl_handle in these functions to pass fences
  // in and out of the mapper.  The ownership of the fd is always transferred
  // with each of these functions.
  void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
             const mapper2::IMapper::Rect& accessRegion, int acquireFence);

  int unlock(const native_handle_t* bufferHandle);

 private:
  void init();
  const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);

  sp<allocator2::IAllocator> mAllocator;
  sp<mapper2::IMapper> mMapper;

  // Keep track of all cloned and imported handles.  When a test fails with
  // ASSERT_*, the destructor will free the handles for the test.
  std::unordered_set<const native_handle_t*> mClonedBuffers;
  std::unordered_set<const native_handle_t*> mImportedBuffers;
};

}  // namespace android
#endif  // GRALLO_WRAPPER_H_
+97 −2
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */

#define LOG_TAG "sensors_hidl_hal_test"
#include "GrallocWrapper.h"
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/sensors/1.0/ISensors.h>
@@ -36,6 +37,7 @@
#include <sys/mman.h>
#include <unistd.h>

using ::android::GrallocWrapper;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_string;
@@ -230,6 +232,7 @@ class SensorsTestSharedMemory {
  native_handle_t* mNativeHandle;
  size_t mSize;
  char* mBuffer;
  std::unique_ptr<GrallocWrapper> mGrallocWrapper;

  DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
};
@@ -265,6 +268,7 @@ std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, siz
  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;
    }

@@ -324,7 +328,34 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size
      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:
@@ -353,6 +384,16 @@ SensorsTestSharedMemory::~SensorsTestSharedMemory() {
      }
      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: "
@@ -1223,7 +1264,7 @@ TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
void SensorsHidlTest::testDirectReportOperation(
    SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
  constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
  constexpr size_t kNEvent = 500;
  constexpr size_t kNEvent = 4096;
  constexpr size_t kMemSize = kEventSize * kNEvent;

  constexpr float kNormalNominal = 50;
@@ -1379,6 +1420,60 @@ TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
      SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::VERY_FAST, NullChecker());
}

// Test sensor event direct report with gralloc for accel sensor at normal rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
                            sAccelNormChecker);
}

// Test sensor event direct report with gralloc for accel sensor at fast rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
                            sAccelNormChecker);
}

// Test sensor event direct report with gralloc for accel sensor at very fast rate
TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
  testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
                            sAccelNormChecker);
}

// Test sensor event direct report with gralloc for gyro sensor at normal rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
                            sGyroNormChecker);
}

// Test sensor event direct report with gralloc for gyro sensor at fast rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
                            sGyroNormChecker);
}

// Test sensor event direct report with gralloc for gyro sensor at very fast rate
TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
  testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
                            sGyroNormChecker);
}

// Test sensor event direct report with gralloc for mag sensor at normal rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
                            NullChecker());
}

// Test sensor event direct report with gralloc for mag sensor at fast rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
  testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
                            NullChecker());
}

// Test sensor event direct report with gralloc for mag sensor at very fast rate
TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
  testDirectReportOperation(
      SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::VERY_FAST, NullChecker());
}

int main(int argc, char **argv) {
  ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
  ::testing::InitGoogleTest(&argc, argv);