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

Commit 2b31cdb2 authored by Chia-I Wu's avatar Chia-I Wu Committed by Android (Google) Code Review
Browse files

Merge "graphics: add target-side tests for IAllocator (again)"

parents 9b07173a bc46dacf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
subdirs = [
    "allocator/2.0",
    "allocator/2.0/default",
    "allocator/2.0/vts/functional",
    "common/1.0",
    "composer/2.1",
    "composer/2.1/default",
+15 −0
Original line number Diff line number Diff line
@@ -78,6 +78,9 @@ interface IAllocator {
     *
     * @return capabilities is a list of supported capabilities.
     */
    @entry
    @exit
    @callflow(next="*")
    getCapabilities() generates (vec<Capability> capabilities);

    /*
@@ -86,6 +89,9 @@ interface IAllocator {
     *
     * @return debugInfo is a string of debug information.
     */
    @entry
    @exit
    @callflow(next="*")
    dumpDebugInfo() generates (string debugInfo);

    /*
@@ -98,6 +104,8 @@ interface IAllocator {
     *         NO_RESOURCES when no more descriptors can currently be created.
     * @return descriptor is the newly created buffer descriptor.
     */
    @entry
    @callflow(next="*")
    createDescriptor(BufferDescriptorInfo descriptorInfo)
          generates (Error error,
                     BufferDescriptor descriptor);
@@ -108,6 +116,8 @@ interface IAllocator {
     * @param descriptor is the descriptor to destroy.
     * @return error is either NONE or BAD_DESCRIPTOR.
     */
    @exit
    @callflow(next="*")
    destroyDescriptor(BufferDescriptor descriptor) generates (Error error);

    /*
@@ -124,6 +134,7 @@ interface IAllocator {
     *         UNSUPPORTED when any of the descriptors can never be satisfied.
     *         UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
     */
    @callflow(next="allocate")
    testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);

    /*
@@ -147,6 +158,7 @@ interface IAllocator {
     *                      time.
     * @return buffers is the allocated buffers.
     */
    @callflow(next="exportHandle")
    allocate(vec<BufferDescriptor> descriptors)
        generates (Error error,
                   vec<Buffer> buffers);
@@ -158,6 +170,8 @@ interface IAllocator {
     * @return error is NONE upon success. Otherwise,
     *         BAD_BUFFER when the buffer is invalid.
     */
    @exit
    @callflow(next="*")
    free(Buffer buffer) generates (Error error);

    /*
@@ -182,6 +196,7 @@ interface IAllocator {
     *         NO_RESOURCES when the buffer cannot be exported at this time.
     * @return bufferHandle is the exported handle.
     */
    @callflow(next="free")
    exportHandle(BufferDescriptor descriptor,
                 Buffer buffer)
      generates (Error error,
+215 −0
Original line number Diff line number Diff line
component_class: HAL_HIDL
component_type_version: 2.0
component_name: "IAllocator"

package: "android.hardware.graphics.allocator"

import: "android.hardware.graphics.allocator@2.0::types"

interface: {
    attribute: {
        name: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability"
        type: TYPE_ENUM
        enum_value: {
            scalar_type: "int32_t"

            enumerator: "INVALID"
            scalar_value: {
                int32_t: 0
            }
            enumerator: "TEST_ALLOCATE"
            scalar_value: {
                int32_t: 1
            }
        }
    }

    attribute: {
        name: "::android::hardware::graphics::allocator::V2_0::IAllocator::BufferDescriptorInfo"
        type: TYPE_STRUCT
        struct_value: {
            name: "width"
            type: TYPE_SCALAR
            scalar_type: "uint32_t"
        }
        struct_value: {
            name: "height"
            type: TYPE_SCALAR
            scalar_type: "uint32_t"
        }
        struct_value: {
            name: "format"
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::PixelFormat"
        }
        struct_value: {
            name: "producerUsageMask"
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        struct_value: {
            name: "consumerUsageMask"
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
    }

    api: {
        name: "getCapabilities"
        return_type_hidl: {
            type: TYPE_VECTOR
            vector_value: {
                type: TYPE_ENUM
                predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability"
            }
        }
        callflow: {
            entry: true
        }
        callflow: {
            exit: true
        }
        callflow: {
            next: "*"
        }
    }

    api: {
        name: "dumpDebugInfo"
        return_type_hidl: {
            type: TYPE_STRING
        }
        callflow: {
            entry: true
        }
        callflow: {
            exit: true
        }
        callflow: {
            next: "*"
        }
    }

    api: {
        name: "createDescriptor"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        return_type_hidl: {
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        arg: {
            type: TYPE_STRUCT
            predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocator::BufferDescriptorInfo"
        }
        callflow: {
            entry: true
        }
        callflow: {
            next: "*"
        }
    }

    api: {
        name: "destroyDescriptor"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        arg: {
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        callflow: {
            exit: true
        }
        callflow: {
            next: "*"
        }
    }

    api: {
        name: "testAllocate"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        arg: {
            type: TYPE_VECTOR
            vector_value: {
                type: TYPE_SCALAR
                scalar_type: "uint64_t"
            }
        }
        callflow: {
            next: "allocate"
        }
    }

    api: {
        name: "allocate"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        return_type_hidl: {
            type: TYPE_VECTOR
            vector_value: {
                type: TYPE_SCALAR
                scalar_type: "uint64_t"
            }
        }
        arg: {
            type: TYPE_VECTOR
            vector_value: {
                type: TYPE_SCALAR
                scalar_type: "uint64_t"
            }
        }
        callflow: {
            next: "exportHandle"
        }
    }

    api: {
        name: "free"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        arg: {
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        callflow: {
            exit: true
        }
        callflow: {
            next: "*"
        }
    }

    api: {
        name: "exportHandle"
        return_type_hidl: {
            type: TYPE_ENUM
            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
        }
        return_type_hidl: {
        }
        arg: {
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        arg: {
            type: TYPE_SCALAR
            scalar_type: "uint64_t"
        }
        callflow: {
            next: "free"
        }
    }

}
+37 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2016 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_test {
    name: "graphics_allocator_hidl_hal_test",
    gtest: true,
    srcs: ["graphics_allocator_hidl_hal_test.cpp"],
    shared_libs: [
        "libbase",
        "liblog",
        "libcutils",
        "libhidlbase",
        "libhidltransport",
        "libhwbinder",
        "libnativehelper",
        "libutils",
        "android.hardware.graphics.allocator@2.0",
    ],
    static_libs: ["libgtest"],
    cflags: [
        "-O0",
        "-g",
    ],
}
+304 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 "graphics_allocator_hidl_hal_test"

#include <unordered_set>

#include <android-base/logging.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <gtest/gtest.h>

namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace tests {
namespace {

using android::hardware::graphics::common::V1_0::PixelFormat;

#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME)                 \
  do {                                                      \
    if (!hasCapability(FEATURE_NAME)) {                     \
      std::cout << "[  SKIPPED ] Feature " << #FEATURE_NAME \
                << " not supported" << std::endl;           \
      return;                                               \
    }                                                       \
  } while (0)

class TempDescriptor {
 public:
  TempDescriptor(const sp<IAllocator>& allocator,
                 const IAllocator::BufferDescriptorInfo& info)
      : mAllocator(allocator), mError(Error::NO_RESOURCES) {
    mAllocator->createDescriptor(
        info, [&](const auto& tmpError, const auto& tmpDescriptor) {
          mError = tmpError;
          mDescriptor = tmpDescriptor;
        });
  }

  ~TempDescriptor() {
    if (mError == Error::NONE) {
      mAllocator->destroyDescriptor(mDescriptor);
    }
  }

  bool isValid() const { return (mError == Error::NONE); }

  operator BufferDescriptor() const { return mDescriptor; }

 private:
  sp<IAllocator> mAllocator;
  Error mError;
  BufferDescriptor mDescriptor;
};

class GraphicsAllocatorHidlTest : public ::testing::Test {
 protected:
  void SetUp() override {
    mAllocator = IAllocator::getService("gralloc");
    ASSERT_NE(mAllocator, nullptr);

    initCapabilities();

    mDummyDescriptorInfo.width = 64;
    mDummyDescriptorInfo.height = 64;
    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
    mDummyDescriptorInfo.producerUsageMask =
        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
    mDummyDescriptorInfo.consumerUsageMask =
        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
  }

  void TearDown() override {}

  /**
   * Initialize the set of supported capabilities.
   */
  void initCapabilities() {
    mAllocator->getCapabilities([this](const auto& capabilities) {
      std::vector<IAllocator::Capability> caps = capabilities;
      mCapabilities.insert(caps.cbegin(), caps.cend());
    });
  }

  /**
   * Test whether a capability is supported.
   */
  bool hasCapability(IAllocator::Capability capability) const {
    return (mCapabilities.count(capability) > 0);
  }

  sp<IAllocator> mAllocator;
  IAllocator::BufferDescriptorInfo mDummyDescriptorInfo{};

 private:
  std::unordered_set<IAllocator::Capability> mCapabilities;
};

TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) {
  auto ret = mAllocator->getCapabilities([](const auto& capabilities) {
    std::vector<IAllocator::Capability> caps = capabilities;
    for (auto cap : caps) {
      EXPECT_NE(IAllocator::Capability::INVALID, cap);
    }
  });

  ASSERT_TRUE(ret.getStatus().isOk());
}

TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) {
  auto ret = mAllocator->dumpDebugInfo([](const auto&) {
    // nothing to do
  });

  ASSERT_TRUE(ret.getStatus().isOk());
}

TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) {
  Error error;
  BufferDescriptor descriptor;
  auto ret = mAllocator->createDescriptor(
      mDummyDescriptorInfo,
      [&](const auto& tmpError, const auto& tmpDescriptor) {
        error = tmpError;
        descriptor = tmpDescriptor;
      });

  ASSERT_TRUE(ret.getStatus().isOk());
  ASSERT_EQ(Error::NONE, error);

  auto err_ret = mAllocator->destroyDescriptor(descriptor);
  ASSERT_TRUE(err_ret.getStatus().isOk());
  ASSERT_EQ(Error::NONE, static_cast<Error>(err_ret));
}

/**
 * Test testAllocate with a single buffer descriptor.
 */
TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) {
  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);

  TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor.isValid());

  hidl_vec<BufferDescriptor> descriptors;
  descriptors.resize(1);
  descriptors[0] = descriptor;

  auto ret = mAllocator->testAllocate(descriptors);
  ASSERT_TRUE(ret.getStatus().isOk());

  auto error = static_cast<Error>(ret);
  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
}

/**
 * Test testAllocate with two buffer descriptors.
 */
TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) {
  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);

  TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor.isValid());

  hidl_vec<BufferDescriptor> descriptors;
  descriptors.resize(2);
  descriptors[0] = descriptor;
  descriptors[1] = descriptor;

  auto ret = mAllocator->testAllocate(descriptors);
  ASSERT_TRUE(ret.getStatus().isOk());

  auto error = static_cast<Error>(ret);
  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
}

/**
 * Test allocate/free with a single buffer descriptor.
 */
TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) {
  TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor.isValid());

  hidl_vec<BufferDescriptor> descriptors;
  descriptors.resize(1);
  descriptors[0] = descriptor;

  Error error;
  std::vector<Buffer> buffers;
  auto ret = mAllocator->allocate(
      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
        error = tmpError;
        buffers = tmpBuffers;
      });

  ASSERT_TRUE(ret.getStatus().isOk());
  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
  EXPECT_EQ(1u, buffers.size());

  if (!buffers.empty()) {
    auto err_ret = mAllocator->free(buffers[0]);
    EXPECT_TRUE(err_ret.getStatus().isOk());
    EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
  }
}

