C++程序  |  834行  |  24.69 KB

/*
 * 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_composer_hidl_hal_test"

#include <IComposerCommandBuffer.h>
#include <android-base/logging.h>
#include "VtsHalGraphicsComposerTestUtils.h"
#include "VtsHalGraphicsMapperTestUtils.h"

#include <VtsHalHidlTargetTestBase.h>
#include <unistd.h>

#include <algorithm>
#include <array>
#include <memory>
#include <mutex>
#include <unordered_set>
#include <vector>

namespace android {
namespace hardware {
namespace graphics {
namespace composer {
namespace V2_1 {
namespace tests {
namespace {

using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::ColorTransform;
using android::hardware::graphics::common::V1_0::Dataspace;
using android::hardware::graphics::common::V1_0::PixelFormat;
using android::hardware::graphics::common::V1_0::Transform;
using android::hardware::graphics::mapper::V2_0::IMapper;
using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
using GrallocError = android::hardware::graphics::mapper::V2_0::Error;

// IComposerCallback to be installed with IComposerClient::registerCallback.
class GraphicsComposerCallback : public IComposerCallback {
 public:
  void setVsyncAllowed(bool allowed) {
    std::lock_guard<std::mutex> lock(mMutex);
    mVsyncAllowed = allowed;
  }

  std::vector<Display> getDisplays() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return std::vector<Display>(mDisplays.begin(), mDisplays.end());
  }

  int getInvalidHotplugCount() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return mInvalidHotplugCount;
  }

  int getInvalidRefreshCount() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return mInvalidRefreshCount;
  }

  int getInvalidVsyncCount() const {
    std::lock_guard<std::mutex> lock(mMutex);
    return mInvalidVsyncCount;
  }

 private:
  Return<void> onHotplug(Display display, Connection connection) override {
    std::lock_guard<std::mutex> lock(mMutex);

    if (connection == Connection::CONNECTED) {
      if (!mDisplays.insert(display).second) {
        mInvalidHotplugCount++;
      }
    } else if (connection == Connection::DISCONNECTED) {
      if (!mDisplays.erase(display)) {
        mInvalidHotplugCount++;
      }
    }

    return Void();
  }

  Return<void> onRefresh(Display display) override {
    std::lock_guard<std::mutex> lock(mMutex);

    if (mDisplays.count(display) == 0) {
      mInvalidRefreshCount++;
    }

    return Void();
  }

  Return<void> onVsync(Display display, int64_t) override {
    std::lock_guard<std::mutex> lock(mMutex);

    if (!mVsyncAllowed || mDisplays.count(display) == 0) {
      mInvalidVsyncCount++;
    }

    return Void();
  }

  mutable std::mutex mMutex;
  // the set of all currently connected displays
  std::unordered_set<Display> mDisplays;
  // true only when vsync is enabled
  bool mVsyncAllowed = false;

  // track invalid callbacks
  int mInvalidHotplugCount = 0;
  int mInvalidRefreshCount = 0;
  int mInvalidVsyncCount = 0;
};

class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 protected:
  void SetUp() override {
    ASSERT_NO_FATAL_FAILURE(mComposer = std::make_unique<Composer>());
    ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());

    mComposerCallback = new GraphicsComposerCallback;
    mComposerClient->registerCallback(mComposerCallback);

    // assume the first display is primary and is never removed
    mPrimaryDisplay = waitForFirstDisplay();
  }

  void TearDown() override {
    if (mComposerCallback != nullptr) {
      EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
      EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
      EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
    }
  }

  // use the slot count usually set by SF
  static constexpr uint32_t kBufferSlotCount = 64;

  std::unique_ptr<Composer> mComposer;
  std::unique_ptr<ComposerClient> mComposerClient;
  sp<GraphicsComposerCallback> mComposerCallback;
  // the first display and is assumed never to be removed
  Display mPrimaryDisplay;

 private:
  Display waitForFirstDisplay() {
    while (true) {
      std::vector<Display> displays = mComposerCallback->getDisplays();
      if (displays.empty()) {
        usleep(5 * 1000);
        continue;
      }

      return displays[0];
    }
  }
};

/**
 * Test IComposer::getCapabilities.
 *
 * Test that IComposer::getCapabilities returns no invalid capabilities.
 */
