vendor-freeze: Move few commonsys-intf/display libs to commonsys/display

Moved libdisplayconfig.qti, libqdMetadata, and libgralloc.qti from
vendor/qcom/opensource/commonsys-intf/display to
vendor/qcom/opensource/commonsys/display to install in system_ext

Change-Id: Iff8e2364ded221858eb1ea211b6212c38df36eb3
LNXDISPLAY-1552: REQ002
CRs-Fixed: 2972776
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..26ce4fe
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,14 @@
+---
+Language:        Cpp
+BasedOnStyle:  Google
+Standard : C++11
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortBlocksOnASingleLine: false
+ColumnLimit:     100
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+DerivePointerAlignment: false
+PointerAlignment: Right
+#ReflowComments: false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ad71dd6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+CMakeLists.txt
+.idea/
+.editorconfig
+.clang-complete
diff --git a/config/display-product-commonsys.mk b/config/display-product-commonsys.mk
new file mode 100644
index 0000000..98b22c3
--- /dev/null
+++ b/config/display-product-commonsys.mk
@@ -0,0 +1,22 @@
+PRODUCT_PACKAGES += libdisplayconfig.system \
+                    libqdMetaData.system \
+                    libgralloc.system.qti \
+                    libdrm \
+                    libsmomo.qti \
+                    liblayerext.qti \
+                    libsmomoconfig.qti \
+                    libcomposerextn.qti \
+                    libdisplayconfig.system.qti
+
+SOONG_CONFIG_NAMESPACES += qtidisplaycommonsys
+SOONG_CONFIG_NAMESPACES += qtiunifeddraw
+# Soong Keys
+SOONG_CONFIG_qtidisplaycommonsys := displayconfig_enabled
+SOONG_CONFIG_qtiunifeddraw := qtiunifeddraw_enabled
+# Soong Values
+SOONG_CONFIG_qtidisplaycommonsys_displayconfig_enabled := false
+SOONG_CONFIG_qtiunifeddraw_qtiunifeddraw_enabled := true
+
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+    SOONG_CONFIG_qtidisplaycommonsys_displayconfig_enabled := true
+endif
diff --git a/gralloc/Android.bp b/gralloc/Android.bp
new file mode 100644
index 0000000..2c28cf6
--- /dev/null
+++ b/gralloc/Android.bp
@@ -0,0 +1,22 @@
+cc_library_shared {
+    name: "libgralloc.system.qti",
+    system_ext_specific: true,
+    cflags: [
+        "-Wno-sign-conversion",
+        "-DLOG_TAG=\"qtigralloc\"",
+    ],
+    shared_libs: [
+         "liblog",
+         "libcutils",
+         "libutils",
+         "libgralloctypes",
+         "libhidlbase",
+         "libhardware",
+         "android.hardware.graphics.mapper@4.0",
+    ],
+
+    srcs: ["QtiGralloc.cpp"],
+
+    header_libs: ["display_intf_headers"],
+}
+
diff --git a/gralloc/QtiGralloc.cpp b/gralloc/QtiGralloc.cpp
new file mode 100644
index 0000000..831163a
--- /dev/null
+++ b/gralloc/QtiGralloc.cpp
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "QtiGralloc.h"
+
+#include <log/log.h>
+namespace qtigralloc {
+
+using android::hardware::graphics::mapper::V4_0::IMapper;
+
+static sp<IMapper> getInstance() {
+  static sp<IMapper> mapper = IMapper::getService();
+  return mapper;
+}
+
+Error decodeMetadataState(hidl_vec<uint8_t> &in, bool *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), METADATA_SET_SIZE);
+  return Error::NONE;
+}
+
+Error encodeMetadataState(bool *in, hidl_vec<uint8_t> *out) {
+  if (!in || !out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(sizeof(bool) * METADATA_SET_SIZE);
+  memcpy(out->data(), in, sizeof(bool) * METADATA_SET_SIZE);
+  return Error::NONE;
+}
+
+Error decodeColorMetadata(hidl_vec<uint8_t> &in, ColorMetaData *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), sizeof(ColorMetaData));
+  return Error::NONE;
+}
+
+Error encodeColorMetadata(ColorMetaData &in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(sizeof(ColorMetaData));
+  memcpy(out->data(), &in, sizeof(ColorMetaData));
+  return Error::NONE;
+}
+
+// decode the raw graphics metadata from bytestream and store it in 'data' member of
+// GraphicsMetadata struct during mapper->set call, 'size' member is unused.
+Error decodeGraphicsMetadata(hidl_vec<uint8_t> &in, GraphicsMetadata *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(&(out->data), in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES);
+  return Error::NONE;
+}
+
+// encode only 'data' member of GraphicsMetadata struct for retrieval of
+// graphics metadata during mapper->get call
+Error encodeGraphicsMetadata(GraphicsMetadata &in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES);
+  memcpy(out->data(), &(in.data), GRAPHICS_METADATA_SIZE_IN_BYTES);
+  return Error::NONE;
+}
+
+// decode the raw graphics metadata from bytestream before presenting it to caller
+Error decodeGraphicsMetadataRaw(hidl_vec<uint8_t> &in, void *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES);
+  return Error::NONE;
+}
+
+// encode the raw graphics metadata in bytestream before calling mapper->set
+Error encodeGraphicsMetadataRaw(void *in, hidl_vec<uint8_t> *out) {
+  if (!in || !out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES);
+  memcpy(out->data(), in, GRAPHICS_METADATA_SIZE_IN_BYTES);
+  return Error::NONE;
+}
+
+Error decodeUBWCStats(hidl_vec<uint8_t> &in, UBWCStats *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
+  return Error::NONE;
+}
+
+Error encodeUBWCStats(UBWCStats *in, hidl_vec<uint8_t> *out) {
+  if (!in || !out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
+  memcpy(out->data(), in, UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
+  return Error::NONE;
+}
+
+Error decodeCVPMetadata(hidl_vec<uint8_t> &in, CVPMetadata *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), sizeof(CVPMetadata));
+  return Error::NONE;
+}
+
+Error encodeCVPMetadata(CVPMetadata &in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(sizeof(CVPMetadata));
+  memcpy(out->data(), &in, sizeof(CVPMetadata));
+  return Error::NONE;
+}
+
+Error decodeVideoHistogramMetadata(hidl_vec<uint8_t> &in, VideoHistogramMetadata *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), sizeof(VideoHistogramMetadata));
+  return Error::NONE;
+}
+
+Error encodeVideoHistogramMetadata(VideoHistogramMetadata &in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(sizeof(VideoHistogramMetadata));
+  memcpy(out->data(), &in, sizeof(VideoHistogramMetadata));
+  return Error::NONE;
+}
+
+Error decodeVideoTimestampInfo(hidl_vec<uint8_t> &in, VideoTimestampInfo *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  memcpy(out, in.data(), sizeof(VideoTimestampInfo));
+  return Error::NONE;
+}
+
+Error encodeVideoTimestampInfo(VideoTimestampInfo &in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(sizeof(VideoTimestampInfo));
+  memcpy(out->data(), &in, sizeof(VideoTimestampInfo));
+  return Error::NONE;
+}
+
+Error decodeYUVPlaneInfoMetadata(hidl_vec<uint8_t> &in, qti_ycbcr *out) {
+  if (!in.size() || !out) {
+    return Error::BAD_VALUE;
+  }
+  qti_ycbcr *p = reinterpret_cast<qti_ycbcr *>(in.data());
+  memcpy(out, in.data(), (YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)));
+  return Error::NONE;
+}
+
+Error encodeYUVPlaneInfoMetadata(qti_ycbcr *in, hidl_vec<uint8_t> *out) {
+  if (!out) {
+    return Error::BAD_VALUE;
+  }
+  out->resize(YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr));
+  memcpy(out->data(), in, YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr));
+  return Error::NONE;
+}
+
+MetadataType getMetadataType(uint32_t in) {
+  switch (in) {
+    case QTI_VT_TIMESTAMP:
+      return MetadataType_VTTimestamp;
+    case QTI_VIDEO_PERF_MODE:
+      return MetadataType_VideoPerfMode;
+    case QTI_LINEAR_FORMAT:
+      return MetadataType_LinearFormat;
+    case QTI_SINGLE_BUFFER_MODE:
+      return MetadataType_SingleBufferMode;
+    case QTI_PP_PARAM_INTERLACED:
+      return MetadataType_PPParamInterlaced;
+    case QTI_MAP_SECURE_BUFFER:
+      return MetadataType_MapSecureBuffer;
+    case QTI_COLOR_METADATA:
+      return MetadataType_ColorMetadata;
+    case QTI_GRAPHICS_METADATA:
+      return MetadataType_GraphicsMetadata;
+    case QTI_UBWC_CR_STATS_INFO:
+      return MetadataType_UBWCCRStatsInfo;
+    case QTI_REFRESH_RATE:
+      return MetadataType_RefreshRate;
+    case QTI_CVP_METADATA:
+      return MetadataType_CVPMetadata;
+    case QTI_VIDEO_HISTOGRAM_STATS:
+      return MetadataType_VideoHistogramStats;
+    case QTI_VIDEO_TS_INFO:
+      return MetadataType_VideoTimestampInfo;
+    case QTI_FD:
+      return MetadataType_FD;
+    case QTI_PRIVATE_FLAGS:
+      return MetadataType_PrivateFlags;
+    case QTI_ALIGNED_WIDTH_IN_PIXELS:
+      return MetadataType_AlignedWidthInPixels;
+    case QTI_ALIGNED_HEIGHT_IN_PIXELS:
+      return MetadataType_AlignedHeightInPixels;
+    case QTI_STANDARD_METADATA_STATUS:
+      return MetadataType_StandardMetadataStatus;
+    case QTI_VENDOR_METADATA_STATUS:
+      return MetadataType_VendorMetadataStatus;
+    case QTI_BUFFER_TYPE:
+      return MetadataType_BufferType;
+    case QTI_CUSTOM_DIMENSIONS_STRIDE:
+      return MetadataType_CustomDimensionsStride;
+    case QTI_CUSTOM_DIMENSIONS_HEIGHT:
+      return MetadataType_CustomDimensionsHeight;
+    case QTI_RGB_DATA_ADDRESS:
+      return MetadataType_RgbDataAddress;
+    case QTI_COLORSPACE:
+      return MetadataType_ColorSpace;
+    case QTI_YUV_PLANE_INFO:
+      return MetadataType_YuvPlaneInfo;
+    default:
+      return MetadataType_Invalid;
+  }
+}
+
+Error get(void *buffer, uint32_t type, void *param) {
+  hidl_vec<uint8_t> bytestream;
+  sp<IMapper> mapper = getInstance();
+
+  MetadataType metadata_type = getMetadataType(type);
+  if (metadata_type == MetadataType_Invalid) {
+    param = nullptr;
+    return Error::UNSUPPORTED;
+  }
+
+  auto err = Error::UNSUPPORTED;
+  mapper->get(buffer, metadata_type, [&](const auto &tmpError, const auto &tmpByteStream) {
+    err = tmpError;
+    bytestream = tmpByteStream;
+  });
+
+  if (err != Error::NONE) {
+    return err;
+  }
+
+  switch (type) {
+    case QTI_VT_TIMESTAMP:
+      err = static_cast<Error>(android::gralloc4::decodeUint64(
+          qtigralloc::MetadataType_VTTimestamp, bytestream, reinterpret_cast<uint64_t *>(param)));
+      break;
+    case QTI_VIDEO_PERF_MODE:
+      err = static_cast<Error>(android::gralloc4::decodeUint32(
+          qtigralloc::MetadataType_VideoPerfMode, bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_LINEAR_FORMAT:
+      err = static_cast<Error>(android::gralloc4::decodeUint32(
+          qtigralloc::MetadataType_LinearFormat, bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_SINGLE_BUFFER_MODE:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint32(qtigralloc::MetadataType_SingleBufferMode, bytestream,
+                                          reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_PP_PARAM_INTERLACED:
+      err = static_cast<Error>(
+          android::gralloc4::decodeInt32(qtigralloc::MetadataType_PPParamInterlaced, bytestream,
+                                         reinterpret_cast<int32_t *>(param)));
+      break;
+    case QTI_MAP_SECURE_BUFFER:
+      err = static_cast<Error>(
+          android::gralloc4::decodeInt32(qtigralloc::MetadataType_MapSecureBuffer, bytestream,
+                                         reinterpret_cast<int32_t *>(param)));
+      break;
+    case QTI_COLOR_METADATA:
+      err = decodeColorMetadata(bytestream, reinterpret_cast<ColorMetaData *>(param));
+      break;
+    case QTI_GRAPHICS_METADATA:
+      err = decodeGraphicsMetadataRaw(bytestream, param);
+      break;
+    case QTI_UBWC_CR_STATS_INFO:
+      err = decodeUBWCStats(bytestream, reinterpret_cast<UBWCStats *>(param));
+      break;
+    case QTI_REFRESH_RATE:
+      err = static_cast<Error>(android::gralloc4::decodeFloat(
+          qtigralloc::MetadataType_RefreshRate, bytestream, reinterpret_cast<float *>(param)));
+      break;
+    case QTI_CVP_METADATA:
+      err = decodeCVPMetadata(bytestream, reinterpret_cast<CVPMetadata *>(param));
+      break;
+    case QTI_VIDEO_HISTOGRAM_STATS:
+      err = decodeVideoHistogramMetadata(bytestream,
+                                         reinterpret_cast<VideoHistogramMetadata *>(param));
+      break;
+    case QTI_VIDEO_TS_INFO:
+      err = decodeVideoTimestampInfo(bytestream, reinterpret_cast<VideoTimestampInfo *>(param));
+      break;
+    case QTI_FD:
+      err = static_cast<Error>(android::gralloc4::decodeInt32(
+          qtigralloc::MetadataType_FD, bytestream, reinterpret_cast<int32_t *>(param)));
+      break;
+    case QTI_PRIVATE_FLAGS:
+      err = static_cast<Error>(android::gralloc4::decodeInt32(
+          qtigralloc::MetadataType_PrivateFlags, bytestream, reinterpret_cast<int32_t *>(param)));
+      break;
+    case QTI_ALIGNED_WIDTH_IN_PIXELS:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedWidthInPixels, bytestream,
+                                          reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_ALIGNED_HEIGHT_IN_PIXELS:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedHeightInPixels,
+                                          bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_STANDARD_METADATA_STATUS:
+    case QTI_VENDOR_METADATA_STATUS:
+      err = decodeMetadataState(bytestream, reinterpret_cast<bool *>(param));
+      break;
+    case QTI_BUFFER_TYPE:
+      err = static_cast<Error>(android::gralloc4::decodeUint32(
+          qtigralloc::MetadataType_BufferType, bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_CUSTOM_DIMENSIONS_STRIDE:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsStride,
+                                          bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_CUSTOM_DIMENSIONS_HEIGHT:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsHeight,
+                                          bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_RGB_DATA_ADDRESS:
+      err = static_cast<Error>(
+          android::gralloc4::decodeUint64(qtigralloc::MetadataType_RgbDataAddress, bytestream,
+                                          reinterpret_cast<uint64_t *>(param)));
+      break;
+    case QTI_COLORSPACE:
+      err = static_cast<Error>(android::gralloc4::decodeUint32(
+          qtigralloc::MetadataType_ColorSpace, bytestream, reinterpret_cast<uint32_t *>(param)));
+      break;
+    case QTI_YUV_PLANE_INFO:
+      err = decodeYUVPlaneInfoMetadata(bytestream, reinterpret_cast<qti_ycbcr *>(param));
+      break;
+    default:
+      param = nullptr;
+      return Error::UNSUPPORTED;
+  }
+
+  return err;
+}
+
+Error set(void *buffer, uint32_t type, void *param) {
+  hidl_vec<uint8_t> bytestream;
+  sp<IMapper> mapper = getInstance();
+
+  Error err = Error::UNSUPPORTED;
+  MetadataType metadata_type = getMetadataType(type);
+  if (metadata_type == MetadataType_Invalid) {
+    return err;
+  }
+
+  switch (type) {
+    case QTI_VT_TIMESTAMP:
+      err = static_cast<Error>(android::gralloc4::encodeUint64(
+          qtigralloc::MetadataType_VTTimestamp, *reinterpret_cast<uint64_t *>(param), &bytestream));
+      break;
+    case QTI_VIDEO_PERF_MODE:
+      err = static_cast<Error>(
+          android::gralloc4::encodeUint32(qtigralloc::MetadataType_VideoPerfMode,
+                                          *reinterpret_cast<uint32_t *>(param), &bytestream));
+      break;
+    case QTI_LINEAR_FORMAT:
+      err = static_cast<Error>(
+          android::gralloc4::encodeUint32(qtigralloc::MetadataType_LinearFormat,
+                                          *reinterpret_cast<uint32_t *>(param), &bytestream));
+      break;
+    case QTI_SINGLE_BUFFER_MODE:
+      err = static_cast<Error>(
+          android::gralloc4::encodeUint32(qtigralloc::MetadataType_SingleBufferMode,
+                                          *reinterpret_cast<uint32_t *>(param), &bytestream));
+      break;
+    case QTI_PP_PARAM_INTERLACED:
+      err = static_cast<Error>(
+          android::gralloc4::encodeInt32(qtigralloc::MetadataType_PPParamInterlaced,
+                                         *reinterpret_cast<int32_t *>(param), &bytestream));
+      break;
+    case QTI_MAP_SECURE_BUFFER:
+      err = static_cast<Error>(
+          android::gralloc4::encodeInt32(qtigralloc::MetadataType_MapSecureBuffer,
+                                         *reinterpret_cast<int32_t *>(param), &bytestream));
+      break;
+    case QTI_COLOR_METADATA:
+      err = encodeColorMetadata(*reinterpret_cast<ColorMetaData *>(param), &bytestream);
+      break;
+    case QTI_GRAPHICS_METADATA:
+      err = encodeGraphicsMetadataRaw(param, &bytestream);
+      break;
+    case QTI_UBWC_CR_STATS_INFO:
+      err = encodeUBWCStats(reinterpret_cast<UBWCStats *>(param), &bytestream);
+      break;
+    case QTI_REFRESH_RATE:
+      err = static_cast<Error>(android::gralloc4::encodeFloat(
+          qtigralloc::MetadataType_RefreshRate, *reinterpret_cast<float *>(param), &bytestream));
+      break;
+    case QTI_CVP_METADATA:
+      err = encodeCVPMetadata(*reinterpret_cast<CVPMetadata *>(param), &bytestream);
+      break;
+    case QTI_VIDEO_HISTOGRAM_STATS:
+      err = encodeVideoHistogramMetadata(*reinterpret_cast<VideoHistogramMetadata *>(param),
+                                         &bytestream);
+      break;
+    case QTI_VIDEO_TS_INFO:
+      err = encodeVideoTimestampInfo(*reinterpret_cast<VideoTimestampInfo *>(param), &bytestream);
+      break;
+    default:
+      param = nullptr;
+      return Error::UNSUPPORTED;
+  }
+
+  if (err != Error::NONE) {
+    return err;
+  }
+
+  return mapper->set(reinterpret_cast<void *>(buffer), metadata_type, bytestream);
+}
+
+int getMetadataState(void *buffer, uint32_t type) {
+  bool metadata_set[METADATA_SET_SIZE];
+  Error err;
+  if (IS_VENDOR_METADATA_TYPE(type)) {
+    err = get(buffer, QTI_VENDOR_METADATA_STATUS, &metadata_set);
+  } else {
+    err = get(buffer, QTI_STANDARD_METADATA_STATUS, &metadata_set);
+  }
+
+  if (err != Error::NONE) {
+    ALOGE("Unable to get metadata state");
+    return -1;
+  }
+
+  if (IS_VENDOR_METADATA_TYPE(type)) {
+    return metadata_set[GET_VENDOR_METADATA_STATUS_INDEX(type)];
+  } else if (GET_STANDARD_METADATA_STATUS_INDEX(type) < METADATA_SET_SIZE) {
+    return metadata_set[GET_STANDARD_METADATA_STATUS_INDEX(type)];
+  } else {
+    return -1;
+  }
+}
+
+}  // namespace qtigralloc
diff --git a/libqdmetadata/Android.bp b/libqdmetadata/Android.bp
new file mode 100644
index 0000000..181eb16
--- /dev/null
+++ b/libqdmetadata/Android.bp
@@ -0,0 +1,21 @@
+cc_library_shared {
+    name: "libqdMetaData.system",
+    system_ext_specific: true,
+    cflags: [
+        "-Wno-sign-conversion",
+        "-DLOG_TAG=\"qdmetadata\"",
+        "-D__QTI_DISPLAY_GRALLOC__",
+    ],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libutils",
+        "libhidlbase",
+        "libgralloc.system.qti",
+        "libgralloctypes",
+    ],
+    header_libs: ["libhardware_headers", "display_intf_headers"],
+    srcs: ["qdMetaData.cpp", "qd_utils.cpp"],
+    export_header_lib_headers: ["display_intf_headers"],
+}
+
diff --git a/libqdmetadata/Makefile.am b/libqdmetadata/Makefile.am
new file mode 100644
index 0000000..1fa7e64
--- /dev/null
+++ b/libqdmetadata/Makefile.am
@@ -0,0 +1,16 @@
+h_sources = qdMetaData.h
+
+cpp_sources = qdMetaData.cpp
+
+AM_CPPFLAGS += -D__QTI_NO_GRALLOC4__
+
+qdMetaData_includedir = $(pkgincludedir)/display
+qdMetaData_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqdMetaData.la
+libqdMetaData_la_CC = @CC@
+libqdMetaData_la_SOURCES = $(cpp_sources)
+libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
+libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdMetaData_LDADD = -lcutils -llog
+libqdMetaData_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
diff --git a/libqdmetadata/qdMetaData.cpp b/libqdmetadata/qdMetaData.cpp
new file mode 100644
index 0000000..228a634
--- /dev/null
+++ b/libqdmetadata/qdMetaData.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qdMetaData.h"
+
+#include <QtiGrallocPriv.h>
+#include <errno.h>
+#include <gralloc_priv.h>
+#ifndef __QTI_NO_GRALLOC4__
+#include <gralloctypes/Gralloc4.h>
+#endif
+#include <log/log.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <cinttypes>
+
+static int colorMetaDataToColorSpace(ColorMetaData in, ColorSpace_t *out) {
+  if (in.colorPrimaries == ColorPrimaries_BT601_6_525 ||
+      in.colorPrimaries == ColorPrimaries_BT601_6_625) {
+    if (in.range == Range_Full) {
+      *out = ITU_R_601_FR;
+    } else {
+      *out = ITU_R_601;
+    }
+  } else if (in.colorPrimaries == ColorPrimaries_BT2020) {
+    if (in.range == Range_Full) {
+      *out = ITU_R_2020_FR;
+    } else {
+      *out = ITU_R_2020;
+    }
+  } else if (in.colorPrimaries == ColorPrimaries_BT709_5) {
+    if (in.range == Range_Full) {
+      *out = ITU_R_709_FR;
+    } else {
+      *out = ITU_R_709;
+    }
+  } else {
+    ALOGE(
+        "Cannot convert ColorMetaData to ColorSpace_t. "
+        "Primaries = %d, Range = %d",
+        in.colorPrimaries, in.range);
+    return -1;
+  }
+
+  return 0;
+}
+
+static int colorSpaceToColorMetadata(ColorSpace_t in, ColorMetaData *out) {
+  out->transfer = Transfer_sRGB;
+  switch (in) {
+    case ITU_R_601:
+      out->colorPrimaries = ColorPrimaries_BT601_6_525;
+      out->range = Range_Limited;
+      break;
+    case ITU_R_601_FR:
+      out->colorPrimaries = ColorPrimaries_BT601_6_525;
+      out->range = Range_Full;
+      break;
+    case ITU_R_709:
+      out->colorPrimaries = ColorPrimaries_BT709_5;
+      out->range = Range_Limited;
+      break;
+    case ITU_R_709_FR:
+      out->colorPrimaries = ColorPrimaries_BT709_5;
+      out->range = Range_Full;
+      break;
+    case ITU_R_2020:
+      out->colorPrimaries = ColorPrimaries_BT2020;
+      out->range = Range_Limited;
+      break;
+    case ITU_R_2020_FR:
+      out->colorPrimaries = ColorPrimaries_BT2020;
+      out->range = Range_Full;
+      break;
+    default:
+      ALOGE("Cannot convert ColorSpace_t %d to ColorMetaData", in);
+      return -1;
+      break;
+  }
+
+  return 0;
+}
+
+#ifndef __QTI_NO_GRALLOC4__
+static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
+  switch (paramType) {
+    case SET_VT_TIMESTAMP:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)];
+    case COLOR_METADATA:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
+    case PP_PARAM_INTERLACED:
+      return metadata
+          ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)];
+    case SET_VIDEO_PERF_MODE:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)];
+    case SET_GRAPHICS_METADATA:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)];
+    case SET_UBWC_CR_STATS_INFO:
+      return metadata
+          ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)];
+    case UPDATE_BUFFER_GEOMETRY:
+      return metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
+          ::android::gralloc4::MetadataType_Crop.value)];
+    case UPDATE_REFRESH_RATE:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)];
+    case UPDATE_COLOR_SPACE:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
+    case MAP_SECURE_BUFFER:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)];
+    case LINEAR_FORMAT:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)];
+    case SET_SINGLE_BUFFER_MODE:
+      return metadata
+          ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)];
+    case SET_CVP_METADATA:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)];
+    case SET_VIDEO_HISTOGRAM_STATS:
+      return metadata
+          ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)];
+    case SET_VIDEO_TS_INFO:
+      return metadata
+          ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)];
+    case GET_S3D_FORMAT:
+      return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)];
+    default:
+      ALOGE("paramType %d not supported", paramType);
+      return false;
+  }
+}
+
+static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
+  switch (paramType) {
+    case SET_VT_TIMESTAMP:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)] = isSet;
+      break;
+    case COLOR_METADATA:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
+      break;
+    case PP_PARAM_INTERLACED:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)] =
+          isSet;
+      break;
+    case SET_VIDEO_PERF_MODE:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)] = isSet;
+      break;
+    case SET_GRAPHICS_METADATA:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)] =
+          isSet;
+      break;
+    case SET_UBWC_CR_STATS_INFO:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)] =
+          isSet;
+      break;
+    case UPDATE_BUFFER_GEOMETRY:
+      metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
+          ::android::gralloc4::MetadataType_Crop.value)] = isSet;
+      break;
+    case UPDATE_REFRESH_RATE:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)] = isSet;
+      break;
+    case UPDATE_COLOR_SPACE:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
+      break;
+    case MAP_SECURE_BUFFER:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)] =
+          isSet;
+      break;
+    case LINEAR_FORMAT:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)] = isSet;
+      break;
+    case SET_SINGLE_BUFFER_MODE:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)] =
+          isSet;
+      break;
+    case SET_CVP_METADATA:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)] = isSet;
+      break;
+    case SET_VIDEO_HISTOGRAM_STATS:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)] =
+          isSet;
+      break;
+    case SET_VIDEO_TS_INFO:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)] =
+          isSet;
+      break;
+    case S3D_FORMAT:
+      metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)] = isSet;
+      break;
+    default:
+      ALOGE("paramType %d not supported in Gralloc4", paramType);
+  }
+}
+#else
+static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
+  return true;
+}
+
+static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
+}
+#endif
+
+
+unsigned long getMetaDataSize() {
+    return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
+}
+
+// Cannot add default argument to existing function
+unsigned long getMetaDataSizeWithReservedRegion(uint64_t reserved_size) {
+  return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t) + reserved_size));
+}
+
+static int validateAndMap(private_handle_t* handle) {
+    if (private_handle_t::validate(handle)) {
+        ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
+        return -1;
+    }
+    if (handle->fd_metadata < 0) {
+      // Metadata cannot be used
+      return -1;
+    }
+
+    if (!handle->base_metadata) {
+        auto size = getMetaDataSize();
+        void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+                handle->fd_metadata, 0);
+        if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+            ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s",
+                __func__, handle, handle->fd_metadata, strerror(errno));
+            return -1;
+        }
+        handle->base_metadata = (uintptr_t) base;
+        auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+        if (metadata->reservedSize) {
+          auto reserved_size = metadata->reservedSize;
+          munmap(reinterpret_cast<void *>(handle->base_metadata), getMetaDataSize());
+          handle->base_metadata = 0;
+          size = getMetaDataSizeWithReservedRegion(reserved_size);
+          void *new_base =
+              mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0);
+          if (new_base == reinterpret_cast<void *>(MAP_FAILED)) {
+            ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle,
+                  handle->fd_metadata, strerror(errno));
+            return -1;
+          }
+          handle->base_metadata = (uintptr_t)new_base;
+        }
+    }
+    return 0;
+}
+
+static void unmapAndReset(private_handle_t *handle) {
+    if (private_handle_t::validate(handle) == 0 && handle->base_metadata) {
+      // If reservedSize is 0, the return value will be the same as getMetaDataSize
+      auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+      auto size = getMetaDataSizeWithReservedRegion(metadata->reservedSize);
+      munmap(reinterpret_cast<void *>(handle->base_metadata), size);
+      handle->base_metadata = 0;
+    }
+}
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+                void *param) {
+    auto err = validateAndMap(handle);
+    if (err != 0)
+        return err;
+    return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata),
+                         paramType, param);
+}
+
+int setMetaDataVa(MetaData_t *data, DispParamType paramType,
+                  void *param) {
+    if (data == nullptr)
+        return -EINVAL;
+    // If parameter is NULL reset the specific MetaData Key
+    if (!param) {
+      setGralloc4Array(data, paramType, false);
+      switch (paramType) {
+        case SET_VIDEO_PERF_MODE:
+          data->isVideoPerfMode = 0;
+          break;
+        case SET_CVP_METADATA:
+          data->cvpMetadata.size = 0;
+          break;
+        case SET_VIDEO_HISTOGRAM_STATS:
+          data->video_histogram_stats.stat_len = 0;
+          break;
+        default:
+          ALOGE("Unknown paramType %d", paramType);
+          break;
+      }
+       // param unset
+       return 0;
+    }
+
+    setGralloc4Array(data, paramType, true);
+    switch (paramType) {
+        case PP_PARAM_INTERLACED:
+            data->interlaced = *((int32_t *)param);
+            break;
+        case UPDATE_BUFFER_GEOMETRY: {
+          BufferDim_t in = *((BufferDim_t *)param);
+          data->crop = {0, 0, in.sliceWidth, in.sliceHeight};
+          break;
+        }
+        case UPDATE_REFRESH_RATE:
+            data->refreshrate = *((float *)param);
+            break;
+        case UPDATE_COLOR_SPACE: {
+          ColorMetaData color = {};
+          if (!colorSpaceToColorMetadata(*((ColorSpace_t *)param), &color)) {
+            data->color = color;
+            break;
+          }
+          return -EINVAL;
+        }
+        case MAP_SECURE_BUFFER:
+            data->mapSecureBuffer = *((int32_t *)param);
+            break;
+        case S3D_FORMAT:
+            data->s3dFormat = *((uint32_t *)param);
+            break;
+        case LINEAR_FORMAT:
+            data->linearFormat = *((uint32_t *)param);
+            break;
+        case SET_SINGLE_BUFFER_MODE:
+            data->isSingleBufferMode = *((uint32_t *)param);
+            break;
+        case SET_VT_TIMESTAMP:
+            data->vtTimeStamp = *((uint64_t *)param);
+            break;
+        case COLOR_METADATA:
+            data->color = *((ColorMetaData *)param);
+            break;
+        case SET_UBWC_CR_STATS_INFO: {
+          struct UBWCStats *stats = (struct UBWCStats *)param;
+          int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+          for (int i = 0; i < numelems; i++) {
+            data->ubwcCRStats[i] = stats[i];
+          }
+          break;
+          }
+        case SET_VIDEO_PERF_MODE:
+            data->isVideoPerfMode = *((uint32_t *)param);
+            break;
+        case SET_GRAPHICS_METADATA: {
+             GraphicsMetadata payload = *((GraphicsMetadata*)(param));
+             data->graphics_metadata.size = payload.size;
+             memcpy(data->graphics_metadata.data, payload.data,
+                    sizeof(data->graphics_metadata.data));
+             break;
+        }
+        case SET_CVP_METADATA: {
+             struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
+             if (cvpMetadata->size <= CVP_METADATA_SIZE) {
+                 data->cvpMetadata.size = cvpMetadata->size;
+                 memcpy(data->cvpMetadata.payload, cvpMetadata->payload,
+                        cvpMetadata->size);
+                 data->cvpMetadata.capture_frame_rate = cvpMetadata->capture_frame_rate;
+                 data->cvpMetadata.cvp_frame_rate = cvpMetadata->cvp_frame_rate;
+                 data->cvpMetadata.flags = cvpMetadata->flags;
+                 memcpy(data->cvpMetadata.reserved, cvpMetadata->reserved,
+                        (8 * sizeof(uint32_t)));
+             } else {
+               setGralloc4Array(data, paramType, false);
+               ALOGE("%s: cvp metadata length %d is more than max size %d", __func__,
+                     cvpMetadata->size, CVP_METADATA_SIZE);
+               return -EINVAL;
+             }
+             break;
+        }
+        case SET_VIDEO_HISTOGRAM_STATS: {
+            struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
+            if (vidstats->stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
+                memcpy(data->video_histogram_stats.stats_info,
+                    vidstats->stats_info, VIDEO_HISTOGRAM_STATS_SIZE);
+                data->video_histogram_stats.stat_len = vidstats->stat_len;
+                data->video_histogram_stats.frame_type = vidstats->frame_type;
+                data->video_histogram_stats.display_width = vidstats->display_width;
+                data->video_histogram_stats.display_height = vidstats->display_height;
+                data->video_histogram_stats.decode_width = vidstats->decode_width;
+                data->video_histogram_stats.decode_height = vidstats->decode_height;
+            } else {
+              setGralloc4Array(data, paramType, false);
+              ALOGE("%s: video stats length %u is more than max size %u", __func__,
+                    vidstats->stat_len, VIDEO_HISTOGRAM_STATS_SIZE);
+              return -EINVAL;
+            }
+            break;
+         }
+        case SET_VIDEO_TS_INFO:
+            data->videoTsInfo = *((VideoTimestampInfo *)param);
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    return 0;
+}
+
+int clearMetaData(private_handle_t *handle, DispParamType paramType) {
+    auto err = validateAndMap(handle);
+    if (err != 0)
+        return err;
+    return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+            paramType);
+}
+
+int clearMetaDataVa(MetaData_t *data, DispParamType paramType) {
+    if (data == nullptr)
+        return -EINVAL;
+    data->operation &= ~paramType;
+    switch (paramType) {
+        case SET_VIDEO_PERF_MODE:
+            data->isVideoPerfMode = 0;
+            break;
+        case SET_CVP_METADATA:
+            data->cvpMetadata.size = 0;
+            break;
+        case SET_VIDEO_HISTOGRAM_STATS:
+            data->video_histogram_stats.stat_len = 0;
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    return 0;
+}
+
+int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
+                                                    void *param) {
+    int ret = validateAndMap(handle);
+    if (ret != 0)
+        return ret;
+    return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
+                         paramType, param);
+}
+
+int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType,
+                  void *param) {
+    // Make sure we send 0 only if the operation queried is present
+    int ret = -EINVAL;
+    if (data == nullptr)
+        return ret;
+    if (param == nullptr)
+        return ret;
+
+    if (!getGralloc4Array(data, paramType)) {
+      return ret;
+    }
+
+    ret = 0;
+
+    switch (paramType) {
+        case GET_PP_PARAM_INTERLACED:
+          *((int32_t *)param) = data->interlaced;
+          break;
+        case GET_BUFFER_GEOMETRY:
+          *((BufferDim_t *)param) = {data->crop.right, data->crop.bottom};
+          break;
+        case GET_REFRESH_RATE:
+          *((float *)param) = data->refreshrate;
+          break;
+        case GET_COLOR_SPACE: {
+          ColorSpace_t color_space;
+          if (!colorMetaDataToColorSpace(data->color, &color_space)) {
+            *((ColorSpace_t *)param) = color_space;
+          } else {
+            ret = -EINVAL;
+          }
+          break;
+        }
+        case GET_MAP_SECURE_BUFFER:
+          *((int32_t *)param) = data->mapSecureBuffer;
+          break;
+        case GET_S3D_FORMAT:
+          *((uint32_t *)param) = data->s3dFormat;
+          break;
+        case GET_LINEAR_FORMAT:
+          *((uint32_t *)param) = data->linearFormat;
+          break;
+        case GET_SINGLE_BUFFER_MODE:
+          *((uint32_t *)param) = data->isSingleBufferMode;
+          break;
+        case GET_VT_TIMESTAMP:
+          *((uint64_t *)param) = data->vtTimeStamp;
+          break;
+        case GET_COLOR_METADATA:
+          *((ColorMetaData *)param) = data->color;
+          break;
+        case GET_UBWC_CR_STATS_INFO: {
+          struct UBWCStats *stats = (struct UBWCStats *)param;
+          int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
+          for (int i = 0; i < numelems; i++) {
+            stats[i] = data->ubwcCRStats[i];
+          }
+          break;
+        }
+        case GET_VIDEO_PERF_MODE:
+          *((uint32_t *)param) = data->isVideoPerfMode;
+          break;
+        case GET_GRAPHICS_METADATA:
+          memcpy(param, data->graphics_metadata.data, sizeof(data->graphics_metadata.data));
+          break;
+        case GET_CVP_METADATA: {
+          struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
+          cvpMetadata->size = 0;
+          if (data->cvpMetadata.size <= CVP_METADATA_SIZE) {
+            cvpMetadata->size = data->cvpMetadata.size;
+            memcpy(cvpMetadata->payload, data->cvpMetadata.payload, data->cvpMetadata.size);
+            cvpMetadata->capture_frame_rate = data->cvpMetadata.capture_frame_rate;
+            cvpMetadata->cvp_frame_rate = data->cvpMetadata.cvp_frame_rate;
+            cvpMetadata->flags = data->cvpMetadata.flags;
+            memcpy(cvpMetadata->reserved, data->cvpMetadata.reserved, (8 * sizeof(uint32_t)));
+          } else {
+            ret = -EINVAL;
+          }
+          break;
+        }
+        case GET_VIDEO_HISTOGRAM_STATS: {
+          struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
+          vidstats->stat_len = 0;
+          if (data->video_histogram_stats.stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
+            memcpy(vidstats->stats_info, data->video_histogram_stats.stats_info,
+                   VIDEO_HISTOGRAM_STATS_SIZE);
+            vidstats->stat_len = data->video_histogram_stats.stat_len;
+            vidstats->frame_type = data->video_histogram_stats.frame_type;
+            vidstats->display_width = data->video_histogram_stats.display_width;
+            vidstats->display_height = data->video_histogram_stats.display_height;
+            vidstats->decode_width = data->video_histogram_stats.decode_width;
+            vidstats->decode_height = data->video_histogram_stats.decode_height;
+          } else {
+            ret = -EINVAL;
+          }
+          break;
+        }
+        case GET_VIDEO_TS_INFO:
+          *((VideoTimestampInfo *)param) = data->videoTsInfo;
+          break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            ret = -EINVAL;
+            break;
+    }
+    return ret;
+}
+
+int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
+    auto err = validateAndMap(src);
+    if (err != 0)
+        return err;
+
+    err = validateAndMap(dst);
+    if (err != 0)
+        return err;
+
+    MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+    MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+    *dst_data = *src_data;
+    return 0;
+}
+
+int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) {
+    int err = -EINVAL;
+    if (src_data == nullptr)
+        return err;
+
+    err = validateAndMap(dst);
+    if (err != 0)
+        return err;
+
+    MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
+    *dst_data = *src_data;
+    return 0;
+}
+
+int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) {
+    int err = -EINVAL;
+    if (dst_data == nullptr)
+        return err;
+
+    err = validateAndMap(src);
+    if (err != 0)
+        return err;
+
+    MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
+    *dst_data = *src_data;
+    return 0;
+}
+
+int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) {
+    int err = -EINVAL;
+    if (src_data == nullptr)
+        return err;
+
+    if (dst_data == nullptr)
+        return err;
+
+    *dst_data = *src_data;
+    return 0;
+}
+
+int setMetaDataAndUnmap(struct private_handle_t *handle, enum DispParamType paramType,
+                        void *param) {
+    auto ret = setMetaData(handle, paramType, param);
+    unmapAndReset(handle);
+    return ret;
+}
+
+int getMetaDataAndUnmap(struct private_handle_t *handle,
+                        enum DispFetchParamType paramType,
+                        void *param) {
+    auto ret = getMetaData(handle, paramType, param);
+    unmapAndReset(handle);
+    return ret;
+}
diff --git a/libqdmetadata/qd_utils.cpp b/libqdmetadata/qd_utils.cpp
new file mode 100644
index 0000000..ac5d094
--- /dev/null
+++ b/libqdmetadata/qd_utils.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2013, 2018, 2020 The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <gralloc_priv.h>
+#include "qd_utils.h"
+
+static const int kFBNodeMax = 4;
+namespace qdutils {
+
+static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
+    char *tmpToken = NULL;
+    char *tmpPtr;
+    uint32_t index = 0;
+    const char *delim = ", =\n";
+    if (!input) {
+      return -1;
+    }
+    tmpToken = strtok_r(input, delim, &tmpPtr);
+    while (tmpToken && index < maxToken) {
+      tokens[index++] = tmpToken;
+      tmpToken = strtok_r(NULL, delim, &tmpPtr);
+    }
+    *count = index;
+
+    return 0;
+}
+
+static int getExternalNode(const char *type) {
+    FILE *displayDeviceFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int j = 0;
+
+    for(j = 0; j < kFBNodeMax; j++) {
+        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+                  "/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
+        displayDeviceFP = fopen(msmFbTypePath, "r");
+        if(displayDeviceFP) {
+            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                    displayDeviceFP);
+            if(strncmp(fbType, type, strlen(type)) == 0) {
+                ALOGD("%s: %s is at fb%d", __func__, type, j);
+                fclose(displayDeviceFP);
+                break;
+            }
+            fclose(displayDeviceFP);
+        } else {
+            ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
+        }
+    }
+
+    if (j < kFBNodeMax)
+        return j;
+    else
+        ALOGE("%s: Failed to find %s node", __func__, type);
+
+    return -1;
+}
+
+int getHDMINode(void) {
+    return getExternalNode("dtv panel");
+}
+
+int getEdidRawData(char *buffer)
+{
+    int size;
+    int edidFile;
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int node_id = getHDMINode();
+
+    if (node_id < 0) {
+        ALOGE("%s no HDMI node found", __func__);
+        return 0;
+    }
+
+    snprintf(msmFbTypePath, sizeof(msmFbTypePath),
+                 "/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
+
+    edidFile = open(msmFbTypePath, O_RDONLY, 0);
+
+    if (edidFile < 0) {
+        ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
+        return 0;
+    }
+
+    size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
+    close(edidFile);
+    return size;
+}
+
+bool isDPConnected() {
+    char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *connectFile = NULL;
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return false;
+    }
+
+    snprintf(connectPath, sizeof(connectPath),
+             "/sys/devices/virtual/graphics/fb%d/connected", nodeId);
+
+    connectFile = fopen(connectPath, "rb");
+    if (!connectFile) {
+        ALOGW("Failed to open connect node for device node %s", connectPath);
+        return false;
+    }
+
+    if (getline(&line, &len, connectFile) < 0) {
+        fclose(connectFile);
+        return false;
+    }
+
+    fclose(connectFile);
+
+    return atoi(line);
+}
+
+int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
+    if (!panelBpp || !patternType) {
+        return -1;
+    }
+
+    char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
+    FILE *configFile = NULL;
+    uint32_t tokenCount = 0;
+    const uint32_t maxCount = 10;
+    char *tokens[maxCount] = { NULL };
+    size_t len = MAX_STRING_LENGTH;
+    char stringBuffer[MAX_STRING_LENGTH];
+    char *line = stringBuffer;
+
+    int nodeId = getExternalNode("dp panel");
+    if (nodeId < 0) {
+        ALOGE("%s no DP node found", __func__);
+        return -EINVAL;
+    }
+
+    snprintf(configPath, sizeof(configPath),
+             "/sys/devices/virtual/graphics/fb%d/config", nodeId);
+
+    configFile = fopen(configPath, "rb");
+    if (!configFile) {
+        ALOGW("Failed to open config node for device node %s", configPath);
+        return -EINVAL;
+    }
+
+    while (getline(&line, &len, configFile) != -1) {
+        if (!parseLine(line, tokens, maxCount, &tokenCount)) {
+            if (tokens[0] != NULL) {
+              if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
+                *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
+              } else  if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
+                *patternType = static_cast<uint32_t>(atoi(tokens[1]));
+              }
+            }
+        }
+    }
+
+    fclose(configFile);
+
+    return 0;
+}
+
+DriverType getDriverType() {
+    const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
+    // 0 - File exists
+    return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
+}
+
+const char *GetHALPixelFormatString(int format) {
+  switch (format) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:
+    return "RGBA_8888";
+  case HAL_PIXEL_FORMAT_RGBX_8888:
+    return "RGBX_8888";
+  case HAL_PIXEL_FORMAT_RGB_888:
+    return "RGB_888";
+  case HAL_PIXEL_FORMAT_RGB_565:
+    return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGR_565:
+    return "BGR_565";
+  case HAL_PIXEL_FORMAT_BGRA_8888:
+    return "BGRA_8888";
+  case HAL_PIXEL_FORMAT_RGBA_5551:
+    return "RGBA_5551";
+  case HAL_PIXEL_FORMAT_RGBA_4444:
+    return "RGBA_4444";
+  case HAL_PIXEL_FORMAT_YV12:
+    return "YV12";
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    return "YCbCr_422_SP_NV16";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    return "YCrCb_420_SP_NV21";
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    return "YCbCr_422_I_YUY2";
+  case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    return "YCrCb_422_I_YVYU";
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    return "NV12_ENCODEABLE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+    return "YCbCr_420_SP_TILED_TILE_4x2";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    return "YCbCr_420_SP";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    return "YCrCb_420_SP_ADRENO";
+  case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    return "YCrCb_422_SP";
+  case HAL_PIXEL_FORMAT_R_8:
+    return "R_8";
+  case HAL_PIXEL_FORMAT_RG_88:
+    return "RG_88";
+  case HAL_PIXEL_FORMAT_INTERLACE:
+    return "INTERLACE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    return "YCbCr_420_SP_VENUS";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+    return "YCrCb_420_SP_VENUS";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    return "YCbCr_420_SP_VENUS_UBWC";
+  case HAL_PIXEL_FORMAT_RGBA_1010102:
+    return "RGBA_1010102";
+  case HAL_PIXEL_FORMAT_ARGB_2101010:
+    return "ARGB_2101010";
+  case HAL_PIXEL_FORMAT_RGBX_1010102:
+    return "RGBX_1010102";
+  case HAL_PIXEL_FORMAT_XRGB_2101010:
+    return "XRGB_2101010";
+  case HAL_PIXEL_FORMAT_BGRA_1010102:
+    return "BGRA_1010102";
+  case HAL_PIXEL_FORMAT_ABGR_2101010:
+    return "ABGR_2101010";
+  case HAL_PIXEL_FORMAT_BGRX_1010102:
+    return "BGRX_1010102";
+  case HAL_PIXEL_FORMAT_XBGR_2101010:
+    return "XBGR_2101010";
+  case HAL_PIXEL_FORMAT_YCbCr_420_P010:
+    return "YCbCr_420_P010";
+  case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+    return "YCbCr_420_TP10_UBWC";
+  case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
+    return "YCbCr_420_P010_VENUS";
+  default:
+    return "Unknown_format";
+  }
+}
+
+}; //namespace qdutils
diff --git a/services/config/src/Android.bp b/services/config/src/Android.bp
new file mode 100644
index 0000000..307f773
--- /dev/null
+++ b/services/config/src/Android.bp
@@ -0,0 +1,24 @@
+cc_library_shared {
+    name: "libdisplayconfig.system.qti",
+    system_ext_specific: true,
+    cflags: [
+        "-Wno-sign-conversion",
+        "-Wno-unused-parameter",
+        "-DLOG_TAG=\"libdisplayconfigqti\"",
+    ],
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libutils",
+        "vendor.display.config@2.0"
+    ],
+    header_libs: ["libhardware_headers", "display_intf_headers"],
+    srcs: [
+        "client_interface.cpp",
+        "client_impl.cpp",
+        "device_impl.cpp",
+        "device_interface.cpp",
+    ],
+    export_header_lib_headers: ["display_intf_headers"],
+}
+
diff --git a/services/config/src/client_impl.cpp b/services/config/src/client_impl.cpp
new file mode 100644
index 0000000..ad0b1fb
--- /dev/null
+++ b/services/config/src/client_impl.cpp
@@ -0,0 +1,1066 @@
+/*
+* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <vector>
+
+#include "client_impl.h"
+
+namespace DisplayConfig {
+
+int ClientImpl::Init(std::string client_name, ConfigCallback *callback) {
+  display_config_ = IDisplayConfig::getService();
+  // Unable to find Display Config 2.0 service. Fail Init.
+  if (!display_config_) {
+    return -1;
+  }
+  int32_t error = 0;
+  uint64_t handle = 0;
+  auto hidl_callback = [&error, &handle] (int32_t err, uint64_t client_handle) {
+    error = err;
+    handle = client_handle;
+  };
+  int pid = getpid();
+  android::sp<ClientCallback> client_cb(new ClientCallback(callback));
+  display_config_->registerClient(client_name + std::to_string(pid), client_cb,
+                                  hidl_callback);
+  client_handle_ = handle;
+
+  return 0;
+}
+
+void ClientImpl::DeInit() {
+  int32_t error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kDestroy, {}, {}, hidl_cb);
+  display_config_.clear();
+  display_config_ = nullptr;
+}
+
+int ClientImpl::IsDisplayConnected(DisplayType dpy, bool *connected) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsDisplayConnected, input_params, {}, hidl_cb);
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *connected = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetDisplayStatus(DisplayType dpy, ExternalStatus status) {
+  struct StatusParams input = {dpy, status};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct StatusParams));
+  int error = 0;
+
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetDisplayStatus, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::ConfigureDynRefreshRate(DynRefreshRateOp op, uint32_t refresh_rate) {
+  struct DynRefreshRateParams input = {op, refresh_rate};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct DynRefreshRateParams));
+  int error = 0;
+
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kConfigureDynRefreshRate, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetConfigCount(DisplayType dpy, uint32_t *count) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType));
+  const uint32_t *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetConfigCount, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const uint32_t*>(data);
+  *count = *output;
+
+  return error;
+}
+
+int ClientImpl::GetActiveConfig(DisplayType dpy, uint32_t *config) {
+  if (!config) {
+    return -EINVAL;
+  }
+
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType));
+  const uint32_t *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  if (display_config_) {
+    display_config_->perform(client_handle_, kGetActiveConfig, input_params, {}, hidl_cb);
+  }
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    output = reinterpret_cast<const uint32_t*>(data);
+    *config = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetActiveConfig(DisplayType dpy, uint32_t config) {
+  struct ConfigParams input = {dpy, config};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct ConfigParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetActiveConfig, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetDisplayAttributes(uint32_t config_index, DisplayType dpy,
+                                     Attributes *attributes) {
+  struct AttributesParams input = {config_index, dpy};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct AttributesParams));
+  const struct Attributes *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetDisplayAttributes, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const Attributes*>(data);
+  if (!error) {
+    *attributes = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetPanelBrightness(uint32_t level) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&level), sizeof(uint32_t));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetPanelBrightness, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetPanelBrightness(uint32_t *level) {
+  const uint32_t *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetPanelBrightness, {}, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const uint32_t*>(data);
+  if (!error) {
+    *level = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::MinHdcpEncryptionLevelChanged(DisplayType dpy, uint32_t min_enc_level) {
+  struct MinHdcpEncLevelChangedParams input = {dpy, min_enc_level};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct MinHdcpEncLevelChangedParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kMinHdcpEncryptionLevelChanged,
+                           input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::RefreshScreen() {
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kRefreshScreen, {}, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::ControlPartialUpdate(DisplayType dpy, bool enable) {
+  struct PartialUpdateParams input = {dpy, enable};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct PartialUpdateParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kControlPartialUpdate, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::ToggleScreenUpdate(bool on) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&on), sizeof(bool));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kToggleScreenUpdate, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::SetIdleTimeout(uint32_t value) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&value), sizeof(uint32_t));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetIdleTimeout, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetHDRCapabilities(DisplayType dpy, HDRCapsParams *caps) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType));
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetHdrCapabilities, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+
+  if (!error) {
+    const int32_t *hdr_caps;
+    const float *lum;
+    size_t size = output_params.size();
+    size_t hdr_caps_size = size - 3 * sizeof(float);
+    hdr_caps_size /= sizeof(int32_t);
+    hdr_caps = reinterpret_cast<const int32_t*>(data);
+    for (size_t i = 0; i < hdr_caps_size; i++) {
+      caps->supported_hdr_types.push_back(*hdr_caps);
+      hdr_caps++;
+    }
+    lum = reinterpret_cast<const float *>(hdr_caps);
+    caps->max_luminance = lum[0];
+    caps->max_avg_luminance = lum[1];
+    caps->min_luminance = lum[2];
+  }
+
+  return error;
+}
+
+int ClientImpl::SetCameraLaunchStatus(uint32_t on) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&on), sizeof(uint32_t));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetCameraLaunchStatus, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::DisplayBWTransactionPending(bool *status) {
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kDisplayBwTransactionPending, {}, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+  if (!error) {
+    *status = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetDisplayAnimating(uint64_t display_id, bool animating) {
+  struct AnimationParams input = {display_id, animating};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct AnimationParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetDisplayAnimating, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::ControlIdlePowerCollapse(bool enable, bool synchronous) {
+  struct IdlePcParams input = {enable, synchronous};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct IdlePcParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kControlIdlePowerCollapse, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetWriteBackCapabilities(bool *is_wb_ubwc_supported) {
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetWritebackCapabilities, {}, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+  if (!error) {
+    *is_wb_ubwc_supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
+                                    uint32_t h_end, uint32_t v_start, uint32_t v_end,
+                                    uint32_t factor_in, uint32_t factor_out) {
+  struct DppsAdRoiParams input = {display_id, h_start, h_end, v_start, v_end,
+                                     factor_in, factor_out};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct DppsAdRoiParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetDisplayDppsAdRoi, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::UpdateVSyncSourceOnPowerModeOff() {
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kUpdateVsyncSourceOnPowerModeOff, {}, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::UpdateVSyncSourceOnPowerModeDoze() {
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kUpdateVsyncSourceOnPowerModeDoze, {}, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::SetPowerMode(uint32_t disp_id, PowerMode power_mode) {
+  struct PowerModeParams input = {disp_id, power_mode};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct PowerModeParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetPowerMode, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::IsPowerModeOverrideSupported(uint32_t disp_id, bool *supported) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsPowerModeOverrideSupported,
+                           input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::IsHDRSupported(uint32_t disp_id, bool *supported) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsHdrSupported, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::IsWCGSupported(uint32_t disp_id, bool *supported) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(int32_t));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsWcgSupported, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
+  struct LayerMaskParams input = {disp_id, layer_id};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct LayerMaskParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetLayerAsMask, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetDebugProperty(const std::string prop_name, std::string *value) {
+  ByteStream input_params;
+  std::string prop(prop_name);
+  prop += '\0';
+  uint8_t *data_input = reinterpret_cast<uint8_t*>(const_cast<char*>(prop.data()));
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(data_input),
+                             prop.size() * sizeof(char));
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetDebugProperty, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  const char *name = reinterpret_cast<const char *>(data);
+  if (!error) {
+    std::string output(name);
+    *value = output;
+  }
+
+  return error;
+}
+
+int ClientImpl::GetActiveBuiltinDisplayAttributes(Attributes *attr) {
+  const struct Attributes *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetActiveBuiltinDisplayAttributes, {}, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const Attributes*>(data);
+  if (!error) {
+    *attr = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetPanelLuminanceAttributes(uint32_t disp_id, float min_lum, float max_lum) {
+  struct PanelLumAttrParams input = {disp_id, min_lum, max_lum};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct PanelLumAttrParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetPanelLuminanceAttributes, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsBuiltinDisplay, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *is_builtin = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed,
+                                   const native_handle_t *buffer) {
+  struct CwbBufferParams input = {disp_id, rect, post_processed};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct CwbBufferParams));
+
+  hidl_handle handle = buffer;
+  std::vector<hidl_handle> handle_vector;
+  handle_vector.push_back(buffer);
+  HandleStream input_handles = handle_vector;
+
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetCwbOutputBuffer, input_params,
+                           input_handles, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetSupportedDSIBitClks(uint32_t disp_id, std::vector<uint64_t> *bit_clks) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetSupportedDsiBitclks, input_params, {}, hidl_cb);
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    const uint64_t *bit_clks_data = reinterpret_cast<const uint64_t *>(data);
+    int num_bit_clks = static_cast<int>(output_params.size() / sizeof(uint64_t));
+    for (int i = 0; i < num_bit_clks; i++) {
+      bit_clks->push_back(bit_clks_data[i]);
+    }
+  }
+
+  return error;
+}
+
+int ClientImpl::GetDSIClk(uint32_t disp_id, uint64_t *bit_clk) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  const uint64_t *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetDsiClk, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const uint64_t*>(data);
+
+  if (!error) {
+    *bit_clk = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::SetDSIClk(uint32_t disp_id, uint64_t bit_clk) {
+  struct DsiClkParams input = {disp_id, bit_clk};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct DsiClkParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetDsiClk, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::SetQsyncMode(uint32_t disp_id, QsyncMode mode) {
+  struct QsyncModeParams input = {disp_id, mode};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct QsyncModeParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSetQsyncMode, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart) {
+  struct SmartPanelCfgParams input = {disp_id, config_id};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct SmartPanelCfgParams));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsSmartPanelConfig, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *is_smart = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::IsAsyncVDSCreationSupported(bool *supported) {
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsAsyncVdsSupported, {}, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t format) {
+  struct VdsParams input = {width, height, format};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct VdsParams));
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kCreateVirtualDisplay, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported) {
+  struct RotatorFormatParams input = {hal_format, ubwc};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct RotatorFormatParams));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsRotatorSupportedFormat, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  output = reinterpret_cast<const bool*>(data);
+
+  if (!error) {
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::ControlQsyncCallback(bool enable) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&enable), sizeof(bool));
+  int32_t error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kControlQsyncCallback, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::ControlIdleStatusCallback(bool enable) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&enable), sizeof(bool));
+  int32_t error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kControlIdleStatusCallback, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::SendTUIEvent(DisplayType dpy, TUIEventType event_type) {
+  struct TUIEventParams input = {dpy, event_type};
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct TUIEventParams));
+  int32_t error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+
+  display_config_->perform(client_handle_, kSendTUIEvent, input_params, {}, hidl_cb);
+
+  return error;
+}
+
+int ClientImpl::GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  ByteStream output_params;
+
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetDisplayHwId, input_params, {}, hidl_cb);
+
+  const uint8_t *data = output_params.data();
+  const uint32_t *output = reinterpret_cast<const uint32_t*>(data);
+
+  if (!error) {
+    *display_hw_id = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::GetSupportedDisplayRefreshRates(DisplayType dpy,
+                                                std::vector<uint32_t> *supported_refresh_rates) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t *>(&dpy), sizeof(DisplayType));
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params](int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kGetSupportedDisplayRefreshRates, input_params, {},
+                           hidl_cb);
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    const uint32_t *refresh_rates_data = reinterpret_cast<const uint32_t *>(data);
+    int num_refresh_rates = static_cast<int>(output_params.size() / sizeof(uint32_t));
+    for (int i = 0; i < num_refresh_rates; i++) {
+      supported_refresh_rates->push_back(refresh_rates_data[i]);
+    }
+  }
+
+  return error;
+}
+
+int ClientImpl::IsRCSupported(uint32_t disp_id, bool *supported) {
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t));
+  const bool *output;
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+
+  display_config_->perform(client_handle_, kIsRCSupported, input_params, {}, hidl_cb);
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    output = reinterpret_cast<const bool*>(data);
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::DummyDisplayConfigAPI() {
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+  display_config_->perform(client_handle_, kDummyOpcode, {}, {}, hidl_cb);
+  if (error) {
+    return -EINVAL;
+  }
+  return error;
+}
+
+int ClientImpl::IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported) {
+  struct SupportedModesParams input = {disp_id, config};
+  ByteStream input_params;
+  ByteStream output_params;
+  const bool *output;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&input),
+                             sizeof(struct SupportedModesParams));
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+  if (display_config_) {
+    display_config_->perform(client_handle_, kIsSupportedConfigSwitch, input_params, {}, hidl_cb);
+  }
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    output = reinterpret_cast<const bool *>(data);
+    *supported = *output;
+  }
+
+  return error;
+}
+
+int ClientImpl::GetDisplayType(uint64_t physical_disp_id, DisplayType *disp_type) {
+  if (!disp_type) {
+    return -EINVAL;
+  }
+  ByteStream input_params;
+  input_params.setToExternal(reinterpret_cast<uint8_t*>(&physical_disp_id), sizeof(uint64_t));
+  ByteStream output_params;
+  int error = 0;
+  auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+    output_params = params;
+  };
+  if (display_config_) {
+    display_config_->perform(client_handle_, kGetDisplayType, input_params, {}, hidl_cb);
+  }
+
+  if (!error) {
+    const uint8_t *data = output_params.data();
+    const DisplayType *output = reinterpret_cast<const DisplayType*>(data);
+    *disp_type = *output;
+  }
+  return error;
+}
+
+int ClientImpl::AllowIdleFallback() {
+  int error = 0;
+  auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) {
+    error = err;
+  };
+  if (display_config_) {
+    display_config_->perform(client_handle_, kAllowIdleFallback, {}, {}, hidl_cb);
+  }
+  return error;
+}
+
+void ClientCallback::ParseNotifyCWBBufferDone(const ByteStream &input_params,
+                                              const HandleStream &input_handles) {
+  const int *error;
+
+  if (callback_ == nullptr || input_params.size() == 0 || input_handles.size() == 0) {
+    return;
+  }
+
+  const uint8_t *data = input_params.data();
+  error = reinterpret_cast<const int*>(data);
+  hidl_handle buffer = input_handles[0];
+  callback_->NotifyCWBBufferDone(*error, buffer.getNativeHandle());
+}
+
+void ClientCallback::ParseNotifyQsyncChange(const ByteStream &input_params) {
+  const struct QsyncCallbackParams *qsync_data;
+
+  if (callback_ == nullptr || input_params.size() == 0) {
+    return;
+  }
+
+  const uint8_t *data = input_params.data();
+  qsync_data = reinterpret_cast<const QsyncCallbackParams*>(data);
+  callback_->NotifyQsyncChange(qsync_data->qsync_enabled, qsync_data->refresh_rate,
+                               qsync_data->qsync_refresh_rate);
+}
+
+void ClientCallback::ParseNotifyIdleStatus(const ByteStream &input_params) {
+  const bool *is_idle;
+  if (callback_ == nullptr || input_params.size() == 0) {
+    return;
+  }
+
+  const uint8_t *data = input_params.data();
+  is_idle = reinterpret_cast<const bool*>(data);
+  callback_->NotifyIdleStatus(*is_idle);
+}
+
+Return<void> ClientCallback::perform(uint32_t op_code, const ByteStream &input_params,
+                                     const HandleStream &input_handles) {
+  switch (op_code) {
+    case kSetCwbOutputBuffer:
+      ParseNotifyCWBBufferDone(input_params, input_handles);
+      break;
+    case kControlQsyncCallback:
+      ParseNotifyQsyncChange(input_params);
+      break;
+    case kControlIdleStatusCallback:
+      ParseNotifyIdleStatus(input_params);
+      break;
+    default:
+      break;
+  }
+
+  return Void();
+}
+
+}  // namespace DisplayConfig
diff --git a/services/config/src/client_impl.h b/services/config/src/client_impl.h
new file mode 100644
index 0000000..48b543a
--- /dev/null
+++ b/services/config/src/client_impl.h
@@ -0,0 +1,139 @@
+/*
+* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __CLIENT_IMPL_H__
+#define __CLIENT_IMPL_H__
+
+#define VALIDATE_CONFIG_SWITCH 1
+
+#include <vendor/display/config/2.0/IDisplayConfig.h>
+#include <hidl/HidlSupport.h>
+#include <log/log.h>
+#include <config/client_interface.h>
+#include <string>
+#include <vector>
+
+#include "opcode_types.h"
+
+namespace DisplayConfig {
+
+using vendor::display::config::V2_0::IDisplayConfig;
+using vendor::display::config::V2_0::IDisplayConfigCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_vec;
+
+typedef hidl_vec<uint8_t> ByteStream;
+typedef hidl_vec<hidl_handle> HandleStream;
+
+class ClientCallback: public IDisplayConfigCallback {
+ public:
+  ClientCallback(ConfigCallback *cb) {
+    callback_ = cb;
+  }
+
+ private:
+  virtual Return<void> perform(uint32_t op_code, const ByteStream &input_params,
+                               const HandleStream &input_handles);
+  void ParseNotifyCWBBufferDone(const ByteStream &input_params, const HandleStream &input_handles);
+  void ParseNotifyQsyncChange(const ByteStream &input_params);
+  void ParseNotifyIdleStatus(const ByteStream &input_params);
+  ConfigCallback *callback_ = nullptr;
+};
+
+class ClientImpl : public ClientInterface {
+ public:
+  int Init(std::string client_name, ConfigCallback *callback);
+  void DeInit();
+
+  virtual int IsDisplayConnected(DisplayType dpy, bool *connected);
+  virtual int SetDisplayStatus(DisplayType dpy, ExternalStatus status);
+  virtual int ConfigureDynRefreshRate(DynRefreshRateOp op, uint32_t refresh_rate);
+  virtual int GetConfigCount(DisplayType dpy, uint32_t *count);
+  virtual int GetActiveConfig(DisplayType dpy, uint32_t *config);
+  virtual int SetActiveConfig(DisplayType dpy, uint32_t config);
+  virtual int GetDisplayAttributes(uint32_t config_index, DisplayType dpy, Attributes *attributes);
+  virtual int SetPanelBrightness(uint32_t level);
+  virtual int GetPanelBrightness(uint32_t *level);
+  virtual int MinHdcpEncryptionLevelChanged(DisplayType dpy, uint32_t min_enc_level);
+  virtual int RefreshScreen();
+  virtual int ControlPartialUpdate(DisplayType dpy, bool enable);
+  virtual int ToggleScreenUpdate(bool on);
+  virtual int SetIdleTimeout(uint32_t value);
+  virtual int GetHDRCapabilities(DisplayType dpy, HDRCapsParams *caps);
+  virtual int SetCameraLaunchStatus(uint32_t on);
+  virtual int DisplayBWTransactionPending(bool *status);
+  virtual int SetDisplayAnimating(uint64_t display_id, bool animating);
+  virtual int ControlIdlePowerCollapse(bool enable, bool synchronous);
+  virtual int GetWriteBackCapabilities(bool *is_wb_ubwc_supported);
+  virtual int SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start, uint32_t h_end,
+                                  uint32_t v_start, uint32_t v_end, uint32_t factor_in,
+                                  uint32_t factor_out);
+  virtual int UpdateVSyncSourceOnPowerModeOff();
+  virtual int UpdateVSyncSourceOnPowerModeDoze();
+  virtual int SetPowerMode(uint32_t disp_id, PowerMode power_mode);
+  virtual int IsPowerModeOverrideSupported(uint32_t disp_id, bool *supported);
+  virtual int IsHDRSupported(uint32_t disp_id, bool *supported);
+  virtual int IsWCGSupported(uint32_t disp_id, bool *supported);
+  virtual int SetLayerAsMask(uint32_t disp_id, uint64_t layer_id);
+  virtual int GetDebugProperty(const std::string prop_name, std::string *value);
+  virtual int GetActiveBuiltinDisplayAttributes(Attributes *attr);
+  virtual int SetPanelLuminanceAttributes(uint32_t disp_id, float min_lum, float max_lum);
+  virtual int IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin);
+  virtual int IsAsyncVDSCreationSupported(bool *supported);
+  virtual int CreateVirtualDisplay(uint32_t width, uint32_t height, int format);
+  virtual int GetSupportedDSIBitClks(uint32_t disp_id, std::vector<uint64_t> *bit_clks);
+  virtual int GetDSIClk(uint32_t disp_id, uint64_t *bit_clk);
+  virtual int SetDSIClk(uint32_t disp_id, uint64_t bit_clk);
+  virtual int SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed,
+                                 const native_handle_t *buffer);
+  virtual int SetQsyncMode(uint32_t disp_id, QsyncMode mode);
+  virtual int IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart);
+  virtual int IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported);
+  virtual int ControlQsyncCallback(bool enable);
+  virtual int SendTUIEvent(DisplayType dpy, TUIEventType event_type);
+  virtual int GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id);
+  virtual int GetSupportedDisplayRefreshRates(DisplayType dpy,
+                                              std::vector<uint32_t> *supported_refresh_rates);
+  virtual int IsRCSupported(uint32_t disp_id, bool *supported);
+  virtual int ControlIdleStatusCallback(bool enable);
+  virtual int IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported);
+  virtual int GetDisplayType(uint64_t physical_disp_id, DisplayType *disp_type);
+  virtual int AllowIdleFallback();
+  virtual int DummyDisplayConfigAPI();
+
+ private:
+  android::sp<IDisplayConfig> display_config_ = nullptr;
+  uint64_t client_handle_ = 0;
+};
+
+}  // namespace DisplayConfig
+
+#endif  // __CLIENT_IMPL_H__
diff --git a/services/config/src/client_interface.cpp b/services/config/src/client_interface.cpp
new file mode 100644
index 0000000..9c9ecd2
--- /dev/null
+++ b/services/config/src/client_interface.cpp
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+
+#include "client_impl.h"
+
+namespace DisplayConfig {
+
+int ClientInterface::Create(std::string client_name, ConfigCallback *callback,
+                            ClientInterface **intf) {
+  if (!intf) {
+    return -1;
+  }
+
+  ClientImpl *impl = new ClientImpl();
+  if (!impl) {
+    return -1;
+  }
+
+  int ret = impl->Init(client_name, callback);
+  if (ret) {
+    delete impl;
+    return -1;
+  }
+
+  *intf = impl;
+  return 0;
+}
+
+void ClientInterface::Destroy(ClientInterface *intf) {
+  if (intf) {
+    ClientImpl *impl = static_cast<ClientImpl *>(intf);
+    impl->DeInit();
+    delete impl;
+  }
+}
+
+}  // namespace DisplayConfig
diff --git a/services/config/src/device_impl.cpp b/services/config/src/device_impl.cpp
new file mode 100644
index 0000000..df4731f
--- /dev/null
+++ b/services/config/src/device_impl.cpp
@@ -0,0 +1,1040 @@
+/*
+* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string>
+#include <vector>
+
+#include "device_impl.h"
+
+namespace DisplayConfig {
+
+DeviceImpl *DeviceImpl::device_obj_ = nullptr;
+std::mutex DeviceImpl::device_lock_;
+
+int DeviceImpl::CreateInstance(ClientContext *intf) {
+  std::lock_guard<std::mutex> lock(device_lock_);
+  if (!device_obj_) {
+    device_obj_ = new DeviceImpl();
+    if (!device_obj_) {
+      return -1;
+    }
+
+    android::status_t status = device_obj_->IDisplayConfig::registerAsService();
+    // Unable to start Display Config 2.0 service. Fail Init.
+    if (status != android::OK) {
+      delete device_obj_;
+      device_obj_ = nullptr;
+      return -1;
+    }
+    device_obj_->intf_ = intf;
+  }
+
+  return 0;
+}
+
+Return<void> DeviceImpl::registerClient(const hidl_string &client_name,
+                                        const sp<IDisplayConfigCallback>& callback,
+                                        registerClient_cb _hidl_cb) {
+  ALOGI("Register client:%s", client_name.c_str());
+  int32_t error = 0;
+  std::string client_name_str = client_name.c_str();
+  if (client_name_str.empty()) {
+    error = -EINVAL;
+    _hidl_cb(error, 0);
+    return Void();
+  }
+
+  if (!callback) {
+    ALOGW("IDisplayConfigCallback provided is null");
+  }
+
+  uint64_t client_handle = static_cast<uint64_t>(client_id_++);
+  std::shared_ptr<DeviceClientContext> device_client(new DeviceClientContext(callback));
+  if (callback) {
+    callback->linkToDeath(this, client_handle);
+  }
+
+  if (!intf_) {
+    ALOGW("ConfigInterface is invalid");
+    _hidl_cb(error, 0);
+    return Void();
+  }
+
+  if (!device_client) {
+    ALOGW("Failed to initialize device client:%s", client_name.c_str());
+    _hidl_cb(error, 0);
+    return Void();
+  }
+
+  ConfigInterface *intf = nullptr;
+  error = intf_->RegisterClientContext(device_client, &intf);
+
+  if (error) {
+    callback->unlinkToDeath(this);
+    return Void();
+  }
+
+  device_client->SetDeviceConfigIntf(intf);
+
+  display_config_map_.emplace(std::make_pair(client_handle, device_client));
+  _hidl_cb(error, client_handle);
+  return Void();
+}
+
+void DeviceImpl::serviceDied(uint64_t client_handle,
+                             const android::wp<::android::hidl::base::V1_0::IBase>& callback) {
+  std::lock_guard<std::mutex> lock(death_service_mutex_);
+  auto itr = display_config_map_.find(client_handle);
+  std::shared_ptr<DeviceClientContext> client = itr->second;
+  if (client != NULL) {
+    ConfigInterface *intf = client->GetDeviceConfigIntf();
+    intf_->UnRegisterClientContext(intf);
+    client.reset();
+    display_config_map_.erase(itr);
+  }
+}
+
+DeviceImpl::DeviceClientContext::DeviceClientContext(
+            const sp<IDisplayConfigCallback> callback) : callback_(callback) { }
+
+sp<IDisplayConfigCallback> DeviceImpl::DeviceClientContext::GetDeviceConfigCallback() {
+  return callback_;
+}
+
+void DeviceImpl::DeviceClientContext::SetDeviceConfigIntf(ConfigInterface *intf) {
+  intf_ = intf;
+}
+
+ConfigInterface* DeviceImpl::DeviceClientContext::GetDeviceConfigIntf() {
+  return intf_;
+}
+
+void DeviceImpl::DeviceClientContext::NotifyCWBBufferDone(int32_t error,
+                                                          const native_handle_t *buffer) {
+  ByteStream output_params;
+  HandleStream output_handles;
+  std::vector<hidl_handle> handles;
+
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&error), sizeof(int));
+  handles.push_back(buffer);
+  output_handles = handles;
+
+  auto status = callback_->perform(kSetCwbOutputBuffer, output_params, output_handles);
+  if (status.isDeadObject()) {
+    return;
+  }
+}
+
+void DeviceImpl::DeviceClientContext::NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate,
+                                                        int32_t qsync_refresh_rate) {
+  struct QsyncCallbackParams data = {qsync_enabled, refresh_rate, qsync_refresh_rate};
+  ByteStream output_params;
+
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&data), sizeof(data));
+
+  auto status = callback_->perform(kControlQsyncCallback, output_params, {});
+  if (status.isDeadObject()) {
+    return;
+  }
+}
+
+void DeviceImpl::DeviceClientContext::NotifyIdleStatus(bool is_idle) {
+  bool data = {is_idle};
+  ByteStream output_params;
+
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&data), sizeof(data));
+
+  auto status = callback_->perform(kControlIdleStatusCallback, output_params, {});
+  if (status.isDeadObject()) {
+    return;
+  }
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsDisplayConnected(const ByteStream &input_params,
+                                                              perform_cb _hidl_cb) {
+  const DisplayType *dpy;
+  bool connected = false;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  dpy = reinterpret_cast<const DisplayType*>(data);
+  int32_t error = intf_->IsDisplayConnected(*dpy, &connected);
+
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&connected),
+                              sizeof(connected));
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetDisplayStatus(const ByteStream &input_params,
+                                                            perform_cb _hidl_cb) {
+  const struct StatusParams *display_status;
+  const uint8_t *data = input_params.data();
+  display_status = reinterpret_cast<const StatusParams*>(data);
+  int32_t error = intf_->SetDisplayStatus(display_status->dpy,
+                                          display_status->status);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseConfigureDynRefreshRate(const ByteStream &input_params,
+                                                                   perform_cb _hidl_cb) {
+  const struct DynRefreshRateParams *dyn_refresh_data;
+  const uint8_t *data = input_params.data();
+  dyn_refresh_data = reinterpret_cast<const DynRefreshRateParams*>(data);
+  int32_t error = intf_->ConfigureDynRefreshRate(dyn_refresh_data->op,
+                                                 dyn_refresh_data->refresh_rate);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetConfigCount(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const DisplayType *dpy;
+  uint32_t count = 0;
+  ByteStream output_params;
+
+  if (input_params.size() == 0) {
+    _hidl_cb(-ENODATA, {}, {});
+    return;
+  }
+
+  const uint8_t *data = input_params.data();
+  dpy = reinterpret_cast<const DisplayType*>(data);
+  int32_t error = intf_->GetConfigCount(*dpy, &count);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&count),
+                              sizeof(uint32_t));
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetActiveConfig(const ByteStream &input_params,
+                                                           perform_cb _hidl_cb) {
+  const DisplayType *dpy;
+  uint32_t config = 0;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  dpy = reinterpret_cast<const DisplayType*>(data);
+  int32_t error = intf_->GetActiveConfig(*dpy, &config);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&config),
+                              sizeof(uint32_t));
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetActiveConfig(const ByteStream &input_params,
+                                                           perform_cb _hidl_cb) {
+  const struct ConfigParams *set_active_cfg_data;
+
+  const uint8_t *data = input_params.data();
+  set_active_cfg_data = reinterpret_cast<const ConfigParams*>(data);
+  int32_t error = intf_->SetActiveConfig(set_active_cfg_data->dpy,
+                                         set_active_cfg_data->config);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetDisplayAttributes(const ByteStream &input_params,
+                                                                perform_cb _hidl_cb) {
+  const struct AttributesParams *get_disp_attr_data;
+  struct Attributes attributes = {};
+  ByteStream output_params;
+  int32_t error = -EINVAL;
+
+  const uint8_t *data = input_params.data();
+  get_disp_attr_data = reinterpret_cast<const AttributesParams*>(data);
+  error = intf_->GetDisplayAttributes(get_disp_attr_data->config_index, get_disp_attr_data->dpy,
+                                      &attributes);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&attributes),
+                              sizeof(struct Attributes));
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetPanelBrightness(const ByteStream &input_params,
+                                                              perform_cb _hidl_cb) {
+  const uint32_t *level;
+  int32_t error = 0;
+
+  const uint8_t *data = input_params.data();
+  level = reinterpret_cast<const uint32_t*>(data);
+  error = intf_->SetPanelBrightness(*level);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetPanelBrightness(perform_cb _hidl_cb) {
+  uint32_t level = 0;
+  ByteStream output_params;
+  int32_t error = -EINVAL;
+
+  error = intf_->GetPanelBrightness(&level);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&level),
+                              sizeof(uint32_t));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseMinHdcpEncryptionLevelChanged(
+                                      const ByteStream &input_params,
+                                      perform_cb _hidl_cb) {
+  const struct MinHdcpEncLevelChangedParams *min_hdcp_enc_level_data;
+  int32_t error = 0;
+
+  const uint8_t *data = input_params.data();
+  min_hdcp_enc_level_data = reinterpret_cast<const MinHdcpEncLevelChangedParams*>(data);
+  error = intf_->MinHdcpEncryptionLevelChanged(min_hdcp_enc_level_data->dpy,
+                                               min_hdcp_enc_level_data->min_enc_level);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseRefreshScreen(perform_cb _hidl_cb) {
+  int32_t error = intf_->RefreshScreen();
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseControlPartialUpdate(const ByteStream &input_params,
+                                                                perform_cb _hidl_cb) {
+  const struct PartialUpdateParams *partial_update_data;
+  int32_t error = 0;
+
+  const uint8_t *data = input_params.data();
+  partial_update_data = reinterpret_cast<const PartialUpdateParams*>(data);
+  error = intf_->ControlPartialUpdate(partial_update_data->dpy, partial_update_data->enable);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseToggleScreenUpdate(const ByteStream &input_params,
+                                                              perform_cb _hidl_cb) {
+  const bool *on;
+  int32_t error = 0;
+
+  const uint8_t *data = input_params.data();
+  on = reinterpret_cast<const bool*>(data);
+  error = intf_->ToggleScreenUpdate(on);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetIdleTimeout(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const uint32_t *timeout_value;
+
+  const uint8_t *data = input_params.data();
+  timeout_value = reinterpret_cast<const uint32_t*>(data);
+  int32_t error = intf_->SetIdleTimeout(*timeout_value);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetHdrCapabilities(const ByteStream &input_params,
+                                                              perform_cb _hidl_cb) {
+  const DisplayType *dpy;
+  ByteStream output_params;
+  struct HDRCapsParams hdr_caps;
+  int32_t *data_output;
+  int32_t error = -EINVAL;
+
+  const uint8_t *data = input_params.data();
+  dpy = reinterpret_cast<const DisplayType*>(data);
+  error = intf_->GetHDRCapabilities(*dpy, &hdr_caps);
+
+  data_output = reinterpret_cast<int32_t *>(malloc(sizeof(int32_t) *
+                hdr_caps.supported_hdr_types.size() + 3 * sizeof(float)));
+  if (data_output != NULL) {
+    for (int i = 0; i < hdr_caps.supported_hdr_types.size(); i++) {
+      data_output[i] = hdr_caps.supported_hdr_types[i];
+    }
+    float *lum = reinterpret_cast<float *>(&data_output[hdr_caps.supported_hdr_types.size()]);
+    *lum = hdr_caps.max_luminance;
+    lum++;
+    *lum = hdr_caps.max_avg_luminance;
+    lum++;
+    *lum = hdr_caps.min_luminance;
+    output_params.setToExternal(reinterpret_cast<uint8_t*>(data_output), sizeof(int32_t) *
+                                hdr_caps.supported_hdr_types.size() + 3 * sizeof(float));
+    _hidl_cb(error, output_params, {});
+  }
+  else {
+    _hidl_cb(-EINVAL, {}, {});
+  }
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetCameraLaunchStatus(const ByteStream &input_params,
+                                                                 perform_cb _hidl_cb) {
+  const uint32_t *launch_status_data;
+
+  const uint8_t *data = input_params.data();
+  launch_status_data = reinterpret_cast<const uint32_t*>(data);
+
+  int32_t error = intf_->SetCameraLaunchStatus(*launch_status_data);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseDisplayBwTransactionPending(perform_cb _hidl_cb) {
+  bool status = true;
+  ByteStream output_params;
+
+  int32_t error = intf_->DisplayBWTransactionPending(&status);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&status),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetDisplayAnimating(const ByteStream &input_params,
+                                                               perform_cb _hidl_cb) {
+  const struct AnimationParams *display_animating_data;
+
+  const uint8_t *data = input_params.data();
+  display_animating_data = reinterpret_cast<const AnimationParams*>(data);
+  int32_t error = intf_->SetDisplayAnimating(display_animating_data->display_id,
+                                             display_animating_data->animating);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseControlIdlePowerCollapse(const ByteStream &input_params,
+                                                                    perform_cb _hidl_cb) {
+  const struct IdlePcParams *idle_pc_data;
+
+  const uint8_t *data = input_params.data();
+  idle_pc_data = reinterpret_cast<const IdlePcParams*>(data);
+  int32_t error = intf_->ControlIdlePowerCollapse(idle_pc_data->enable, idle_pc_data->synchronous);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetWritebackCapabilities(perform_cb _hidl_cb) {
+  bool is_wb_ubwc_supported = false;
+  int32_t error = intf_->GetWriteBackCapabilities(&is_wb_ubwc_supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_wb_ubwc_supported),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetDisplayDppsAdRoi(const ByteStream &input_params,
+                                                               perform_cb _hidl_cb) {
+  const struct DppsAdRoiParams *ad_roi_data;
+
+  const uint8_t *data = input_params.data();
+  ad_roi_data = reinterpret_cast<const DppsAdRoiParams*>(data);
+
+  int32_t error = intf_->SetDisplayDppsAdROI(ad_roi_data->display_id, ad_roi_data->h_start,
+                                             ad_roi_data->h_end, ad_roi_data->v_start,
+                                             ad_roi_data->v_end, ad_roi_data->factor_in,
+                                             ad_roi_data->factor_out);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseUpdateVsyncSourceOnPowerModeOff(perform_cb _hidl_cb) {
+  int32_t error = intf_->UpdateVSyncSourceOnPowerModeOff();
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseUpdateVsyncSourceOnPowerModeDoze(perform_cb _hidl_cb) {
+  int32_t error = intf_->UpdateVSyncSourceOnPowerModeDoze();
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetPowerMode(const ByteStream &input_params,
+                                                        perform_cb _hidl_cb) {
+  const struct PowerModeParams *set_power_mode_data;
+
+  const uint8_t *data = input_params.data();
+  set_power_mode_data = reinterpret_cast<const PowerModeParams*>(data);
+  int32_t error = intf_->SetPowerMode(set_power_mode_data->disp_id,
+                                      set_power_mode_data->power_mode);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsPowerModeOverrideSupported(
+                                      const ByteStream &input_params,
+                                      perform_cb _hidl_cb) {
+  const uint8_t *data = input_params.data();
+  const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data);
+  bool supported = false;
+  int32_t error = intf_->IsPowerModeOverrideSupported(*disp_id, &supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsHdrSupported(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const uint8_t *data = input_params.data();
+  const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data);
+  bool supported = false;
+  int32_t error = intf_->IsHDRSupported(*disp_id, &supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsWcgSupported(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const uint8_t *data = input_params.data();
+  const int32_t *disp_id = reinterpret_cast<const int32_t*>(data);
+  bool supported = false;
+  int32_t error = intf_->IsWCGSupported(*disp_id, &supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetLayerAsMask(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const struct LayerMaskParams *layer_mask_data;
+
+  const uint8_t *data = input_params.data();
+  layer_mask_data = reinterpret_cast<const LayerMaskParams*>(data);
+  int32_t error = intf_->SetLayerAsMask(layer_mask_data->disp_id, layer_mask_data->layer_id);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetDebugProperty(const ByteStream &input_params,
+                                                            perform_cb _hidl_cb) {
+  std::string value;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  const char *name = reinterpret_cast<const char *>(data);
+  std::string prop_name(name);
+  int32_t error = intf_->GetDebugProperty(prop_name, &value);
+  value += '\0';
+  uint8_t *data_output = reinterpret_cast<uint8_t*>(value.data());
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(data_output),
+                              value.size() * sizeof(char));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetActiveBuiltinDisplayAttributes(perform_cb _hidl_cb) {
+  struct Attributes attr;
+  ByteStream output_params;
+
+  int32_t error = intf_->GetActiveBuiltinDisplayAttributes(&attr);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&attr), sizeof(Attributes));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetPanelLuminanceAttributes(
+                                      const ByteStream &input_params,
+                                      perform_cb _hidl_cb) {
+  const struct PanelLumAttrParams *panel_lum_attr_data;
+
+  const uint8_t *data = input_params.data();
+  panel_lum_attr_data = reinterpret_cast<const PanelLumAttrParams*>(data);
+  int32_t error = intf_->SetPanelLuminanceAttributes(panel_lum_attr_data->disp_id,
+                                                     panel_lum_attr_data->min_lum,
+                                                     panel_lum_attr_data->max_lum);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsBuiltinDisplay(const ByteStream &input_params,
+                                                            perform_cb _hidl_cb) {
+  const uint32_t *disp_id;
+  bool is_builtin = false;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  disp_id = reinterpret_cast<const uint32_t*>(data);
+  int32_t error = intf_->IsBuiltInDisplay(*disp_id, &is_builtin);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_builtin),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetCwbOutputBuffer(uint64_t clientHandle,
+                                                              const ByteStream &input_params,
+                                                              const HandleStream &input_handles,
+                                                              perform_cb _hidl_cb) {
+  const struct CwbBufferParams *cwb_buffer_data;
+
+  const uint8_t *data = input_params.data();
+  cwb_buffer_data = reinterpret_cast<const CwbBufferParams*>(data);
+  hidl_handle buffer = input_handles[0];
+
+  if (!callback_ || !buffer.getNativeHandle()) {
+    _hidl_cb(-1, {}, {});
+    return;
+  }
+
+  int32_t error = intf_->SetCWBOutputBuffer(cwb_buffer_data->disp_id , cwb_buffer_data->rect,
+                                            cwb_buffer_data->post_processed,
+                                            buffer.getNativeHandle());
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetSupportedDsiBitclks(const ByteStream &input_params,
+                                                                  perform_cb _hidl_cb) {
+  const uint32_t *disp_id;
+  ByteStream output_params;
+  std::vector<uint64_t> bit_clks;
+  uint64_t *bit_clks_data;
+
+  const uint8_t *data = input_params.data();
+  disp_id = reinterpret_cast<const uint32_t*>(data);
+  int32_t error = intf_->GetSupportedDSIBitClks(*disp_id, &bit_clks);
+
+  bit_clks_data = reinterpret_cast<uint64_t *>(malloc(sizeof(uint64_t) * bit_clks.size()));
+  if (bit_clks_data == NULL) {
+    _hidl_cb(-EINVAL, {}, {});
+    return;
+  }
+  for (int i = 0; i < bit_clks.size(); i++) {
+    bit_clks_data[i] = bit_clks[i];
+  }
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(bit_clks_data),
+                              sizeof(uint64_t) * bit_clks.size());
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetDsiClk(const ByteStream &input_params,
+                                                     perform_cb _hidl_cb) {
+  const uint32_t *disp_id;
+  uint64_t bit_clk = 0;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  disp_id = reinterpret_cast<const uint32_t*>(data);
+  int32_t error = intf_->GetDSIClk(*disp_id, &bit_clk);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&bit_clk),
+                              sizeof(uint64_t));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetDsiClk(const ByteStream &input_params,
+                                                     perform_cb _hidl_cb) {
+  const struct DsiClkParams *set_dsi_clk_data;
+
+  const uint8_t *data = input_params.data();
+  set_dsi_clk_data = reinterpret_cast<const DsiClkParams*>(data);
+  int32_t error = intf_->SetDSIClk(set_dsi_clk_data->disp_id, set_dsi_clk_data->bit_clk);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSetQsyncMode(const ByteStream &input_params,
+                                                        perform_cb _hidl_cb) {
+  const struct QsyncModeParams *set_qsync_mode_data;
+
+  const uint8_t *data = input_params.data();
+  set_qsync_mode_data = reinterpret_cast<const QsyncModeParams*>(data);
+  int32_t error = intf_->SetQsyncMode(set_qsync_mode_data->disp_id, set_qsync_mode_data->mode);
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsSmartPanelConfig(const ByteStream &input_params,
+                                                              perform_cb _hidl_cb) {
+  const struct SmartPanelCfgParams *smart_panel_cfg_data;
+  bool is_smart = false;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  smart_panel_cfg_data = reinterpret_cast<const SmartPanelCfgParams*>(data);
+  int32_t error = intf_->IsSmartPanelConfig(smart_panel_cfg_data->disp_id,
+                                            smart_panel_cfg_data->config_id, &is_smart);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_smart),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsAsyncVdsSupported(perform_cb _hidl_cb) {
+  bool is_supported = false;
+  int32_t error = intf_->IsAsyncVDSCreationSupported(&is_supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_supported),
+                             sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseCreateVirtualDisplay(const ByteStream &input_params,
+                                                                perform_cb _hidl_cb) {
+  const struct VdsParams *vds_input_data;
+
+  const uint8_t *data = input_params.data();
+  vds_input_data = reinterpret_cast<const VdsParams*>(data);
+
+  int32_t error = intf_->CreateVirtualDisplay(vds_input_data->width, vds_input_data->height,
+                                              vds_input_data->format);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsRotatorSupportedFormat(const ByteStream &input_params,
+                                                                    perform_cb _hidl_cb) {
+  const struct RotatorFormatParams *input_data;
+  bool supported = false;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  input_data = reinterpret_cast<const RotatorFormatParams*>(data);
+  int32_t error = intf_->IsRotatorSupportedFormat(input_data->hal_format, input_data->ubwc,
+                                                  &supported);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported),
+                              sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseControlQsyncCallback(uint64_t client_handle,
+                                                                const ByteStream &input_params,
+                                                                perform_cb _hidl_cb) {
+  const bool *enable;
+
+  const uint8_t *data = input_params.data();
+  enable = reinterpret_cast<const bool*>(data);
+
+  int32_t error = intf_->ControlQsyncCallback(*enable);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseControlIdleStatusCallback(uint64_t client_handle,
+                                                                     const ByteStream &input_params,
+                                                                     perform_cb _hidl_cb) {
+  const bool *enable;
+
+  const uint8_t *data = input_params.data();
+  enable = reinterpret_cast<const bool*>(data);
+
+  int32_t error = intf_->ControlIdleStatusCallback(*enable);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseSendTUIEvent(const ByteStream &input_params,
+                                                        perform_cb _hidl_cb) {
+  const struct TUIEventParams *input_data =
+               reinterpret_cast<const TUIEventParams*>(input_params.data());
+
+  int32_t error = intf_->SendTUIEvent(input_data->dpy, input_data->tui_event_type);
+
+  _hidl_cb(error, {}, {});
+}
+
+void DeviceImpl::ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb) {
+  auto itr = display_config_map_.find(client_handle);
+  if (itr == display_config_map_.end()) {
+    _hidl_cb(-EINVAL, {}, {});
+    return;
+  }
+
+  std::shared_ptr<DeviceClientContext> client = itr->second;
+  if (client != NULL) {
+    sp<IDisplayConfigCallback> callback = client->GetDeviceConfigCallback();
+    callback->unlinkToDeath(this);
+    ConfigInterface *intf = client->GetDeviceConfigIntf();
+    intf_->UnRegisterClientContext(intf);
+    client.reset();
+    display_config_map_.erase(itr);
+  }
+
+  _hidl_cb(0, {}, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetDisplayHwId(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  uint32_t disp_hw_id = 0;
+  ByteStream output_params;
+
+  const uint8_t *data = input_params.data();
+  const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data);
+  int32_t error = intf_->GetDisplayHwId(*disp_id, &disp_hw_id);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_hw_id), sizeof(uint32_t));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetSupportedDisplayRefreshRates(
+    const ByteStream &input_params, perform_cb _hidl_cb) {
+  ByteStream output_params;
+  std::vector<uint32_t> refresh_rates;
+
+  const uint8_t *data = input_params.data();
+  const DisplayType *dpy = reinterpret_cast<const DisplayType *>(data);
+  int32_t error = intf_->GetSupportedDisplayRefreshRates(*dpy, &refresh_rates);
+
+  uint32_t *refresh_rates_data =
+      reinterpret_cast<uint32_t *>(malloc(sizeof(uint32_t) * refresh_rates.size()));
+  if (refresh_rates_data) {
+    for (int i = 0; i < refresh_rates.size(); i++) {
+      refresh_rates_data[i] = refresh_rates[i];
+    }
+    output_params.setToExternal(reinterpret_cast<uint8_t *>(refresh_rates_data),
+                                sizeof(uint32_t) * refresh_rates.size());
+    _hidl_cb(error, output_params, {});
+  } else {
+    _hidl_cb(-EINVAL, {}, {});
+  }
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsRCSupported(const ByteStream &input_params,
+                                                         perform_cb _hidl_cb) {
+  const uint8_t *data = input_params.data();
+  const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data);
+  bool supported = false;
+  int32_t error = intf_->IsRCSupported(*disp_id, &supported);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), sizeof(bool));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseIsSupportedConfigSwitch(const ByteStream &input_params,
+                                                                 perform_cb _hidl_cb) {
+  if (!intf_) {
+    _hidl_cb(-EINVAL, {}, {});
+    return;
+  }
+
+  const struct SupportedModesParams *supported_modes_data;
+  const uint8_t *data = input_params.data();
+  bool supported = false;
+  ByteStream output_params;
+  supported_modes_data = reinterpret_cast<const SupportedModesParams*>(data);
+
+  int32_t error = intf_->IsSupportedConfigSwitch(supported_modes_data->disp_id,
+                                               supported_modes_data->mode, &supported);
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), sizeof(bool));
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseGetDisplayType(const ByteStream &input_params,
+                                                          perform_cb _hidl_cb) {
+  const uint8_t *data = input_params.data();
+  const uint64_t *physical_disp_id = reinterpret_cast<const uint64_t*>(data);
+  DisplayType disp_type = DisplayConfig::DisplayType::kInvalid;
+  int32_t error = intf_->GetDisplayType(*physical_disp_id, &disp_type);
+  ByteStream output_params;
+  output_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_type), sizeof(DisplayType));
+
+  _hidl_cb(error, output_params, {});
+}
+
+void DeviceImpl::DeviceClientContext::ParseAllowIdleFallback(perform_cb _hidl_cb) {
+  int32_t error = intf_->AllowIdleFallback();
+  _hidl_cb(error, {}, {});
+}
+
+Return<void> DeviceImpl::perform(uint64_t client_handle, uint32_t op_code,
+                                 const ByteStream &input_params, const HandleStream &input_handles,
+                                 perform_cb _hidl_cb) {
+  int32_t error = 0;
+  auto itr = display_config_map_.find(client_handle);
+  if (itr == display_config_map_.end()) {
+    error = -EINVAL;
+    _hidl_cb(error, {}, {});
+    return Void();
+  }
+
+  std::shared_ptr<DeviceClientContext> client = itr->second;
+  if (!client) {
+    error = -EINVAL;
+    _hidl_cb(error, {}, {});
+     return Void();
+  }
+  switch (op_code) {
+    case kIsDisplayConnected:
+      client->ParseIsDisplayConnected(input_params, _hidl_cb);
+      break;
+    case kSetDisplayStatus:
+      client->ParseSetDisplayStatus(input_params, _hidl_cb);
+      break;
+    case kConfigureDynRefreshRate:
+      client->ParseConfigureDynRefreshRate(input_params, _hidl_cb);
+      break;
+    case kGetConfigCount:
+      client->ParseGetConfigCount(input_params, _hidl_cb);
+      break;
+    case kGetActiveConfig:
+      client->ParseGetActiveConfig(input_params, _hidl_cb);
+      break;
+    case kSetActiveConfig:
+      client->ParseSetActiveConfig(input_params, _hidl_cb);
+      break;
+    case kGetDisplayAttributes:
+      client->ParseGetDisplayAttributes(input_params, _hidl_cb);
+      break;
+    case kSetPanelBrightness:
+      client->ParseSetPanelBrightness(input_params, _hidl_cb);
+      break;
+    case kGetPanelBrightness:
+      client->ParseGetPanelBrightness(_hidl_cb);
+      break;
+    case kMinHdcpEncryptionLevelChanged:
+      client->ParseMinHdcpEncryptionLevelChanged(input_params, _hidl_cb);
+      break;
+    case kRefreshScreen:
+      client->ParseRefreshScreen(_hidl_cb);
+      break;
+    case kControlPartialUpdate:
+      client->ParseControlPartialUpdate(input_params, _hidl_cb);
+      break;
+    case kToggleScreenUpdate:
+      client->ParseToggleScreenUpdate(input_params, _hidl_cb);
+      break;
+    case kSetIdleTimeout:
+      client->ParseSetIdleTimeout(input_params, _hidl_cb);
+      break;
+    case kGetHdrCapabilities:
+      client->ParseGetHdrCapabilities(input_params, _hidl_cb);
+      break;
+    case kSetCameraLaunchStatus:
+      client->ParseSetCameraLaunchStatus(input_params, _hidl_cb);
+      break;
+    case kDisplayBwTransactionPending:
+      client->ParseDisplayBwTransactionPending(_hidl_cb);
+      break;
+    case kSetDisplayAnimating:
+      client->ParseSetDisplayAnimating(input_params, _hidl_cb);
+      break;
+    case kControlIdlePowerCollapse:
+      client->ParseControlIdlePowerCollapse(input_params, _hidl_cb);
+      break;
+    case kGetWritebackCapabilities:
+      client->ParseGetWritebackCapabilities(_hidl_cb);
+      break;
+    case kSetDisplayDppsAdRoi:
+      client->ParseSetDisplayDppsAdRoi(input_params, _hidl_cb);
+      break;
+    case kUpdateVsyncSourceOnPowerModeOff:
+      client->ParseUpdateVsyncSourceOnPowerModeOff(_hidl_cb);
+      break;
+    case kUpdateVsyncSourceOnPowerModeDoze:
+      client->ParseUpdateVsyncSourceOnPowerModeDoze(_hidl_cb);
+      break;
+    case kSetPowerMode:
+      client->ParseSetPowerMode(input_params, _hidl_cb);
+      break;
+    case kIsPowerModeOverrideSupported:
+      client->ParseIsPowerModeOverrideSupported(input_params, _hidl_cb);
+      break;
+    case kIsHdrSupported:
+      client->ParseIsHdrSupported(input_params, _hidl_cb);
+      break;
+    case kIsWcgSupported:
+      client->ParseIsWcgSupported(input_params, _hidl_cb);
+      break;
+    case kSetLayerAsMask:
+      client->ParseSetLayerAsMask(input_params, _hidl_cb);
+      break;
+    case kGetDebugProperty:
+      client->ParseGetDebugProperty(input_params, _hidl_cb);
+      break;
+    case kGetActiveBuiltinDisplayAttributes:
+      client->ParseGetActiveBuiltinDisplayAttributes(_hidl_cb);
+      break;
+    case kSetPanelLuminanceAttributes:
+      client->ParseSetPanelLuminanceAttributes(input_params, _hidl_cb);
+      break;
+    case kIsBuiltinDisplay:
+      client->ParseIsBuiltinDisplay(input_params, _hidl_cb);
+      break;
+    case kSetCwbOutputBuffer:
+      client->ParseSetCwbOutputBuffer(client_handle, input_params, input_handles, _hidl_cb);
+      break;
+    case kGetSupportedDsiBitclks:
+      client->ParseGetSupportedDsiBitclks(input_params, _hidl_cb);
+      break;
+    case kGetDsiClk:
+      client->ParseGetDsiClk(input_params, _hidl_cb);
+      break;
+    case kSetDsiClk:
+      client->ParseSetDsiClk(input_params, _hidl_cb);
+      break;
+    case kSetQsyncMode:
+      client->ParseSetQsyncMode(input_params, _hidl_cb);
+      break;
+    case kIsSmartPanelConfig:
+      client->ParseIsSmartPanelConfig(input_params, _hidl_cb);
+      break;
+    case kIsAsyncVdsSupported:
+      client->ParseIsAsyncVdsSupported(_hidl_cb);
+      break;
+    case kCreateVirtualDisplay:
+      client->ParseCreateVirtualDisplay(input_params, _hidl_cb);
+      break;
+    case kIsRotatorSupportedFormat:
+      client->ParseIsRotatorSupportedFormat(input_params, _hidl_cb);
+      break;
+    case kControlQsyncCallback:
+      client->ParseControlQsyncCallback(client_handle, input_params, _hidl_cb);
+      break;
+    case kControlIdleStatusCallback:
+      client->ParseControlIdleStatusCallback(client_handle, input_params, _hidl_cb);
+      break;
+    case kSendTUIEvent:
+      client->ParseSendTUIEvent(input_params, _hidl_cb);
+      break;
+    case kDestroy:
+      ParseDestroy(client_handle, _hidl_cb);
+      break;
+    case kGetDisplayHwId:
+      client->ParseGetDisplayHwId(input_params, _hidl_cb);
+      break;
+    case kGetSupportedDisplayRefreshRates:
+      client->ParseGetSupportedDisplayRefreshRates(input_params, _hidl_cb);
+      break;
+    case kIsRCSupported:
+      client->ParseIsRCSupported(input_params, _hidl_cb);
+      break;
+    case kIsSupportedConfigSwitch:
+      client->ParseIsSupportedConfigSwitch(input_params, _hidl_cb);
+      break;
+    case kGetDisplayType:
+      client->ParseGetDisplayType(input_params, _hidl_cb);
+      break;
+    case kAllowIdleFallback:
+      client->ParseAllowIdleFallback(_hidl_cb);
+      break;
+    case kDummyOpcode:
+      _hidl_cb(-EINVAL, {}, {});
+      break;
+    default:
+      _hidl_cb(-EINVAL, {}, {});
+      break;
+  }
+  return Void();
+}
+
+}  // namespace DisplayConfig
diff --git a/services/config/src/device_impl.h b/services/config/src/device_impl.h
new file mode 100644
index 0000000..4c22a47
--- /dev/null
+++ b/services/config/src/device_impl.h
@@ -0,0 +1,153 @@
+/*
+* Copyright (c) 2021 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DEVICE_IMPL_H__
+#define __DEVICE_IMPL_H__
+
+#include <vendor/display/config/2.0/IDisplayConfig.h>
+#include <hidl/HidlSupport.h>
+#include <log/log.h>
+#include <config/device_interface.h>
+#include <map>
+#include <utility>
+#include <string>
+#include <vector>
+
+#include "opcode_types.h"
+
+namespace DisplayConfig {
+
+using vendor::display::config::V2_0::IDisplayConfig;
+using vendor::display::config::V2_0::IDisplayConfigCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+typedef hidl_vec<uint8_t> ByteStream;
+typedef hidl_vec<hidl_handle> HandleStream;
+
+class DeviceImpl : public IDisplayConfig, public android::hardware::hidl_death_recipient {
+ public:
+  static int CreateInstance(ClientContext *intf);
+
+ private:
+  class DeviceClientContext : public ConfigCallback {
+   public:
+    explicit DeviceClientContext(const sp<IDisplayConfigCallback> callback);
+
+    void SetDeviceConfigIntf(ConfigInterface *intf);
+    ConfigInterface* GetDeviceConfigIntf();
+    sp<IDisplayConfigCallback> GetDeviceConfigCallback();
+
+    virtual void NotifyCWBBufferDone(int32_t error, const native_handle_t *buffer);
+    virtual void NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate,
+                                   int32_t qsync_refresh_rate);
+    virtual void NotifyIdleStatus(bool is_idle);
+
+    void ParseIsDisplayConnected(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetDisplayStatus(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseConfigureDynRefreshRate(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetConfigCount(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetDisplayAttributes(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetPanelBrightness(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetPanelBrightness(perform_cb _hidl_cb);
+    void ParseMinHdcpEncryptionLevelChanged(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseRefreshScreen(perform_cb _hidl_cb);
+    void ParseControlPartialUpdate(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseToggleScreenUpdate(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetIdleTimeout(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetHdrCapabilities(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetCameraLaunchStatus(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseDisplayBwTransactionPending(perform_cb _hidl_cb);
+    void ParseSetDisplayAnimating(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseControlIdlePowerCollapse(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetWritebackCapabilities(perform_cb _hidl_cb);
+    void ParseSetDisplayDppsAdRoi(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseUpdateVsyncSourceOnPowerModeOff(perform_cb _hidl_cb);
+    void ParseUpdateVsyncSourceOnPowerModeDoze(perform_cb _hidl_cb);
+    void ParseSetPowerMode(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsPowerModeOverrideSupported(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsHdrSupported(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsWcgSupported(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetLayerAsMask(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetDebugProperty(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetActiveBuiltinDisplayAttributes(perform_cb _hidl_cb);
+    void ParseSetPanelLuminanceAttributes(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsBuiltinDisplay(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetCwbOutputBuffer(uint64_t clientHandle, const ByteStream &input_params,
+                                 const HandleStream &inputHandles, perform_cb _hidl_cb);
+    void ParseGetSupportedDsiBitclks(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseSetQsyncMode(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsSmartPanelConfig(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsAsyncVdsSupported(perform_cb _hidl_cb);
+    void ParseCreateVirtualDisplay(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsRotatorSupportedFormat(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseControlQsyncCallback(uint64_t client_handle, const ByteStream &input_params,
+                                   perform_cb _hidl_cb);
+    void ParseSendTUIEvent(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetDisplayHwId(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetSupportedDisplayRefreshRates(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseIsRCSupported(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseControlIdleStatusCallback(uint64_t client_handle, const ByteStream &input_params,
+                                        perform_cb _hidl_cb);
+    void ParseIsSupportedConfigSwitch(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseGetDisplayType(const ByteStream &input_params, perform_cb _hidl_cb);
+    void ParseAllowIdleFallback(perform_cb _hidl_cb);
+
+   private:
+    ConfigInterface *intf_ = nullptr;
+    const sp<IDisplayConfigCallback> callback_;
+  };
+
+  Return<void> registerClient(const hidl_string &client_name, const sp<IDisplayConfigCallback>& cb,
+                              registerClient_cb _hidl_cb) override;
+  Return<void> perform(uint64_t client_handle, uint32_t op_code, const ByteStream &input_params,
+                       const HandleStream &input_handles, perform_cb _hidl_cb) override;
+  void serviceDied(uint64_t client_handle,
+                   const android::wp<::android::hidl::base::V1_0::IBase>& callback);
+  void ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb);
+
+  ClientContext *intf_ = nullptr;
+  std::map<uint64_t, std::shared_ptr<DeviceClientContext>> display_config_map_;
+  uint64_t client_id_ = 0;
+  std::mutex death_service_mutex_;
+  static DeviceImpl *device_obj_;
+  static std::mutex device_lock_;
+};
+
+}  // namespace DisplayConfig
+
+#endif  // __DEVICE_IMPL_H__
diff --git a/services/config/src/device_interface.cpp b/services/config/src/device_interface.cpp
new file mode 100644
index 0000000..0c2d6b7
--- /dev/null
+++ b/services/config/src/device_interface.cpp
@@ -0,0 +1,42 @@
+/*
+* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "device_impl.h"
+
+namespace DisplayConfig {
+
+int DeviceInterface::RegisterDevice(ClientContext *intf) {
+  if (!intf) {
+    return -1;
+  }
+
+  return DeviceImpl::CreateInstance(intf);
+}
+
+}  // namespace DisplayConfig
diff --git a/services/config/src/opcode_types.h b/services/config/src/opcode_types.h
new file mode 100644
index 0000000..4813e47
--- /dev/null
+++ b/services/config/src/opcode_types.h
@@ -0,0 +1,93 @@
+/*
+* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __OPCODE_TYPES_H__
+#define __OPCODE_TYPES_H__
+
+namespace DisplayConfig {
+
+enum OpCode {
+  kIsDisplayConnected = 0,
+  kSetDisplayStatus = 1,
+  kConfigureDynRefreshRate = 2,
+  kGetConfigCount = 3,
+  kGetActiveConfig = 4,
+  kSetActiveConfig = 5,
+  kGetDisplayAttributes = 6,
+  kSetPanelBrightness = 7,
+  kGetPanelBrightness =  8,
+  kMinHdcpEncryptionLevelChanged = 9,
+  kRefreshScreen = 10,
+  kControlPartialUpdate = 11,
+  kToggleScreenUpdate = 12,
+  kSetIdleTimeout = 13,
+  kGetHdrCapabilities = 14,
+  kSetCameraLaunchStatus = 15,
+  kDisplayBwTransactionPending = 16,
+  kSetDisplayAnimating = 17,
+  kControlIdlePowerCollapse = 18,
+  kGetWritebackCapabilities = 19,
+  kSetDisplayDppsAdRoi = 20,
+  kUpdateVsyncSourceOnPowerModeOff = 21,
+  kUpdateVsyncSourceOnPowerModeDoze = 22,
+  kSetPowerMode = 23,
+  kIsPowerModeOverrideSupported = 24,
+  kIsHdrSupported = 25,
+  kIsWcgSupported = 26,
+  kSetLayerAsMask = 27,
+  kGetDebugProperty = 28,
+  kGetActiveBuiltinDisplayAttributes = 29,
+  kSetPanelLuminanceAttributes = 30,
+  kIsBuiltinDisplay = 31,
+  kSetCwbOutputBuffer = 32,
+  kGetSupportedDsiBitclks = 33,
+  kGetDsiClk = 34,
+  kSetDsiClk = 35,
+  kSetQsyncMode = 36,
+  kIsSmartPanelConfig = 37,
+  kIsAsyncVdsSupported = 38,
+  kCreateVirtualDisplay = 39,
+  kIsRotatorSupportedFormat = 40,
+  kControlQsyncCallback = 41,
+  kSendTUIEvent = 42,
+  kGetDisplayHwId = 43,
+  kGetSupportedDisplayRefreshRates = 44,
+  kIsRCSupported = 45,
+  kControlIdleStatusCallback = 46,
+  kIsSupportedConfigSwitch = 47,
+  kGetDisplayType = 48,
+  kAllowIdleFallback = 49,
+  kDummyOpcode = 50,
+
+  kDestroy = 0xFFFF, // Destroy sequence execution
+};
+
+}  // namespace DisplayConfig
+
+#endif  // __OPCODE_TYPES_H__