graphics: move libVtsHalGraphicsComposerTestUtils

Move libVtsHalGraphicsComposerTestUtils from vts/functional to
utils/vts.

Test: make VtsHalGraphicsComposerV2_1TargetTest
Change-Id: Ic3042aa7f2578d099fbe79039b60892bd0e87f25
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..7f4a7c3
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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_library_static {
+    name: "libVtsHalGraphicsComposerTestUtils",
+    defaults: ["hidl_defaults"],
+    srcs: [
+        "GraphicsComposerCallback.cpp",
+        "TestCommandReader.cpp",
+        "VtsHalGraphicsComposerTestUtils.cpp",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "libfmq",
+        "libsync",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-O0",
+        "-g",
+        "-DLOG_TAG=\"GraphicsComposerTestUtils\"",
+    ],
+    export_include_dirs: ["include/composer-vts/2.1"],
+}
diff --git a/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
new file mode 100644
index 0000000..0ad440c
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include "GraphicsComposerCallback.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
+  std::lock_guard<std::mutex> lock(mMutex);
+  mVsyncAllowed = allowed;
+}
+
+std::vector<Display> GraphicsComposerCallback::getDisplays() const {
+  std::lock_guard<std::mutex> lock(mMutex);
+  return std::vector<Display>(mDisplays.begin(), mDisplays.end());
+}
+
+int GraphicsComposerCallback::getInvalidHotplugCount() const {
+  std::lock_guard<std::mutex> lock(mMutex);
+  return mInvalidHotplugCount;
+}
+
+int GraphicsComposerCallback::getInvalidRefreshCount() const {
+  std::lock_guard<std::mutex> lock(mMutex);
+  return mInvalidRefreshCount;
+}
+
+int GraphicsComposerCallback::getInvalidVsyncCount() const {
+  std::lock_guard<std::mutex> lock(mMutex);
+  return mInvalidVsyncCount;
+}
+
+Return<void> GraphicsComposerCallback::onHotplug(Display display,
+                                                 Connection connection) {
+  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> GraphicsComposerCallback::onRefresh(Display display) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  if (mDisplays.count(display) == 0) {
+    mInvalidRefreshCount++;
+  }
+
+  return Void();
+}
+
+Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  if (!mVsyncAllowed || mDisplays.count(display) == 0) {
+    mInvalidVsyncCount++;
+  }
+
+  return Void();
+}
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
new file mode 100644
index 0000000..b1f9aca
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#include "TestCommandReader.h"
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+void TestCommandReader::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();
+  }
+}
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.1/utils/vts/VtsHalGraphicsComposerTestUtils.cpp
new file mode 100644
index 0000000..c66cdd0
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/VtsHalGraphicsComposerTestUtils.cpp
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include "VtsHalGraphicsComposerTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+Composer::Composer() {
+  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
+  init();
+}
+
+Composer::Composer(const std::string& name) {
+  mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
+  init();
+}
+
+void Composer::init() {
+  ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+
+  std::vector<IComposer::Capability> capabilities = getCapabilities();
+  mCapabilities.insert(capabilities.begin(), capabilities.end());
+}
+
+sp<IComposer> Composer::getRaw() const { return mComposer; }
+
+bool Composer::hasCapability(IComposer::Capability capability) const {
+  return mCapabilities.count(capability) > 0;
+}
+
+std::vector<IComposer::Capability> Composer::getCapabilities() {
+  std::vector<IComposer::Capability> capabilities;
+  mComposer->getCapabilities(
+      [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
+
+  return capabilities;
+}
+
+std::string Composer::dumpDebugInfo() {
+  std::string debugInfo;
+  mComposer->dumpDebugInfo(
+      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+  return debugInfo;
+}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+  std::unique_ptr<ComposerClient> client;
+  mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+    ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+    client = std::make_unique<ComposerClient>(tmpClient);
+  });
+
+  return client;
+}
+
+ComposerClient::ComposerClient(const sp<IComposerClient>& client)
+    : mClient(client) {}
+
+ComposerClient::~ComposerClient() {
+  for (auto it : mDisplayResources) {
+    Display display = it.first;
+    DisplayResource& resource = it.second;
+
+    for (auto layer : resource.layers) {
+      EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
+          << "failed to destroy layer " << layer;
+    }
+
+    if (resource.isVirtual) {
+      EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
+          << "failed to destroy virtual display " << display;
+    }
+  }
+  mDisplayResources.clear();
+}
+
+sp<IComposerClient> ComposerClient::getRaw() const { return mClient; }
+
+void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
+  mClient->registerCallback(callback);
+}
+
+uint32_t ComposerClient::getMaxVirtualDisplayCount() {
+  return mClient->getMaxVirtualDisplayCount();
+}
+
+Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
+                                             PixelFormat formatHint,
+                                             uint32_t outputBufferSlotCount,
+                                             PixelFormat* outFormat) {
+  Display display = 0;
+  mClient->createVirtualDisplay(
+      width, height, formatHint, outputBufferSlotCount,
+      [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
+        display = tmpDisplay;
+        *outFormat = tmpFormat;
+
+        ASSERT_TRUE(
+            mDisplayResources.insert({display, DisplayResource(true)}).second)
+            << "duplicated virtual display id " << display;
+      });
+
+  return display;
+}
+
+void ComposerClient::destroyVirtualDisplay(Display display) {
+  Error error = mClient->destroyVirtualDisplay(display);
+  ASSERT_EQ(Error::NONE, error)
+      << "failed to destroy virtual display " << display;
+
+  mDisplayResources.erase(display);
+}
+
+Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
+  Layer layer = 0;
+  mClient->createLayer(
+      display, bufferSlotCount,
+      [&](const auto& tmpError, const auto& tmpLayer) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
+        layer = tmpLayer;
+
+        auto resourceIt = mDisplayResources.find(display);
+        if (resourceIt == mDisplayResources.end()) {
+          resourceIt =
+              mDisplayResources.insert({display, DisplayResource(false)}).first;
+        }
+
+        ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
+            << "duplicated layer id " << layer;
+      });
+
+  return layer;
+}
+
+void ComposerClient::destroyLayer(Display display, Layer layer) {
+  Error error = mClient->destroyLayer(display, layer);
+  ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
+
+  auto resourceIt = mDisplayResources.find(display);
+  ASSERT_NE(mDisplayResources.end(), resourceIt);
+  resourceIt->second.layers.erase(layer);
+}
+
+Config ComposerClient::getActiveConfig(Display display) {
+  Config config = 0;
+  mClient->getActiveConfig(
+      display, [&](const auto& tmpError, const auto& tmpConfig) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
+        config = tmpConfig;
+      });
+
+  return config;
+}
+
+bool ComposerClient::getClientTargetSupport(Display display, uint32_t width,
+                                            uint32_t height, PixelFormat format,
+                                            Dataspace dataspace) {
+  Error error = mClient->getClientTargetSupport(display, width, height, format,
+                                                dataspace);
+  return error == Error::NONE;
+}
+
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
+  std::vector<ColorMode> modes;
+  mClient->getColorModes(
+      display, [&](const auto& tmpError, const auto& tmpMode) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
+        modes = tmpMode;
+      });
+
+  return modes;
+}
+
+int32_t ComposerClient::getDisplayAttribute(
+    Display display, Config config, IComposerClient::Attribute attribute) {
+  int32_t value = 0;
+  mClient->getDisplayAttribute(display, config, attribute,
+                               [&](const auto& tmpError, const auto& tmpValue) {
+                                 ASSERT_EQ(Error::NONE, tmpError)
+                                     << "failed to get display attribute";
+                                 value = tmpValue;
+                               });
+
+  return value;
+}
+
+std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
+  std::vector<Config> configs;
+  mClient->getDisplayConfigs(
+      display, [&](const auto& tmpError, const auto& tmpConfigs) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
+        configs = tmpConfigs;
+      });
+
+  return configs;
+}
+
+std::string ComposerClient::getDisplayName(Display display) {
+  std::string name;
+  mClient->getDisplayName(
+      display, [&](const auto& tmpError, const auto& tmpName) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
+        name = tmpName.c_str();
+      });
+
+  return name;
+}
+
+IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
+  IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+  mClient->getDisplayType(
+      display, [&](const auto& tmpError, const auto& tmpType) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
+        type = tmpType;
+      });
+
+  return type;
+}
+
+bool ComposerClient::getDozeSupport(Display display) {
+  bool support = false;
+  mClient->getDozeSupport(
+      display, [&](const auto& tmpError, const auto& tmpSupport) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
+        support = tmpSupport;
+      });
+
+  return support;
+}
+
+std::vector<Hdr> ComposerClient::getHdrCapabilities(
+    Display display, float* outMaxLuminance, float* outMaxAverageLuminance,
+    float* outMinLuminance) {
+  std::vector<Hdr> types;
+  mClient->getHdrCapabilities(
+      display,
+      [&](const auto& tmpError, const auto& tmpTypes,
+          const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance,
+          const auto& tmpMinLuminance) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
+        types = tmpTypes;
+        *outMaxLuminance = tmpMaxLuminance;
+        *outMaxAverageLuminance = tmpMaxAverageLuminance;
+        *outMinLuminance = tmpMinLuminance;
+      });
+
+  return types;
+}
+
+void ComposerClient::setClientTargetSlotCount(Display display,
+                                              uint32_t clientTargetSlotCount) {
+  Error error =
+      mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
+  ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
+}
+
+void ComposerClient::setActiveConfig(Display display, Config config) {
+  Error error = mClient->setActiveConfig(display, config);
+  ASSERT_EQ(Error::NONE, error) << "failed to set active config";
+}
+
+void ComposerClient::setColorMode(Display display, ColorMode mode) {
+  Error error = mClient->setColorMode(display, mode);
+  ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
+}
+
+void ComposerClient::setPowerMode(Display display,
+                                  IComposerClient::PowerMode mode) {
+  Error error = mClient->setPowerMode(display, mode);
+  ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
+}
+
+void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
+  IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE
+                                           : IComposerClient::Vsync::DISABLE;
+  Error error = mClient->setVsyncEnabled(display, vsync);
+  ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
+
+  // give the hwbinder thread some time to handle any pending vsync callback
+  if (!enabled) {
+      usleep(5 * 1000);
+  }
+}
+
+void ComposerClient::execute(TestCommandReader* reader,
+                             CommandWriterBase* writer) {
+  bool queueChanged = false;
+  uint32_t commandLength = 0;
+  hidl_vec<hidl_handle> commandHandles;
+  ASSERT_TRUE(
+      writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+  if (queueChanged) {
+    auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
+    ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
+    return;
+  }
+
+  mClient->executeCommands(
+      commandLength, commandHandles,
+      [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+          const auto& tmpOutLength, const auto& tmpOutHandles) {
+        ASSERT_EQ(Error::NONE, tmpError);
+
+        if (tmpOutQueueChanged) {
+          mClient->getOutputCommandQueue(
+              [&](const auto& tmpError, const auto& tmpDescriptor) {
+                ASSERT_EQ(Error::NONE, tmpError);
+                reader->setMQDescriptor(tmpDescriptor);
+              });
+        }
+
+        ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+        reader->parse();
+      });
+}
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
new file mode 100644
index 0000000..e332086
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h
@@ -0,0 +1,69 @@
+/*
+ * 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 GRAPHICS_COMPOSER_CALLBACK_H
+#define GRAPHICS_COMPOSER_CALLBACK_H
+
+#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
+
+#include <mutex>
+#include <unordered_set>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+// IComposerCallback to be installed with IComposerClient::registerCallback.
+class GraphicsComposerCallback : public IComposerCallback {
+ public:
+  void setVsyncAllowed(bool allowed);
+
+  std::vector<Display> getDisplays() const;
+
+  int getInvalidHotplugCount() const;
+
+  int getInvalidRefreshCount() const;
+
+  int getInvalidVsyncCount() const;
+
+ private:
+  Return<void> onHotplug(Display display, Connection connection) override;
+  Return<void> onRefresh(Display display) override;
+  Return<void> onVsync(Display display, int64_t) override;
+
+  mutable std::mutex mMutex;
+  // the set of all currently connected displays
+  std::unordered_set<Display> mDisplays;
+  // true only when vsync is enabled
+  bool mVsyncAllowed = true;
+
+  // track invalid callbacks
+  int mInvalidHotplugCount = 0;
+  int mInvalidRefreshCount = 0;
+  int mInvalidVsyncCount = 0;
+};
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // GRAPHICS_COMPOSER_CALLBACK_H
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
new file mode 100644
index 0000000..ae25d2d
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -0,0 +1,45 @@
+/*
+ * 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 TEST_COMMAND_READER_H
+#define TEST_COMMAND_READER_H
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+// A command parser that checks that no error nor unexpected commands are
+// returned.
+class TestCommandReader : public CommandReaderBase {
+ public:
+  // Parse all commands in the return command queue.  Call GTEST_FAIL() for
+  // unexpected errors or commands.
+  void parse();
+};
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // TEST_COMMAND_READER_H
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/VtsHalGraphicsComposerTestUtils.h
new file mode 100644
index 0000000..00d9d8c
--- /dev/null
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/VtsHalGraphicsComposerTestUtils.h
@@ -0,0 +1,134 @@
+/*
+ * 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 VTS_HAL_GRAPHICS_COMPOSER_UTILS
+#define VTS_HAL_GRAPHICS_COMPOSER_UTILS
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <utils/StrongPointer.h>
+
+#include "TestCommandReader.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace tests {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer {
+ public:
+  Composer();
+  explicit Composer(const std::string& name);
+
+  sp<IComposer> getRaw() const;
+
+  // Returns true when the composer supports the specified capability.
+  bool hasCapability(IComposer::Capability capability) const;
+
+  std::vector<IComposer::Capability> getCapabilities();
+  std::string dumpDebugInfo();
+  std::unique_ptr<ComposerClient> createClient();
+
+ protected:
+  sp<IComposer> mComposer;
+
+ private:
+  void init();
+
+  std::unordered_set<IComposer::Capability> mCapabilities;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient {
+ public:
+  ComposerClient(const sp<IComposerClient>& client);
+  ~ComposerClient();
+
+  sp<IComposerClient> getRaw() const;
+
+  void registerCallback(const sp<IComposerCallback>& callback);
+  uint32_t getMaxVirtualDisplayCount();
+
+  Display createVirtualDisplay(uint32_t width, uint32_t height,
+                               PixelFormat formatHint,
+                               uint32_t outputBufferSlotCount,
+                               PixelFormat* outFormat);
+  void destroyVirtualDisplay(Display display);
+
+  Layer createLayer(Display display, uint32_t bufferSlotCount);
+  void destroyLayer(Display display, Layer layer);
+
+  Config getActiveConfig(Display display);
+  bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                              PixelFormat format, Dataspace dataspace);
+  std::vector<ColorMode> getColorModes(Display display);
+  int32_t getDisplayAttribute(Display display, Config config,
+                              IComposerClient::Attribute attribute);
+  std::vector<Config> getDisplayConfigs(Display display);
+  std::string getDisplayName(Display display);
+  IComposerClient::DisplayType getDisplayType(Display display);
+  bool getDozeSupport(Display display);
+  std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
+                                      float* outMaxAverageLuminance,
+                                      float* outMinLuminance);
+
+  void setClientTargetSlotCount(Display display,
+                                uint32_t clientTargetSlotCount);
+  void setActiveConfig(Display display, Config config);
+  void setColorMode(Display display, ColorMode mode);
+  void setPowerMode(Display display, IComposerClient::PowerMode mode);
+  void setVsyncEnabled(Display display, bool enabled);
+
+  void execute(TestCommandReader* reader, CommandWriterBase* writer);
+
+ private:
+  sp<IComposerClient> mClient;
+
+  // Keep track of all virtual displays and layers.  When a test fails with
+  // ASSERT_*, the destructor will clean up the resources for the test.
+  struct DisplayResource {
+    DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
+
+    bool isVirtual;
+    std::unordered_set<Layer> layers;
+  };
+  std::unordered_map<Display, DisplayResource> mDisplayResources;
+};
+
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_GRAPHICS_COMPOSER_UTILS