TEST_F(GraphicsComposerHidlTest, GetCapabilities) {
  auto capabilities = mComposer->getCapabilities();
  ASSERT_EQ(capabilities.end(),
            std::find(capabilities.begin(), capabilities.end(),
                      IComposer::Capability::INVALID));
}

/**
 * Test IComposer::dumpDebugInfo.
 */
TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); }

/**
 * Test IComposer::createClient.
 *
 * Test that IComposerClient is a singleton.
 */
TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) {
  mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) {
    EXPECT_EQ(Error::NO_RESOURCES, tmpError);
  });
}

/**
 * Test IComposerClient::createVirtualDisplay and
 * IComposerClient::destroyVirtualDisplay.
 *
 * Test that virtual displays can be created and has the correct display type.
 */
TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) {
  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
    GTEST_SUCCEED() << "no virtual display support";
    return;
  }

  Display display;
  PixelFormat format;
  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
                              kBufferSlotCount, &format));

  // test display type
  IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
  EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);

  mComposerClient->destroyVirtualDisplay(display);
}

/**
 * Test IComposerClient::createLayer and IComposerClient::destroyLayer.
 *
 * Test that layers can be created and destroyed.
 */
TEST_F(GraphicsComposerHidlTest, CreateLayer) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mComposerClient->destroyLayer(mPrimaryDisplay, layer);
}

/**
 * Test IComposerClient::getDisplayName.
 */
TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
  mComposerClient->getDisplayName(mPrimaryDisplay);
}

/**
 * Test IComposerClient::getDisplayType.
 *
 * Test that IComposerClient::getDisplayType returns the correct display type
 * for the primary display.
 */
TEST_F(GraphicsComposerHidlTest, GetDisplayType) {
  ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
            mComposerClient->getDisplayType(mPrimaryDisplay));
}

/**
 * Test IComposerClient::getClientTargetSupport.
 *
 * Test that IComposerClient::getClientTargetSupport returns true for the
 * required client targets.
 */
TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) {
  std::vector<Config> configs =
      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
  for (auto config : configs) {
    int32_t width = mComposerClient->getDisplayAttribute(
        mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH);
    int32_t height = mComposerClient->getDisplayAttribute(
        mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT);
    ASSERT_LT(0, width);
    ASSERT_LT(0, height);

    mComposerClient->setActiveConfig(mPrimaryDisplay, config);

    ASSERT_TRUE(mComposerClient->getClientTargetSupport(
        mPrimaryDisplay, width, height, PixelFormat::RGBA_8888,
        Dataspace::UNKNOWN));
  }
}

/**
 * Test IComposerClient::getDisplayAttribute.
 *
 * Test that IComposerClient::getDisplayAttribute succeeds for the required
 * formats, and succeeds or fails correctly for optional attributes.
 */
TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) {
  std::vector<Config> configs =
      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
  for (auto config : configs) {
    const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
        IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
        IComposerClient::Attribute::VSYNC_PERIOD,
    }};
    for (auto attribute : requiredAttributes) {
      mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
    }

    const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
        IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
    }};
    for (auto attribute : optionalAttributes) {
      mComposerClient->getRaw()->getDisplayAttribute(
          mPrimaryDisplay, config, attribute,
          [&](const auto& tmpError, const auto&) {
            EXPECT_TRUE(tmpError == Error::NONE ||
                        tmpError == Error::UNSUPPORTED);
          });
    }
  }
}

/**
 * Test IComposerClient::getHdrCapabilities.
 */
TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) {
  float maxLuminance;
  float maxAverageLuminance;
  float minLuminance;
  mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance,
                                      &maxAverageLuminance, &minLuminance);
}

/**
 * Test IComposerClient::setClientTargetSlotCount.
 */
TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) {
  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
}

/**
 * Test IComposerClient::setActiveConfig.
 *
 * Test that IComposerClient::setActiveConfig succeeds for all display
 * configs.
 */