/**
 * Test allocate/free with an array of buffer descriptors.
 */
TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) {
  TempDescriptor descriptor1(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor1.isValid());

  TempDescriptor descriptor2(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor2.isValid());

  hidl_vec<BufferDescriptor> descriptors;
  descriptors.resize(3);
  descriptors[0] = descriptor1;
  descriptors[1] = descriptor1;
  descriptors[2] = descriptor2;

  Error error;
  std::vector<Buffer> buffers;
  auto ret = mAllocator->allocate(
      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
        error = tmpError;
        buffers = tmpBuffers;
      });

  ASSERT_TRUE(ret.getStatus().isOk());
  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
  EXPECT_EQ(descriptors.size(), buffers.size());

  for (auto buf : buffers) {
    auto err_ret = mAllocator->free(buf);
    EXPECT_TRUE(err_ret.getStatus().isOk());
    EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
  }
}

TEST_F(GraphicsAllocatorHidlTest, ExportHandle) {
  TempDescriptor descriptor(mAllocator, mDummyDescriptorInfo);
  ASSERT_TRUE(descriptor.isValid());

  hidl_vec<BufferDescriptor> descriptors;
  descriptors.resize(1);
  descriptors[0] = descriptor;

  Error error;
  std::vector<Buffer> buffers;
  auto ret = mAllocator->allocate(
      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
        error = tmpError;
        buffers = tmpBuffers;
      });

  ASSERT_TRUE(ret.getStatus().isOk());
  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
  ASSERT_EQ(1u, buffers.size());

  ret = mAllocator->exportHandle(
      descriptors[0], buffers[0],
      [&](const auto& tmpError, const auto&) { error = tmpError; });
  EXPECT_TRUE(ret.getStatus().isOk());
  EXPECT_EQ(Error::NONE, error);

  auto err_ret = mAllocator->free(buffers[0]);
  EXPECT_TRUE(err_ret.getStatus().isOk());
  EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
}

}  // namespace anonymous
}  // namespace tests
}  // namespace V2_0
}  // namespace allocator
}  // namespace graphics
}  // namespace hardware
}  // namespace android

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

  int status = RUN_ALL_TESTS();
  ALOGI("Test result = %d", status);

  return status;
}
Loading