TEST_F(GraphicsComposerHidlTest, SetActiveConfig) {
  std::vector<Config> configs =
      mComposerClient->getDisplayConfigs(mPrimaryDisplay);
  for (auto config : configs) {
    mComposerClient->setActiveConfig(mPrimaryDisplay, config);
    ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
  }
}

/**
 * Test IComposerClient::setColorMode.
 *
 * Test that IComposerClient::setColorMode succeeds for all color modes.
 */
TEST_F(GraphicsComposerHidlTest, SetColorMode) {
  std::vector<ColorMode> modes =
      mComposerClient->getColorModes(mPrimaryDisplay);
  for (auto mode : modes) {
    mComposerClient->setColorMode(mPrimaryDisplay, mode);
  }
}

/**
 * Test IComposerClient::setPowerMode.
 *
 * Test that IComposerClient::setPowerMode succeeds for all power modes.
 */
TEST_F(GraphicsComposerHidlTest, SetPowerMode) {
  std::vector<IComposerClient::PowerMode> modes;
  modes.push_back(IComposerClient::PowerMode::OFF);

  if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
    modes.push_back(IComposerClient::PowerMode::DOZE);
    modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
  }

  // push ON last
  modes.push_back(IComposerClient::PowerMode::ON);

  for (auto mode : modes) {
    mComposerClient->setPowerMode(mPrimaryDisplay, mode);
  }
}

/**
 * Test IComposerClient::setVsyncEnabled.
 *
 * Test that IComposerClient::setVsyncEnabled succeeds and there is no
 * spurious vsync events.
 */
TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) {
  mComposerCallback->setVsyncAllowed(true);

  mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
  usleep(60 * 1000);
  mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);

  mComposerCallback->setVsyncAllowed(false);
}

// Tests for IComposerClient::Command.
class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
 protected:
  void SetUp() override {
    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());

    ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());

    mWriter = std::make_unique<CommandWriterBase>(1024);
    mReader = std::make_unique<CommandReader>();
  }

  void TearDown() override {
    ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
  }

  const native_handle_t* allocate() {
      IMapper::BufferDescriptorInfo info{};
      info.width = 64;
      info.height = 64;
      info.layerCount = 1;
      info.format = PixelFormat::RGBA_8888;
      info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
                                         BufferUsage::CPU_READ_OFTEN);

      return mGralloc->allocate(info);
  }

  void execute() {
    bool queueChanged = false;
    uint32_t commandLength = 0;
    hidl_vec<hidl_handle> commandHandles;
    ASSERT_TRUE(
        mWriter->writeQueue(&queueChanged, &commandLength, &commandHandles));

    if (queueChanged) {
      auto ret = mComposerClient->getRaw()->setInputCommandQueue(
          *mWriter->getMQDescriptor());
      ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
      return;
    }

    mComposerClient->getRaw()->executeCommands(
        commandLength, commandHandles,
        [&](const auto& tmpError, const auto& tmpOutQueueChanged,
            const auto& tmpOutLength, const auto& tmpOutHandles) {
          ASSERT_EQ(Error::NONE, tmpError);

          if (tmpOutQueueChanged) {
            mComposerClient->getRaw()->getOutputCommandQueue(
                [&](const auto& tmpError, const auto& tmpDescriptor) {
                  ASSERT_EQ(Error::NONE, tmpError);
                  mReader->setMQDescriptor(tmpDescriptor);
                });
          }

          ASSERT_TRUE(mReader->readQueue(tmpOutLength, tmpOutHandles));
          mReader->parse();
        });
  }

  // A command parser that checks that no error nor unexpected commands are
  // returned.
  class CommandReader : public CommandReaderBase {
   public:
    // Parse all commands in the return command queue.  Call GTEST_FAIL() for
    // unexpected errors or commands.
    void parse() {
      while (!isEmpty()) {
        IComposerClient::Command command;
        uint16_t length;
        ASSERT_TRUE(beginCommand(&command, &length));

        switch (command) {
          case IComposerClient::Command::SET_ERROR: {
            ASSERT_EQ(2, length);
            auto loc = read();
            auto err = readSigned();
            GTEST_FAIL() << "unexpected error " << err << " at location "
                         << loc;
          } break;
          case IComposerClient::Command::SELECT_DISPLAY:
          case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
          case IComposerClient::Command::SET_DISPLAY_REQUESTS:
          case IComposerClient::Command::SET_PRESENT_FENCE:
          case IComposerClient::Command::SET_RELEASE_FENCES:
            break;
          default:
            GTEST_FAIL() << "unexpected return command " << std::hex
                         << static_cast<int>(command);
            break;
        }

        endCommand();
      }
    }
  };

  std::unique_ptr<CommandWriterBase> mWriter;
  std::unique_ptr<CommandReader> mReader;

 private:
  std::unique_ptr<Gralloc> mGralloc;
};

/**
 * Test IComposerClient::Command::SET_COLOR_TRANSFORM.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) {
  const std::array<float, 16> identity = {{
      1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
      0.0f, 0.0f, 0.0f, 1.0f,
  }};

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);

  execute();
}

/**
 * Test IComposerClient::Command::SET_CLIENT_TARGET.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) {
  mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
                           std::vector<IComposerClient::Rect>());

  execute();
}

/**
 * Test IComposerClient::Command::SET_OUTPUT_BUFFER.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) {
  if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
    GTEST_SUCCEED() << "no virtual display support";
    return;
  }

  Display display;
  PixelFormat format;
  ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
                              64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
                              kBufferSlotCount, &format));

  const native_handle_t* handle;
  ASSERT_NO_FATAL_FAILURE(handle = allocate());

  mWriter->selectDisplay(display);
  mWriter->setOutputBuffer(0, handle, -1);
  execute();
}

/**
 * Test IComposerClient::Command::VALIDATE_DISPLAY.
 */
TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) {
  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->validateDisplay();
  execute();
}

/**
 * Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES.
 */
TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->validateDisplay();
  mWriter->acceptDisplayChanges();
  execute();
}

/**
 * Test IComposerClient::Command::PRESENT_DISPLAY.
 */
TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) {
  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->validateDisplay();
  mWriter->presentDisplay();
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerCursorPosition(1, 1);
  mWriter->setLayerCursorPosition(0, 0);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_BUFFER.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
  auto handle = allocate();
  ASSERT_NE(nullptr, handle);

  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerBuffer(0, handle, -1);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  IComposerClient::Rect empty{0, 0, 0, 0};
  IComposerClient::Rect unit{0, 0, 1, 1};

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
  mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_BLEND_MODE.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
  mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
  mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_COLOR.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
  mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
  mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
  mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
  mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_DATASPACE.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerDataspace(Dataspace::UNKNOWN);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerPlaneAlpha(0.0f);
  mWriter->setLayerPlaneAlpha(1.0f);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
  if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
    GTEST_SUCCEED() << "no sideband stream support";
    return;
  }

  auto handle = allocate();
  ASSERT_NE(nullptr, handle);

  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerSidebandStream(handle);
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_SOURCE_CROP.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_TRANSFORM.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerTransform(static_cast<Transform>(0));
  mWriter->setLayerTransform(Transform::FLIP_H);
  mWriter->setLayerTransform(Transform::FLIP_V);
  mWriter->setLayerTransform(Transform::ROT_90);
  mWriter->setLayerTransform(Transform::ROT_180);
  mWriter->setLayerTransform(Transform::ROT_270);
  mWriter->setLayerTransform(
      static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
  mWriter->setLayerTransform(
      static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  IComposerClient::Rect empty{0, 0, 0, 0};
  IComposerClient::Rect unit{0, 0, 1, 1};

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
  mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
  execute();
}

/**
 * Test IComposerClient::Command::SET_LAYER_Z_ORDER.
 */
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
  Layer layer;
  ASSERT_NO_FATAL_FAILURE(
      layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));

  mWriter->selectDisplay(mPrimaryDisplay);
  mWriter->selectLayer(layer);
  mWriter->setLayerZOrder(10);
  mWriter->setLayerZOrder(0);
  execute();
}

}  // namespace anonymous
}  // namespace tests
}  // namespace V2_1
}  // namespace composer
}  // namespace graphics
}  // namespace hardware
}  // namespace android

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

  int status = RUN_ALL_TESTS();
  LOG(INFO) << "Test result = " << status;

  return status;
}