sdm: Implement composer hidl directly.

- Implement the hidl .hal interfaces directly instead of
  using the default shims.
- This is required since new additions to .hal will no
  longer be added to the legacy hwcomposer C header.
- Create new composer process in INIT_RC
- Implement CommandQueue Reader and Writer
    -Reader is used to parse the commands from
     i/p CMQ of client
    -Writer is used to write the outputs if any,
     for parsed commands then o/p CMQ passed to client.
- Add IMapper support to clone buffer handles for HWComposer
    -In IComposer, any buffer_handle_t is owned by the caller
     and we need to make a clone for HWComposer.
- Implement composer 2.1 and 2.2 API's as well.

CRs-Fixed: 2466333
Change-Id: Ife311443efdc067399d928221478d84677c17191
diff --git a/common.mk b/common.mk
index eca4769..5db3d16 100644
--- a/common.mk
+++ b/common.mk
@@ -48,7 +48,7 @@
 
 #Common C flags
 common_flags := -Wno-missing-field-initializers
-common_flags += -Wconversion -Wall -Werror -std=c++14
+common_flags += -Wall -Werror -std=c++14
 common_flags += -DUSE_GRALLOC1
 ifeq ($(TARGET_IS_HEADLESS), true)
     common_flags += -DTARGET_HEADLESS
diff --git a/composer/Android.mk b/composer/Android.mk
index 8050cfc..a13889a 100644
--- a/composer/Android.mk
+++ b/composer/Android.mk
@@ -1,12 +1,11 @@
 LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
 include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
 
 ifeq ($(use_hwc2),true)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
 LOCAL_VENDOR_MODULE           := true
-LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
 LOCAL_C_INCLUDES              += $(kernel_includes)
@@ -113,4 +112,101 @@
                                  hwc_buffer_allocator.cpp
 
 include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := vendor.qti.hardware.display.composer@1.0-service
+LOCAL_VENDOR_MODULE           := true
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes)
+LOCAL_HEADER_LIBRARIES        := display_headers
+
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -std=c++11 -fcolor-diagnostics \
+                                 -DLOG_TAG=\"SDM\" $(common_flags)
+LOCAL_CLANG                   := true
+
+LOCAL_SHARED_LIBRARIES        := libbinder libhardware libutils libcutils libsync \
+                                 libc++ liblog libhidlbase libhidltransport \
+                                 hwcomposer.$(TARGET_BOARD_PLATFORM) \
+                                 vendor.display.config@1.0 liblog libfmq \
+                                 vendor.qti.hardware.display.composer@1.0 \
+                                 android.hardware.graphics.composer@2.1 \
+                                 android.hardware.graphics.composer@2.2 \
+                                 android.hardware.graphics.composer@2.3 \
+                                 android.hardware.graphics.mapper@2.0 \
+                                 android.hardware.graphics.mapper@2.1 \
+                                 android.hardware.graphics.mapper@3.0 \
+                                 android.hardware.graphics.allocator@2.0 \
+                                 android.hardware.graphics.allocator@3.0
+
+$(info IDisplayConfig version: $(display_config_version))
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_1)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_2)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2 vendor.display.config@1.1
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_3)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_4)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_5)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_6)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_7)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_8)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.8
+endif
+ifeq ($(display_config_version), DISPLAY_CONFIG_1_9)
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.1
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.2
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.3
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.4
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.5
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.6
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.7
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.8
+LOCAL_SHARED_LIBRARIES        += vendor.display.config@1.9
+endif
+
+LOCAL_SRC_FILES               := QtiComposer.cpp QtiComposerClient.cpp service.cpp \
+                                 QtiComposerHandleImporter.cpp
+LOCAL_INIT_RC                 := vendor.qti.hardware.display.composer@1.0-service.rc
+include $(BUILD_EXECUTABLE)
 endif
diff --git a/composer/QtiComposer.cpp b/composer/QtiComposer.cpp
new file mode 100644
index 0000000..b4760bd
--- /dev/null
+++ b/composer/QtiComposer.cpp
@@ -0,0 +1,147 @@
+/*
+* Copyright (c) 2019, 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 <vector>
+#include "QtiComposer.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+namespace implementation {
+
+QtiComposer::QtiComposer() {
+  hwc_session_ = HWCSession::GetInstance();
+}
+
+QtiComposer::~QtiComposer() {
+  hwc_session_->Deinit();
+}
+
+// Methods from ::android::hardware::graphics::composer::V2_1::IComposer follow.
+Return<void> QtiComposer::getCapabilities(getCapabilities_cb _hidl_cb) {
+  const std::array<IComposer::Capability, 3> all_caps = {{
+    IComposer::Capability::SIDEBAND_STREAM,
+    IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM,
+    IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE,
+  }};
+
+  uint32_t count = 0;
+  hwc_session_->GetCapabilities(&count, nullptr);
+
+  std::vector<int32_t> composer_caps(count);
+  hwc_session_->GetCapabilities(&count, composer_caps.data());
+  composer_caps.resize(count);
+
+  std::unordered_set<hwc2_capability_t> Capabilities;
+  Capabilities.reserve(count);
+  for (auto cap : composer_caps) {
+    Capabilities.insert(static_cast<hwc2_capability_t>(cap));
+  }
+
+  std::vector<IComposer::Capability> caps;
+  for (auto cap : all_caps) {
+    if (Capabilities.count(static_cast<hwc2_capability_t>(cap)) > 0) {
+     caps.push_back(cap);
+    }
+  }
+
+  hidl_vec<IComposer::Capability> caps_reply;
+  caps_reply.setToExternal(caps.data(), caps.size());
+
+  _hidl_cb(caps_reply);
+  return Void();
+}
+
+Return<void> QtiComposer::dumpDebugInfo(dumpDebugInfo_cb _hidl_cb) {
+  uint32_t len;
+  hwc_session_->Dump(&len, nullptr);
+
+  std::vector<char> buf(len + 1);
+  hwc_session_->Dump(&len, buf.data());
+
+  buf.resize(len + 1);
+  buf[len] = '\0';
+  hidl_string buf_reply;
+  buf_reply.setToExternal(buf.data(), len);
+
+  _hidl_cb(buf_reply);
+  return Void();
+}
+
+Return<void> QtiComposer::createClient(createClient_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t createClient_2_3
+  sp<IQtiComposerClient> composer_client = new QtiComposerClient();
+  if (!composer_client) {
+    _hidl_cb(Error::NO_RESOURCES, nullptr);
+    return Void();
+  }
+
+  _hidl_cb(Error::NONE, composer_client);
+  return Void();
+}
+
+
+// Methods from ::android::hardware::graphics::composer::V2_3::IComposer follow.
+Return<void> QtiComposer::createClient_2_3(createClient_2_3_cb _hidl_cb) {
+  sp<IQtiComposerClient> composer_client = new QtiComposerClient();
+  if (!composer_client) {
+    _hidl_cb(Error::NO_RESOURCES, nullptr);
+    return Void();
+  }
+
+  _hidl_cb(Error::NONE, composer_client);
+  return Void();
+}
+
+QtiComposer *QtiComposer::initialize() {
+  auto error = HWCSession::GetInstance()->Init();
+  if (error) {
+    ALOGE("failed to get hwcomposer instance");
+    return nullptr;
+  }
+
+  return new QtiComposer();
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+IQtiComposer* HIDL_FETCH_IQtiComposer(const char* /* name */) {
+  return new QtiComposer();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
diff --git a/composer/QtiComposer.h b/composer/QtiComposer.h
new file mode 100644
index 0000000..1452a06
--- /dev/null
+++ b/composer/QtiComposer.h
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2019, 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 __QTICOMPOSER_H__
+#define __QTICOMPOSER_H__
+
+#include <vendor/qti/hardware/display/composer/1.0/IQtiComposer.h>
+#include <log/log.h>
+#include <unordered_set>
+#include <QtiComposerClient.h>
+
+// TODO(user): recheck on this header inclusion
+#include <hardware/hwcomposer2.h>
+
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+namespace implementation {
+
+using ::vendor::qti::hardware::display::composer::V1_0::IQtiComposer;
+
+class QtiComposer : public IQtiComposer {
+ public:
+  QtiComposer();
+  virtual ~QtiComposer();
+  // Methods from ::android::hardware::graphics::composer::V2_1::IComposer follow.
+  Return<void> getCapabilities(getCapabilities_cb _hidl_cb) override;
+  Return<void> dumpDebugInfo(dumpDebugInfo_cb _hidl_cb) override;
+  Return<void> createClient(createClient_cb _hidl_cb) override;
+
+  // Methods from ::android::hardware::graphics::composer::V2_3::IComposer follow.
+  Return<void> createClient_2_3(createClient_2_3_cb _hidl_cb) override;
+
+  // Methods from ::android::hidl::base::V1_0::IBase follow.
+
+  static QtiComposer *initialize();
+
+ private:
+    HWCSession *hwc_session_ = nullptr;
+};
+
+extern "C" IQtiComposer* HIDL_FETCH_IQtiComposer(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
+#endif  // __QTICOMPOSER_H__
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
new file mode 100644
index 0000000..2a858b4
--- /dev/null
+++ b/composer/QtiComposerClient.cpp
@@ -0,0 +1,1841 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include "QtiComposerClient.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+namespace implementation {
+
+ComposerHandleImporter mHandleImporter;
+
+BufferCacheEntry::BufferCacheEntry() : mHandle(nullptr) {}
+
+BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other) {
+  mHandle = other.mHandle;
+  other.mHandle = nullptr;
+}
+
+BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle) {
+  clear();
+  mHandle = handle;
+  return *this;
+}
+
+BufferCacheEntry::~BufferCacheEntry() {
+  clear();
+}
+
+void BufferCacheEntry::clear() {
+  if (mHandle) {
+    mHandleImporter.freeBuffer(mHandle);
+  }
+}
+
+QtiComposerClient::QtiComposerClient() : mWriter(kWriterInitialSize), mReader(*this) {
+  hwc_session_ = HWCSession::GetInstance();
+  mHandleImporter.initialize();
+}
+
+QtiComposerClient::~QtiComposerClient() {
+  // We want to call hwc2_close here (and move hwc2_open to the
+  // constructor), with the assumption that hwc2_close would
+  //
+  //  - clean up all resources owned by the client
+  //  - make sure all displays are blank (since there is no layer)
+  //
+  // But since SF used to crash at this point, different hwcomposer2
+  // implementations behave differently on hwc2_close.  Our only portable
+  // choice really is to abort().  But that is not an option anymore
+  // because we might also have VTS or VR as clients that can come and go.
+  //
+  // Below we manually clean all resources (layers and virtual
+  // displays), and perform a presentDisplay afterwards.
+  ALOGW("destroying composer client");
+
+  enableCallback(false);
+
+  // no need to grab the mutex as any in-flight hwbinder call would have
+  // kept the client alive
+  for (const auto& dpy : mDisplayData) {
+    ALOGW("destroying client resources for display %" PRIu64, dpy.first);
+
+    for (const auto& ly : dpy.second.Layers) {
+      hwc_session_->DestroyLayer(dpy.first, ly.first);
+    }
+
+    if (dpy.second.IsVirtual) {
+      destroyVirtualDisplay(dpy.first);
+    } else {
+      ALOGW("performing a final presentDisplay");
+
+      std::vector<Layer> changedLayers;
+      std::vector<IComposerClient::Composition> compositionTypes;
+      uint32_t displayRequestMask = 0;
+      std::vector<Layer> requestedLayers;
+      std::vector<uint32_t> requestMasks;
+      mReader.validateDisplay(dpy.first, changedLayers, compositionTypes, displayRequestMask,
+                              requestedLayers, requestMasks);
+
+      hwc_session_->AcceptDisplayChanges(dpy.first);
+
+      int32_t presentFence = -1;
+      std::vector<Layer> releasedLayers;
+      std::vector<int32_t> releaseFences;
+      mReader.presentDisplay(dpy.first, presentFence, releasedLayers, releaseFences);
+
+      if (presentFence >= 0) {
+        close(presentFence);
+      }
+      for (auto fence : releaseFences) {
+        if (fence >= 0) {
+          close(fence);
+        }
+      }
+    }
+  }
+
+  mDisplayData.clear();
+
+  mHandleImporter.cleanup();
+
+  ALOGW("removed composer client");
+}
+
+void QtiComposerClient::onHotplug(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                                    int32_t connected) {
+  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
+  auto connect = static_cast<composer_V2_1::IComposerCallback::Connection>(connected);
+  {
+    std::lock_guard<std::mutex> lock(client->mDisplayDataMutex);
+    if (connect == composer_V2_1::IComposerCallback::Connection::CONNECTED) {
+      client->mDisplayData.emplace(display, DisplayData(false));
+    } else if (connect == composer_V2_1::IComposerCallback::Connection::DISCONNECTED) {
+      client->mDisplayData.erase(display);
+    }
+  }
+
+  auto ret = client->mCallback->onHotplug(display, connect);
+  ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+}
+
+void QtiComposerClient::onRefresh(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
+  auto ret = client->mCallback->onRefresh(display);
+  ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+}
+
+void QtiComposerClient::onVsync(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                                  int64_t timestamp) {
+  auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
+  auto ret = client->mCallback->onVsync(display, timestamp);
+  ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+}
+
+// convert fenceFd to or from hidl_handle
+Error QtiComposerClient::getFenceFd(const hidl_handle& fenceHandle,
+                                    android::base::unique_fd* outFenceFd) {
+  auto handle = fenceHandle.getNativeHandle();
+  if (handle && handle->numFds > 1) {
+    ALOGE("invalid fence handle with %d fds", handle->numFds);
+    return Error::BAD_PARAMETER;
+  }
+
+  int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+  if (fenceFd >= 0) {
+    fenceFd = dup(fenceFd);
+    if (fenceFd < 0) {
+      return Error::NO_RESOURCES;
+    }
+  }
+
+  outFenceFd->reset(fenceFd);
+
+  return Error::NONE;
+}
+
+hidl_handle QtiComposerClient::getFenceHandle(const android::base::unique_fd& fenceFd,
+                                              char* handleStorage) {
+  native_handle_t* handle = nullptr;
+  if (fenceFd >= 0) {
+    handle = native_handle_init(handleStorage, 1, 0);
+    handle->data[0] = fenceFd;
+  }
+
+  return hidl_handle(handle);
+}
+
+Error QtiComposerClient::getDisplayReadbackBuffer(Display display,
+                                                  const native_handle_t* rawHandle,
+                                                  const native_handle_t** outHandle) {
+  // TODO(user): revisit for caching and freeBuffer in success case.
+  if (!mHandleImporter.importBuffer(rawHandle)) {
+    ALOGE("%s: importBuffer failed: ", __FUNCTION__);
+    return Error::NO_RESOURCES;
+  }
+
+  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+  auto iter = mDisplayData.find(display);
+  if (iter == mDisplayData.end()) {
+    mHandleImporter.freeBuffer(rawHandle);
+    return Error::BAD_DISPLAY;
+  }
+
+  *outHandle = rawHandle;
+  return Error::NONE;
+}
+
+void QtiComposerClient::getCapabilities() {
+  uint32_t count = 0;
+  hwc_session_->GetCapabilities(&count, nullptr);
+
+  std::vector<int32_t> composer_caps(count);
+  hwc_session_->GetCapabilities(&count, composer_caps.data());
+  composer_caps.resize(count);
+
+  mCapabilities.reserve(count);
+  for (auto cap : composer_caps) {
+    mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
+  }
+}
+
+void QtiComposerClient::enableCallback(bool enable) {
+  if (enable) {
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_HOTPLUG, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(onHotplug));
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_REFRESH, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(onRefresh));
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC, this,
+                                   reinterpret_cast<hwc2_function_pointer_t>(onVsync));
+  } else {
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_HOTPLUG, this, nullptr);
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_REFRESH, this, nullptr);
+    hwc_session_->RegisterCallback(HWC2_CALLBACK_VSYNC, this, nullptr);
+  }
+}
+
+// Methods from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+Return<void> QtiComposerClient::registerCallback(
+                                            const sp<composer_V2_1::IComposerCallback>& callback) {
+  mCallback = callback;
+  enableCallback(callback != nullptr);
+  return Void();
+}
+
+Return<uint32_t> QtiComposerClient::getMaxVirtualDisplayCount() {
+  return hwc_session_->GetMaxVirtualDisplayCount();
+}
+
+Return<void> QtiComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
+                                                     common_V1_0::PixelFormat formatHint,
+                                                     uint32_t outputBufferSlotCount,
+                                                     createVirtualDisplay_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t createVirtualDisplay_2_2
+  int32_t format = static_cast<int32_t>(formatHint);
+  uint64_t display;
+  auto error = hwc_session_->CreateVirtualDisplay(width, height, &format, &display);
+
+  if (static_cast<Error>(error) == Error::NONE) {
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+    auto dpy = mDisplayData.emplace(static_cast<Display>(display), DisplayData(true)).first;
+    dpy->second.OutputBuffers.resize(outputBufferSlotCount);
+  }
+
+  _hidl_cb(static_cast<Error>(error), display, static_cast<common_V1_0::PixelFormat>(format));
+  return Void();
+}
+
+Return<composer_V2_1::Error> QtiComposerClient::destroyVirtualDisplay(uint64_t display) {
+  auto error = hwc_session_->DestroyVirtualDisplay(display);
+  if (static_cast<Error>(error) == Error::NONE) {
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+    mDisplayData.erase(display);
+  }
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::createLayer(uint64_t display, uint32_t bufferSlotCount,
+                                            createLayer_cb _hidl_cb) {
+  composer_V2_1::Layer layer = 0;
+  auto error = hwc_session_->CreateLayer(display, &layer);
+  Error err = static_cast<Error>(error);
+  if (err == Error::NONE) {
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+    auto dpy = mDisplayData.find(display);
+    // The display entry may have already been removed by onHotplug.
+    if (dpy != mDisplayData.end()) {
+      auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
+      ly->second.Buffers.resize(bufferSlotCount);
+    } else {
+      err = Error::BAD_DISPLAY;
+      // Note: We do not destroy the layer on this error as the hotplug
+      // disconnect invalidates the display id. The implementation should
+      // ensure all layers for the display are destroyed.
+    }
+  }
+
+  _hidl_cb(err, layer);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::destroyLayer(uint64_t display, uint64_t layer) {
+  auto error = hwc_session_->DestroyLayer(display, layer);
+  Error err = static_cast<Error>(error);
+  if (err == Error::NONE) {
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+    auto dpy = mDisplayData.find(display);
+    // The display entry may have already been removed by onHotplug.
+    if (dpy != mDisplayData.end()) {
+      dpy->second.Layers.erase(layer);
+    }
+  }
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getActiveConfig(uint64_t display, getActiveConfig_cb _hidl_cb) {
+  uint32_t config = 0;
+  auto error = hwc_session_->GetActiveConfig(display, &config);
+
+  _hidl_cb(static_cast<Error>(error), config);
+
+  return Void();
+}
+
+Return<Error> QtiComposerClient::getClientTargetSupport(uint64_t display, uint32_t width,
+                                                        uint32_t height,
+                                                        common_V1_0::PixelFormat format,
+                                                        common_V1_0::Dataspace dataspace) {
+  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
+                                                    static_cast<int32_t>(format),
+                                                    static_cast<int32_t>(dataspace));
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getColorModes(uint64_t display, getColorModes_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getColorModes_2_3
+  hidl_vec<common_V1_0::ColorMode> modes;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), modes);
+    return Void();
+  }
+
+  modes.resize(count);
+  error = hwc_session_->GetColorModes(display, &count,
+              reinterpret_cast<std::underlying_type<common_V1_0::ColorMode>::type*>(modes.data()));
+
+  _hidl_cb(static_cast<Error>(error), modes);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDisplayAttribute(uint64_t display, uint32_t config,
+                                               composer_V2_1::IComposerClient::Attribute attribute,
+                                               getDisplayAttribute_cb _hidl_cb) {
+  int32_t value = 0;
+  auto error = hwc_session_->GetDisplayAttribute(display, config, static_cast<int32_t>(attribute),
+                                                 &value);
+
+  _hidl_cb(static_cast<Error>(error), value);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDisplayConfigs(uint64_t display,
+                                                  getDisplayConfigs_cb _hidl_cb) {
+  hidl_vec<uint32_t> configs;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetDisplayConfigs(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), configs);
+    return Void();
+  }
+
+  configs.resize(count);
+  error = hwc_session_->GetDisplayConfigs(display, &count, configs.data());
+
+  _hidl_cb(static_cast<Error>(error), configs);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDisplayName(uint64_t display, getDisplayName_cb _hidl_cb) {
+  uint32_t count = 0;
+  hidl_string name_reply;
+  std::vector<char> name;
+
+  auto error = hwc_session_->GetDisplayName(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), name_reply);
+    return Void();
+  }
+
+  name.resize(count + 1);
+  error = hwc_session_->GetDisplayName(display, &count, name.data());
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), name_reply);
+    return Void();
+  }
+
+  name.resize(count + 1);
+  name[count] = '\0';
+  name_reply.setToExternal(name.data(), count);
+
+  _hidl_cb(static_cast<Error>(error), name_reply);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDisplayType(uint64_t display, getDisplayType_cb _hidl_cb) {
+  int32_t hwc_type;
+  auto error = hwc_session_->GetDisplayType(display, &hwc_type);
+
+  _hidl_cb(static_cast<Error>(error), static_cast<IComposerClient::DisplayType>(hwc_type));
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDozeSupport(uint64_t display, getDozeSupport_cb _hidl_cb) {
+  int32_t hwc_support = 0;
+  auto error = hwc_session_->GetDozeSupport(display, &hwc_support);
+
+  _hidl_cb(static_cast<Error>(error), hwc_support);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getHdrCapabilities(uint64_t display,
+                                                   getHdrCapabilities_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getHdrCapabilities_2_3
+  uint32_t count = 0;
+  hidl_vec<common_V1_0::Hdr> types;
+  float max_lumi = 0.0f;
+  float max_avg_lumi = 0.0f;
+  float min_lumi = 0.0f;
+
+  auto error = hwc_session_->GetHdrCapabilities(display, &count, nullptr, &max_lumi,
+                                                &max_avg_lumi, &min_lumi);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
+    return Void();
+  }
+
+  types.resize(count);
+  error = hwc_session_->GetHdrCapabilities(display, &count,
+           reinterpret_cast<std::underlying_type<common_V1_2::Hdr>::type*>(types.data()),
+           &max_lumi, &max_avg_lumi, &min_lumi);
+
+  _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setClientTargetSlotCount(uint64_t display,
+                                                          uint32_t clientTargetSlotCount) {
+  std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+  auto dpy = mDisplayData.find(display);
+  if (dpy == mDisplayData.end()) {
+    return Error::BAD_DISPLAY;
+  }
+  dpy->second.ClientTargets.resize(clientTargetSlotCount);
+
+  return Error::NONE;
+}
+
+Return<Error> QtiComposerClient::setActiveConfig(uint64_t display, uint32_t config) {
+  auto error = hwc_session_->SetActiveConfig(display, config);
+
+  return static_cast<Error>(error);
+}
+
+Return<Error> QtiComposerClient::setColorMode(uint64_t display, common_V1_0::ColorMode mode) {
+  auto error = hwc_session_->SetColorMode(display, static_cast<int32_t>(mode));
+
+  return static_cast<Error>(error);
+}
+
+Return<Error> QtiComposerClient::setPowerMode(uint64_t display,
+                                              composer_V2_1::IComposerClient::PowerMode mode) {
+  // TODO(user): Implement combinedly w.r.t setPowerMode_2_2
+  auto error = hwc_session_->SetPowerMode(display, static_cast<int32_t>(mode));
+
+  return static_cast<Error>(error);
+}
+
+Return<Error> QtiComposerClient::setVsyncEnabled(uint64_t display,
+                                                 composer_V2_1::IComposerClient::Vsync enabled) {
+  auto error = hwc_session_->SetVsyncEnabled(display, static_cast<int32_t>(enabled));
+
+  return static_cast<Error>(error);
+}
+
+Return<Error> QtiComposerClient::setInputCommandQueue(
+                                                    const MQDescriptorSync<uint32_t>& descriptor) {
+  std::lock_guard<std::mutex> lock(mCommandMutex);
+  return mReader.setMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
+}
+
+Return<void> QtiComposerClient::getOutputCommandQueue(getOutputCommandQueue_cb _hidl_cb) {
+  // no locking as we require this function to be called inside
+  // executeCommands_cb
+
+  auto outDescriptor = mWriter.getMQDescriptor();
+  if (outDescriptor) {
+    _hidl_cb(Error::NONE, *outDescriptor);
+  } else {
+    _hidl_cb(Error::NO_RESOURCES, MQDescriptorSync<uint32_t>());
+  }
+
+  return Void();
+}
+
+Return<void> QtiComposerClient::executeCommands(uint32_t inLength,
+                                                const hidl_vec<hidl_handle>& inHandles,
+                                                executeCommands_cb _hidl_cb) {
+  std::lock_guard<std::mutex> lock(mCommandMutex);
+
+  bool outChanged = false;
+  uint32_t outLength = 0;
+  hidl_vec<hidl_handle> outHandles;
+
+  if (!mReader.readQueue(inLength, inHandles)) {
+    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
+    return Void();
+  }
+
+  Error err = mReader.parse();
+  if (err == Error::NONE &&
+      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
+    err = Error::NO_RESOURCES;
+  }
+
+  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);
+
+  mReader.reset();
+  mWriter.reset();
+
+  return Void();
+}
+
+
+// Methods from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+Return<void> QtiComposerClient::getPerFrameMetadataKeys(uint64_t display,
+                                                        getPerFrameMetadataKeys_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getPerFrameMetadataKeys_2_3
+  std::vector<PerFrameMetadataKey_V2> keys;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetPerFrameMetadataKeys(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), keys);
+    return Void();
+  }
+
+  keys.resize(count);
+  error = hwc_session_->GetPerFrameMetadataKeys(display, &count,
+               reinterpret_cast<std::underlying_type<PerFrameMetadataKey_V2>::type*>(keys.data()));
+
+  _hidl_cb(static_cast<Error>(error), keys);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getReadbackBufferAttributes(uint64_t display,
+                                                         getReadbackBufferAttributes_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getReadbackBufferAttributes_2_3
+  int32_t format = 0;
+  int32_t dataspace = 0;
+
+  auto error = hwc_session_->GetReadbackBufferAttributes(display, &format, &dataspace);
+
+  if (error != HWC2_ERROR_NONE) {
+    format = 0;
+    dataspace = 0;
+  }
+
+  _hidl_cb(static_cast<Error>(error), static_cast<common_V1_1::PixelFormat>(format),
+           static_cast<common_V1_1::Dataspace>(dataspace));
+  return Void();
+}
+
+Return<void> QtiComposerClient::getReadbackBufferFence(uint64_t display,
+                                                       getReadbackBufferFence_cb _hidl_cb) {
+  int32_t Fd = -1;
+  auto error = hwc_session_->GetReadbackBufferFence(display, &Fd);
+  if (static_cast<Error>(error) != Error::NONE) {
+    _hidl_cb(static_cast<Error>(error), nullptr);
+    return Void();
+  }
+
+  android::base::unique_fd fenceFd;
+  fenceFd.reset(Fd);
+  NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+
+  _hidl_cb(static_cast<Error>(error), getFenceHandle(fenceFd, fenceStorage));
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setReadbackBuffer(uint64_t display, const hidl_handle& buffer,
+                                                   const hidl_handle& releaseFence) {
+  android::base::unique_fd fenceFd;
+  Error error = getFenceFd(releaseFence, &fenceFd);
+  if (error != Error::NONE) {
+    return error;
+  }
+
+  const native_handle_t* readbackBuffer;
+  getDisplayReadbackBuffer(display, buffer.getNativeHandle(), &readbackBuffer);
+  if (error != Error::NONE) {
+    return error;
+  }
+
+  auto err = hwc_session_->SetReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
+  return static_cast<Error>(err);
+}
+
+Return<void> QtiComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+                                                         common_V1_1::PixelFormat formatHint,
+                                                         uint32_t outputBufferSlotCount,
+                                                         createVirtualDisplay_2_2_cb _hidl_cb) {
+  int32_t format = static_cast<int32_t>(formatHint);
+  uint64_t display;
+  auto error = hwc_session_->CreateVirtualDisplay(width, height, &format, &display);
+
+  if (static_cast<Error>(error) == Error::NONE) {
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+    auto dpy = mDisplayData.emplace(static_cast<Display>(display), DisplayData(true)).first;
+    dpy->second.OutputBuffers.resize(outputBufferSlotCount);
+  }
+
+  _hidl_cb(static_cast<Error>(error), display, static_cast<common_V1_1::PixelFormat>(format));
+  return Void();
+}
+
+Return<Error> QtiComposerClient::getClientTargetSupport_2_2(uint64_t display, uint32_t width,
+                                                            uint32_t height,
+                                                            common_V1_1::PixelFormat format,
+                                                            common_V1_1::Dataspace dataspace) {
+  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
+                                                    static_cast<int32_t>(format),
+                                                    static_cast<int32_t>(dataspace));
+
+  return static_cast<Error>(error);
+}
+
+Return<Error> QtiComposerClient::setPowerMode_2_2(uint64_t display,
+                                                  composer_V2_2::IComposerClient::PowerMode mode) {
+  if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
+    return Error::UNSUPPORTED;
+  }
+  auto error = hwc_session_->SetPowerMode(display, static_cast<int32_t>(mode));
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getColorModes_2_2(uint64_t display,
+                                                  getColorModes_2_2_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getColorModes_2_3
+  hidl_vec<common_V1_1::ColorMode> modes;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), modes);
+    return Void();
+  }
+
+  modes.resize(count);
+  error = hwc_session_->GetColorModes(display, &count,
+              reinterpret_cast<std::underlying_type<common_V1_1::ColorMode>::type*>(modes.data()));
+
+  _hidl_cb(static_cast<Error>(error), modes);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getRenderIntents(uint64_t display, common_V1_1::ColorMode mode,
+                                                 getRenderIntents_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t getRenderIntents_2_3
+  uint32_t count = 0;
+  std::vector<RenderIntent> intents;
+
+  auto error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), intents);
+    return Void();
+  }
+
+  intents.resize(count);
+  error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count,
+  reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));
+
+  _hidl_cb(static_cast<Error>(error), intents);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setColorMode_2_2(uint64_t display, common_V1_1::ColorMode mode,
+                                                  common_V1_1::RenderIntent intent) {
+  auto error = hwc_session_->SetColorModeWithRenderIntent(display, static_cast<int32_t>(mode),
+                                                          static_cast<int32_t>(intent));
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getDataspaceSaturationMatrix(common_V1_1::Dataspace dataspace,
+                                                        getDataspaceSaturationMatrix_cb _hidl_cb) {
+  if (dataspace != common_V1_1::Dataspace::SRGB_LINEAR) {
+    _hidl_cb(Error::BAD_PARAMETER, std::array<float, 16>{0.0f}.data());
+    return Void();
+  }
+
+  std::array<float, 16> matrix;
+  int32_t error = HWC2_ERROR_UNSUPPORTED;
+  error = hwc_session_->GetDataspaceSaturationMatrix(static_cast<int32_t>(dataspace),
+                                                     matrix.data());
+  if (error != HWC2_ERROR_NONE) {
+    matrix = {
+      1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+      0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+    };
+  }
+  _hidl_cb(Error::NONE, matrix.data());
+  return Void();
+}
+
+Return<void> QtiComposerClient::executeCommands_2_2(uint32_t inLength,
+                                                    const hidl_vec<hidl_handle>& inHandles,
+                                                    executeCommands_2_2_cb _hidl_cb) {
+  std::lock_guard<std::mutex> lock(mCommandMutex);
+
+  bool outChanged = false;
+  uint32_t outLength = 0;
+  hidl_vec<hidl_handle> outHandles;
+
+  if (!mReader.readQueue(inLength, inHandles)) {
+    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
+    return Void();
+  }
+
+  Error err = mReader.parse();
+  if (err == Error::NONE &&
+      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
+      err = Error::NO_RESOURCES;
+  }
+
+  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);
+
+  mReader.reset();
+  mWriter.reset();
+
+  return Void();
+}
+
+
+// Methods from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+Return<void> QtiComposerClient::getDisplayIdentificationData(uint64_t display,
+                                                        getDisplayIdentificationData_cb _hidl_cb) {
+  uint8_t port = 0;
+  uint32_t size = 0;
+  std::vector<uint8_t> data(size);
+
+  auto error = hwc_session_->GetDisplayIdentificationData(display, &port, &size, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), port, data);
+    return Void();
+  }
+
+  data.resize(size);
+  error = hwc_session_->GetDisplayIdentificationData(display, &port, &size, data.data());
+
+  _hidl_cb(static_cast<Error>(error), port, data);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getReadbackBufferAttributes_2_3(uint64_t display,
+                                                     getReadbackBufferAttributes_2_3_cb _hidl_cb) {
+  int32_t format = 0;
+  int32_t dataspace = 0;
+
+  auto error = hwc_session_->GetReadbackBufferAttributes(display, &format, &dataspace);
+
+  if (error != HWC2_ERROR_NONE) {
+    format = 0;
+    dataspace = 0;
+  }
+
+  _hidl_cb(static_cast<Error>(error), static_cast<common_V1_2::PixelFormat>(format),
+           static_cast<common_V1_2::Dataspace>(dataspace));
+  return Void();
+}
+
+Return<Error> QtiComposerClient::getClientTargetSupport_2_3(uint64_t display, uint32_t width,
+                                                            uint32_t height,
+                                                            common_V1_2::PixelFormat format,
+                                                            common_V1_2::Dataspace dataspace) {
+  auto error = hwc_session_->GetClientTargetSupport(display, width, height,
+                                                    static_cast<int32_t>(format),
+                                                    static_cast<int32_t>(dataspace));
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getDisplayedContentSamplingAttributes(uint64_t display,
+                                               getDisplayedContentSamplingAttributes_cb _hidl_cb) {
+  // getDisplayedContentSamplingAttributes is not supported
+  int constexpr invalid = -1;
+  auto error = Error::UNSUPPORTED;
+  common_V1_2::PixelFormat format = static_cast<common_V1_2::PixelFormat>(invalid);
+  common_V1_2::Dataspace dataspace = static_cast<common_V1_2::Dataspace>(invalid);
+  hidl_bitfield<IComposerClient::FormatColorComponent> componentMask =
+    static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(invalid);
+
+  _hidl_cb(error, format, dataspace, componentMask);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setDisplayedContentSamplingEnabled(uint64_t display,
+                                   composer_V2_3::IComposerClient::DisplayedContentSampling enable,
+                                   hidl_bitfield<FormatColorComponent> componentMask,
+                                   uint64_t maxFrames) {
+  // setDisplayedContentSamplingEnabled is not supported
+  return Error::UNSUPPORTED;
+}
+
+Return<void> QtiComposerClient::getDisplayedContentSample(uint64_t display, uint64_t maxFrames,
+                                                          uint64_t timestamp,
+                                                          getDisplayedContentSample_cb _hidl_cb) {
+  // getDisplayedContentSample is not supported
+  auto error = Error::UNSUPPORTED;
+  uint64_t frameCount = 0;
+  hidl_vec<uint64_t> sampleComponent0 = 0;
+  hidl_vec<uint64_t> sampleComponent1 = 0;
+  hidl_vec<uint64_t> sampleComponent2 = 0;
+  hidl_vec<uint64_t> sampleComponent3 = 0;
+
+  _hidl_cb(error, frameCount, sampleComponent0, sampleComponent1, sampleComponent2,
+           sampleComponent3);
+  return Void();
+}
+
+Return<void> QtiComposerClient::executeCommands_2_3(uint32_t inLength,
+                                                    const hidl_vec<hidl_handle>& inHandles,
+                                                    executeCommands_2_3_cb _hidl_cb) {
+  // TODO(user): Implement combinedly w.r.t executeCommands_2_2
+  std::lock_guard<std::mutex> lock(mCommandMutex);
+
+  bool outChanged = false;
+  uint32_t outLength = 0;
+  hidl_vec<hidl_handle> outHandles;
+
+  if (!mReader.readQueue(inLength, inHandles)) {
+    _hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
+    return Void();
+  }
+
+  Error err = mReader.parse();
+  if (err == Error::NONE &&
+      !mWriter.writeQueue(outChanged, outLength, outHandles)) {
+      err = Error::NO_RESOURCES;
+  }
+
+  _hidl_cb(Error::NONE, outChanged, outLength, outHandles);
+
+  mReader.reset();
+  mWriter.reset();
+
+  return Void();
+}
+
+Return<void> QtiComposerClient::getRenderIntents_2_3(uint64_t display, common_V1_2::ColorMode mode,
+                                                     getRenderIntents_2_3_cb _hidl_cb) {
+  uint32_t count = 0;
+  std::vector<RenderIntent> intents;
+
+  auto error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), intents);
+    return Void();
+  }
+
+  intents.resize(count);
+  error = hwc_session_->GetRenderIntents(display, int32_t(mode), &count,
+  reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));
+
+  _hidl_cb(static_cast<Error>(error), intents);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getColorModes_2_3(uint64_t display,
+                                                  getColorModes_2_3_cb _hidl_cb) {
+  hidl_vec<common_V1_2::ColorMode> modes;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetColorModes(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), modes);
+    return Void();
+  }
+
+  modes.resize(count);
+  error = hwc_session_->GetColorModes(display, &count,
+              reinterpret_cast<std::underlying_type<common_V1_2::ColorMode>::type*>(modes.data()));
+
+  _hidl_cb(static_cast<Error>(error), modes);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setColorMode_2_3(uint64_t display, common_V1_2::ColorMode mode,
+                                                  common_V1_1::RenderIntent intent) {
+  auto error = hwc_session_->SetColorModeWithRenderIntent(display, static_cast<int32_t>(mode),
+                                                          static_cast<int32_t>(intent));
+
+  return static_cast<Error>(error);
+}
+
+Return<void> QtiComposerClient::getDisplayCapabilities(uint64_t display,
+                                                       getDisplayCapabilities_cb _hidl_cb) {
+  hidl_vec<IComposerClient::DisplayCapability> capabilities;
+  uint32_t count = 0;
+  auto error = hwc_session_->GetDisplayCapabilities(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), capabilities);
+    return Void();
+  }
+
+  capabilities.resize(count);
+  error = hwc_session_->GetDisplayCapabilities(display, &count,
+                 reinterpret_cast<std::underlying_type<IComposerClient::DisplayCapability>::type*>(
+                 capabilities.data()));
+  if (error != HWC2_ERROR_NONE) {
+    capabilities = hidl_vec<IComposerClient::DisplayCapability>();
+    _hidl_cb(static_cast<Error>(error), capabilities);
+    return Void();
+  }
+
+  _hidl_cb(static_cast<Error>(error), capabilities);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getPerFrameMetadataKeys_2_3(uint64_t display,
+                                                         getPerFrameMetadataKeys_2_3_cb _hidl_cb) {
+  std::vector<PerFrameMetadataKey> keys;
+  uint32_t count = 0;
+
+  auto error = hwc_session_->GetPerFrameMetadataKeys(display, &count, nullptr);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), keys);
+    return Void();
+  }
+
+  keys.resize(count);
+  error = hwc_session_->GetPerFrameMetadataKeys(display, &count,
+                  reinterpret_cast<std::underlying_type<PerFrameMetadataKey>::type*>(keys.data()));
+
+  _hidl_cb(static_cast<Error>(error), keys);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getHdrCapabilities_2_3(uint64_t display,
+                                                       getHdrCapabilities_2_3_cb _hidl_cb) {
+  uint32_t count = 0;
+  hidl_vec<common_V1_2::Hdr> types;
+  float max_lumi = 0.0f;
+  float max_avg_lumi = 0.0f;
+  float min_lumi = 0.0f;
+
+  auto error = hwc_session_->GetHdrCapabilities(display, &count, nullptr, &max_lumi,
+                                                &max_avg_lumi, &min_lumi);
+  if (error != HWC2_ERROR_NONE) {
+    _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
+    return Void();
+  }
+
+  types.resize(count);
+  error = hwc_session_->GetHdrCapabilities(display, &count,
+           reinterpret_cast<std::underlying_type<common_V1_2::Hdr>::type*>(types.data()),
+           &max_lumi, &max_avg_lumi, &min_lumi);
+
+  _hidl_cb(static_cast<Error>(error), types, max_lumi, max_avg_lumi, min_lumi);
+  return Void();
+}
+
+Return<void> QtiComposerClient::getDisplayBrightnessSupport(uint64_t display,
+                                                         getDisplayBrightnessSupport_cb _hidl_cb) {
+  bool support = false;
+  auto error = hwc_session_->GetDisplayBrightnessSupport(display, &support);
+
+  _hidl_cb(static_cast<Error>(error), support);
+  return Void();
+}
+
+Return<Error> QtiComposerClient::setDisplayBrightness(uint64_t display, float brightness) {
+  if (std::isnan(brightness) || brightness > 1.0f || (brightness < 0.0f && brightness != -1.0f)) {
+    return Error::BAD_PARAMETER;
+  }
+
+  auto error = hwc_session_->SetDisplayBrightness(display, brightness);
+  return static_cast<Error>(error);
+}
+
+QtiComposerClient::CommandReader::CommandReader(QtiComposerClient& client)
+  : mClient(client), mWriter(client.mWriter) {
+}
+
+Error QtiComposerClient::CommandReader::parse() {
+  IComposerClient::Command command;
+  uint16_t length;
+
+  while (!isEmpty()) {
+    if (!beginCommand(command, length)) {
+      break;
+    }
+
+    bool parsed = false;
+    switch (command) {
+    // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+    case IComposerClient::Command::SELECT_DISPLAY:
+      parsed = parseSelectDisplay(length);
+      break;
+    case IComposerClient::Command::SELECT_LAYER:
+      parsed = parseSelectLayer(length);
+      break;
+    case IComposerClient::Command::SET_COLOR_TRANSFORM:
+      parsed = parseSetColorTransform(length);
+      break;
+    case IComposerClient::Command::SET_CLIENT_TARGET:
+      parsed = parseSetClientTarget(length);
+      break;
+    case IComposerClient::Command::SET_OUTPUT_BUFFER:
+      parsed = parseSetOutputBuffer(length);
+      break;
+    case IComposerClient::Command::VALIDATE_DISPLAY:
+      parsed = parseValidateDisplay(length);
+      break;
+    case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+      parsed = parseAcceptDisplayChanges(length);
+      break;
+    case IComposerClient::Command::PRESENT_DISPLAY:
+      parsed = parsePresentDisplay(length);
+      break;
+    case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+      parsed = parsePresentOrValidateDisplay(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+      parsed = parseSetLayerCursorPosition(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_BUFFER:
+      parsed = parseSetLayerBuffer(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+      parsed = parseSetLayerSurfaceDamage(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+      parsed = parseSetLayerBlendMode(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_COLOR:
+      parsed = parseSetLayerColor(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+      parsed = parseSetLayerCompositionType(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_DATASPACE:
+      parsed = parseSetLayerDataspace(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+      parsed = parseSetLayerDisplayFrame(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+      parsed = parseSetLayerPlaneAlpha(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+      parsed = parseSetLayerSidebandStream(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+      parsed = parseSetLayerSourceCrop(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_TRANSFORM:
+      parsed = parseSetLayerTransform(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+      parsed = parseSetLayerVisibleRegion(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_Z_ORDER:
+      parsed = parseSetLayerZOrder(length);
+      break;
+    // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+    case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA:
+      parsed = parseSetLayerPerFrameMetadata(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
+      parsed = parseSetLayerFloatColor(length);
+      break;
+    // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+    case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM:
+      parsed = parseSetLayerColorTransform(length);
+      break;
+    case IComposerClient::Command::SET_LAYER_PER_FRAME_METADATA_BLOBS:
+      parsed = parseSetLayerPerFrameMetadataBlobs(length);
+      break;
+    default:
+      parsed = false;
+      break;
+    }
+
+    endCommand();
+
+    if (!parsed) {
+      ALOGE("failed to parse command 0x%x, length %" PRIu16,
+          command, length);
+      break;
+    }
+  }
+
+  return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
+}
+
+bool QtiComposerClient::CommandReader::parseSelectDisplay(uint16_t length) {
+  if (length != CommandWriter::kSelectDisplayLength) {
+    return false;
+  }
+
+  mDisplay = read64();
+  mWriter.selectDisplay(mDisplay);
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSelectLayer(uint16_t length) {
+  if (length != CommandWriter::kSelectLayerLength) {
+    return false;
+  }
+
+  mLayer = read64();
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetColorTransform(uint16_t length) {
+  if (length != CommandWriter::kSetColorTransformLength) {
+    return false;
+  }
+
+  float matrix[16];
+  for (int i = 0; i < 16; i++) {
+    matrix[i] = readFloat();
+  }
+  auto transform = readSigned();
+
+  auto err = mClient.hwc_session_->SetColorTransform(mDisplay, matrix, transform);
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetClientTarget(uint16_t length) {
+  // 4 parameters followed by N rectangles
+  if ((length - 4) % 4 != 0) {
+    return false;
+  }
+
+  bool useCache = false;
+  auto slot = read();
+  auto clientTarget = readHandle(useCache);
+  auto fence = readFence();
+  auto dataspace = readSigned();
+  auto damage = readRegion((length - 4) / 4);
+  bool closeFence = true;
+  hwc_region region = {damage.size(), damage.data()};
+  auto err = lookupBuffer(BufferCache::CLIENT_TARGETS, slot, useCache, clientTarget, &clientTarget);
+  if (err == Error::NONE) {
+    auto error = mClient.hwc_session_->SetClientTarget(mDisplay, clientTarget, fence,
+        dataspace, region);
+    err = static_cast<Error>(error);
+    auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
+        useCache, clientTarget);
+    if (err == Error::NONE) {
+      closeFence = false;
+      err = updateBufErr;
+    }
+  }
+  if (closeFence) {
+    close(fence);
+  }
+  if (err != Error::NONE) {
+    mWriter.setError(getCommandLoc(), err);
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length) {
+  if (length != CommandWriter::kSetOutputBufferLength) {
+    return false;
+  }
+
+  bool useCache;
+  auto slot = read();
+  auto outputBuffer = readHandle(useCache);
+  auto fence = readFence();
+  bool closeFence = true;
+
+  auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS, slot, useCache, outputBuffer, &outputBuffer);
+  if (err == Error::NONE) {
+    auto error = mClient.hwc_session_->SetOutputBuffer(mDisplay, outputBuffer, fence);
+    err = static_cast<Error>(error);
+    auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS, slot, useCache, outputBuffer);
+    if (err == Error::NONE) {
+      closeFence = false;
+      err = updateBufErr;
+    }
+  }
+  if (closeFence) {
+    close(fence);
+  }
+  if (err != Error::NONE) {
+    mWriter.setError(getCommandLoc(), err);
+  }
+
+  return true;
+}
+
+Error QtiComposerClient::CommandReader::validateDisplay(Display display,
+                                       std::vector<Layer>& changedLayers,
+                                       std::vector<IComposerClient::Composition>& compositionTypes,
+                                       uint32_t& displayRequestMask,
+                                       std::vector<Layer>& requestedLayers,
+                                       std::vector<uint32_t>& requestMasks) {
+  uint32_t types_count = 0;
+  uint32_t reqs_count = 0;
+
+  auto err = mClient.hwc_session_->ValidateDisplay(mDisplay, &types_count, &reqs_count);
+  if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+    return static_cast<Error>(err);
+  }
+
+  err = mClient.hwc_session_->GetChangedCompositionTypes(mDisplay, &types_count, nullptr, nullptr);
+  if (err != HWC2_ERROR_NONE) {
+    return static_cast<Error>(err);
+  }
+
+  changedLayers.resize(types_count);
+  compositionTypes.resize(types_count);
+  err = mClient.hwc_session_->GetChangedCompositionTypes(mDisplay, &types_count,
+                        changedLayers.data(),
+                        reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+                        compositionTypes.data()));
+
+  if (err != HWC2_ERROR_NONE) {
+    changedLayers.clear();
+    compositionTypes.clear();
+    return static_cast<Error>(err);
+  }
+
+  int32_t display_reqs = 0;
+  err = mClient.hwc_session_->GetDisplayRequests(mDisplay, &display_reqs, &reqs_count, nullptr,
+                                                 nullptr);
+  if (err != HWC2_ERROR_NONE) {
+    changedLayers.clear();
+    compositionTypes.clear();
+    return static_cast<Error>(err);
+  }
+
+  requestedLayers.resize(reqs_count);
+  requestMasks.resize(reqs_count);
+  err = mClient.hwc_session_->GetDisplayRequests(mDisplay, &display_reqs, &reqs_count,
+                                                 requestedLayers.data(),
+                                                 reinterpret_cast<int32_t*>(requestMasks.data()));
+  if (err != HWC2_ERROR_NONE) {
+    changedLayers.clear();
+    compositionTypes.clear();
+
+    requestedLayers.clear();
+    requestMasks.clear();
+    return static_cast<Error>(err);
+  }
+
+  displayRequestMask = display_reqs;
+
+  return static_cast<Error>(err);
+}
+
+bool QtiComposerClient::CommandReader::parseValidateDisplay(uint16_t length) {
+  if (length != CommandWriter::kValidateDisplayLength) {
+    return false;
+  }
+
+  std::vector<Layer> changedLayers;
+  std::vector<IComposerClient::Composition> compositionTypes;
+  uint32_t displayRequestMask;
+  std::vector<Layer> requestedLayers;
+  std::vector<uint32_t> requestMasks;
+
+  auto err = validateDisplay(mDisplay, changedLayers, compositionTypes, displayRequestMask,
+                             requestedLayers, requestMasks);
+
+  if (static_cast<Error>(err) == Error::NONE) {
+    mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+    mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+  } else {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length) {
+  if (length != CommandWriter::kAcceptDisplayChangesLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->AcceptDisplayChanges(mDisplay);
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+Error QtiComposerClient::CommandReader::presentDisplay(Display display, int32_t& presentFence,
+                                                       std::vector<Layer>& layers,
+                                                       std::vector<int32_t>& releaseFences) {
+  int32_t err = mClient.hwc_session_->PresentDisplay(display, &presentFence);
+  if (err != HWC2_ERROR_NONE) {
+    return static_cast<Error>(err);
+  }
+
+  uint32_t count = 0;
+  err = mClient.hwc_session_->GetReleaseFences(display, &count, nullptr, nullptr);
+  if (err != HWC2_ERROR_NONE) {
+    ALOGW("failed to get release fences");
+    return Error::NONE;
+  }
+
+  layers.resize(count);
+  releaseFences.resize(count);
+  err = mClient.hwc_session_->GetReleaseFences(display, &count, layers.data(),
+                                               releaseFences.data());
+  if (err != HWC2_ERROR_NONE) {
+    ALOGW("failed to get release fences");
+    layers.clear();
+    releaseFences.clear();
+    return Error::NONE;
+  }
+
+  return static_cast<Error>(err);
+}
+
+bool QtiComposerClient::CommandReader::parsePresentDisplay(uint16_t length) {
+  if (length != CommandWriter::kPresentDisplayLength) {
+    return false;
+  }
+
+  int presentFence;
+  std::vector<Layer> layers;
+  std::vector<int> fences;
+
+  auto err = presentDisplay(mDisplay, presentFence, layers, fences);
+  if (err == Error::NONE) {
+    mWriter.setPresentFence(presentFence);
+    mWriter.setReleaseFences(layers, fences);
+  } else {
+    mWriter.setError(getCommandLoc(), err);
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length) {
+  if (length != CommandWriter::kPresentOrValidateDisplayLength) {
+     return false;
+  }
+
+  // First try to Present as is.
+  mClient.getCapabilities();
+  if (mClient.hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+    int presentFence = -1;
+    std::vector<Layer> layers;
+    std::vector<int> fences;
+    auto err = presentDisplay(mDisplay, presentFence, layers, fences);
+    if (err == Error::NONE) {
+      mWriter.setPresentOrValidateResult(1);
+      mWriter.setPresentFence(presentFence);
+      mWriter.setReleaseFences(layers, fences);
+      return true;
+    }
+  }
+
+  // Present has failed. We need to fallback to validate
+  std::vector<Layer> changedLayers;
+  std::vector<IComposerClient::Composition> compositionTypes;
+  uint32_t displayRequestMask = 0x0;
+  std::vector<Layer> requestedLayers;
+  std::vector<uint32_t> requestMasks;
+
+  auto err = validateDisplay(mDisplay, changedLayers, compositionTypes, displayRequestMask,
+                             requestedLayers, requestMasks);
+  // mResources->setDisplayMustValidateState(mDisplay, false);
+  if (err == Error::NONE) {
+    mWriter.setPresentOrValidateResult(0);
+    mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+    mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+  } else {
+    mWriter.setError(getCommandLoc(), err);
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length) {
+  if (length != CommandWriter::kSetLayerCursorPositionLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetCursorPosition(mDisplay, mLayer, readSigned(), readSigned());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length) {
+  if (length != CommandWriter::kSetLayerBufferLength) {
+    return false;
+  }
+
+  bool useCache;
+  auto slot = read();
+  auto buffer = readHandle(useCache);
+  auto fence = readFence();
+  bool closeFence = true;
+
+  auto error = lookupBuffer(BufferCache::LAYER_BUFFERS, slot, useCache, buffer, &buffer);
+  if (error == Error::NONE) {
+    auto err = mClient.hwc_session_->SetLayerBuffer(mDisplay, mLayer, buffer, fence);
+    error = static_cast<Error>(err);
+    auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot, useCache, buffer);
+    if (static_cast<Error>(error) == Error::NONE) {
+      closeFence = false;
+      error = updateBufErr;
+    }
+  }
+  if (closeFence) {
+    close(fence);
+  }
+  if (static_cast<Error>(error) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(error));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length) {
+  // N rectangles
+  if (length % 4 != 0) {
+    return false;
+  }
+
+  auto damage = readRegion(length / 4);
+  hwc_region region = {damage.size(), damage.data()};
+  auto err = mClient.hwc_session_->SetLayerSurfaceDamage(mDisplay, mLayer, region);
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length) {
+  if (length != CommandWriter::kSetLayerBlendModeLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerBlendMode(mDisplay, mLayer, readSigned());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerColor(uint16_t length) {
+  if (length != CommandWriter::kSetLayerColorLength) {
+    return false;
+  }
+  auto color = readColor();
+  hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
+  auto err = mClient.hwc_session_->SetLayerColor(mDisplay, mLayer, hwc_color);
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerCompositionType(uint16_t length) {
+  if (length != CommandWriter::kSetLayerCompositionTypeLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerCompositionType(mDisplay, mLayer, readSigned());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length) {
+  if (length != CommandWriter::kSetLayerDataspaceLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerDataspace(mDisplay, mLayer, readSigned());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length) {
+  if (length != CommandWriter::kSetLayerDisplayFrameLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerDisplayFrame(mDisplay, mLayer, readRect());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length) {
+  if (length != CommandWriter::kSetLayerPlaneAlphaLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerPlaneAlpha(mDisplay, mLayer, readFloat());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length) {
+  if (length != CommandWriter::kSetLayerSidebandStreamLength) {
+    return false;
+  }
+
+  // Sideband stream is not supported
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length) {
+  if (length != CommandWriter::kSetLayerSourceCropLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerSourceCrop(mDisplay, mLayer, readFRect());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerTransform(uint16_t length) {
+  if (length != CommandWriter::kSetLayerTransformLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerTransform(mDisplay, mLayer, readSigned());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length) {
+  // N rectangles
+  if (length % 4 != 0) {
+    return false;
+  }
+
+  auto region = readRegion(length / 4);
+  hwc_region visibleRegion = {region.size(), region.data()};
+  auto err = mClient.hwc_session_->SetLayerVisibleRegion(mDisplay, mLayer, visibleRegion);
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length) {
+  if (length != CommandWriter::kSetLayerZOrderLength) {
+    return false;
+  }
+
+  auto err = mClient.hwc_session_->SetLayerZOrder(mDisplay, mLayer, read());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerPerFrameMetadata(uint16_t length) {
+  // (key, value) pairs
+  if (length % 2 != 0) {
+    return false;
+  }
+
+  std::vector<IComposerClient::PerFrameMetadata> metadata;
+  metadata.reserve(length / 2);
+  while (length > 0) {
+    metadata.emplace_back(IComposerClient::PerFrameMetadata{
+                          static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()),
+                          readFloat()});
+    length -= 2;
+  }
+
+  std::vector<int32_t> keys;
+  std::vector<float> values;
+  keys.reserve(metadata.size());
+  values.reserve(metadata.size());
+  for (const auto& m : metadata) {
+    keys.push_back(static_cast<int32_t>(m.key));
+    values.push_back(m.value);
+  }
+
+  auto err = mClient.hwc_session_->SetLayerPerFrameMetadata(mDisplay, mLayer, metadata.size(),
+                                                            keys.data(), values.data());
+  if (static_cast<Error>(err) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerFloatColor(uint16_t length) {
+  if (length != CommandWriter::kSetLayerFloatColorLength) {
+    return false;
+  }
+
+  // setLayerFloatColor is not supported
+  auto err = Error::UNSUPPORTED;
+  mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerColorTransform(uint16_t length) {
+  if (length != CommandWriter::kSetLayerColorTransformLength) {
+    return false;
+  }
+
+  float matrix[16];
+  for (int i = 0; i < 16; i++) {
+    matrix[i] = readFloat();
+  }
+
+  auto error = mClient.hwc_session_->SetLayerColorTransform(mDisplay, mLayer, matrix);
+  if (static_cast<Error>(error) != Error::NONE) {
+    mWriter.setError(getCommandLoc(), static_cast<Error>(error));
+  }
+
+  return true;
+}
+
+bool QtiComposerClient::CommandReader::parseSetLayerPerFrameMetadataBlobs(uint16_t length) {
+  // must have at least one metadata blob
+  // of at least size 1 in queue (i.e {/*numBlobs=*/1, key, size, blob})
+  if (length < 4) {
+    return false;
+  }
+
+  // SetLayerPerFrameMetadataBlobs is not supported
+  auto err = Error::UNSUPPORTED;
+  mWriter.setError(getCommandLoc(), static_cast<Error>(err));
+
+  return true;
+}
+
+hwc_rect_t QtiComposerClient::CommandReader::readRect() {
+  return hwc_rect_t{
+    readSigned(),
+    readSigned(),
+    readSigned(),
+    readSigned(),
+  };
+}
+
+std::vector<hwc_rect_t> QtiComposerClient::CommandReader::readRegion(size_t count) {
+  std::vector<hwc_rect_t> region;
+  region.reserve(count);
+  while (count > 0) {
+    region.emplace_back(readRect());
+    count--;
+  }
+
+  return region;
+}
+
+hwc_frect_t QtiComposerClient::CommandReader::readFRect() {
+  return hwc_frect_t{
+    readFloat(),
+    readFloat(),
+    readFloat(),
+    readFloat(),
+  };
+}
+
+Error QtiComposerClient::CommandReader::lookupBufferCacheEntryLocked(BufferCache cache,
+                                                                     uint32_t slot,
+                                                                     BufferCacheEntry** outEntry) {
+  auto dpy = mClient.mDisplayData.find(mDisplay);
+  if (dpy == mClient.mDisplayData.end()) {
+    return Error::BAD_DISPLAY;
+  }
+
+  BufferCacheEntry* entry = nullptr;
+  switch (cache) {
+  case BufferCache::CLIENT_TARGETS:
+    if (slot < dpy->second.ClientTargets.size()) {
+      entry = &dpy->second.ClientTargets[slot];
+    }
+    break;
+  case BufferCache::OUTPUT_BUFFERS:
+    if (slot < dpy->second.OutputBuffers.size()) {
+      entry = &dpy->second.OutputBuffers[slot];
+    }
+    break;
+  case BufferCache::LAYER_BUFFERS:
+    {
+      auto ly = dpy->second.Layers.find(mLayer);
+      if (ly == dpy->second.Layers.end()) {
+        return Error::BAD_LAYER;
+      }
+      if (slot < ly->second.Buffers.size()) {
+        entry = &ly->second.Buffers[slot];
+      }
+    }
+    break;
+  case BufferCache::LAYER_SIDEBAND_STREAMS:
+    {
+      auto ly = dpy->second.Layers.find(mLayer);
+      if (ly == dpy->second.Layers.end()) {
+        return Error::BAD_LAYER;
+      }
+      if (slot == 0) {
+        entry = &ly->second.SidebandStream;
+      }
+    }
+    break;
+  default:
+    break;
+  }
+
+  if (!entry) {
+    ALOGW("invalid buffer slot %" PRIu32, slot);
+    return Error::BAD_PARAMETER;
+  }
+
+  *outEntry = entry;
+
+  return Error::NONE;
+}
+
+Error QtiComposerClient::CommandReader::lookupBuffer(BufferCache cache, uint32_t slot,
+                                                     bool useCache, buffer_handle_t handle,
+                                                     buffer_handle_t* outHandle) {
+  if (useCache) {
+    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
+
+    BufferCacheEntry* entry;
+    Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
+    if (error != Error::NONE) {
+      return error;
+    }
+
+    // input handle is ignored
+    *outHandle = entry->getHandle();
+  } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
+    if (handle) {
+      *outHandle = native_handle_clone(handle);
+      if (*outHandle == nullptr) {
+        return Error::NO_RESOURCES;
+      }
+    }
+  } else {
+    if (!mHandleImporter.importBuffer(handle)) {
+      return Error::NO_RESOURCES;
+    }
+
+    *outHandle = handle;
+  }
+
+  return Error::NONE;
+}
+
+Error QtiComposerClient::CommandReader::updateBuffer(BufferCache cache, uint32_t slot,
+                                                     bool useCache, buffer_handle_t handle) {
+  // handle was looked up from cache
+  if (useCache) {
+    return Error::NONE;
+  }
+
+  std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
+
+  BufferCacheEntry* entry = nullptr;
+  Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
+  if (error != Error::NONE) {
+    return error;
+  }
+
+  *entry = handle;
+  return Error::NONE;
+}
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+IQtiComposerClient* HIDL_FETCH_IQtiComposerClient(const char* /* name */) {
+  return new QtiComposerClient();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
diff --git a/composer/QtiComposerClient.h b/composer/QtiComposerClient.h
new file mode 100644
index 0000000..8db39db
--- /dev/null
+++ b/composer/QtiComposerClient.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __QTICOMPOSERCLIENT_H__
+#define __QTICOMPOSERCLIENT_H__
+
+#include <vendor/qti/hardware/display/composer/1.0/IQtiComposerClient.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <log/log.h>
+#include <unordered_set>
+#include <vector>
+
+#include "hwc_session.h"
+#include "QtiComposerCommandBuffer.h"
+#include "QtiComposerHandleImporter.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+namespace implementation {
+
+namespace common_V1_0 = ::android::hardware::graphics::common::V1_0;
+namespace common_V1_1 = ::android::hardware::graphics::common::V1_1;
+namespace common_V1_2 = ::android::hardware::graphics::common::V1_2;
+
+namespace composer_V2_1 = ::android::hardware::graphics::composer::V2_1;
+namespace composer_V2_2 = ::android::hardware::graphics::composer::V2_2;
+namespace composer_V2_3 = ::android::hardware::graphics::composer::V2_3;
+
+using PerFrameMetadataKey_V2 = composer_V2_2::IComposerClient::PerFrameMetadataKey;
+using PerFrameMetadataKey = composer_V2_3::IComposerClient::PerFrameMetadataKey;
+
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_bitfield;
+using ::android::hardware::graphics::composer::V2_1::Error;
+
+using sdm::HWCSession;
+
+class BufferCacheEntry {
+ public:
+  BufferCacheEntry();
+  BufferCacheEntry(BufferCacheEntry&& other);
+
+  BufferCacheEntry(const BufferCacheEntry& other) = delete;
+  BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
+
+  BufferCacheEntry& operator=(buffer_handle_t handle);
+  ~BufferCacheEntry();
+
+  buffer_handle_t getHandle() const { return mHandle; }
+
+ private:
+  void clear();
+
+  buffer_handle_t mHandle;
+};
+
+class QtiComposerClient : public IQtiComposerClient {
+ public:
+  QtiComposerClient();
+  virtual ~QtiComposerClient();
+
+  // Methods from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+  Return<void> registerCallback(const sp<composer_V2_1::IComposerCallback>& callback) override;
+  Return<uint32_t> getMaxVirtualDisplayCount() override;
+  Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
+                                    common_V1_0::PixelFormat formatHint,
+                                    uint32_t outputBufferSlotCount,
+                                    createVirtualDisplay_cb _hidl_cb) override;
+  Return<Error> destroyVirtualDisplay(uint64_t display) override;
+  Return<void> createLayer(uint64_t display, uint32_t bufferSlotCount,
+                           createLayer_cb _hidl_cb) override;
+  Return<Error> destroyLayer(uint64_t display, uint64_t layer) override;
+  Return<void> getActiveConfig(uint64_t display, getActiveConfig_cb _hidl_cb) override;
+  Return<Error> getClientTargetSupport(uint64_t display, uint32_t width, uint32_t height,
+                                       common_V1_0::PixelFormat format,
+                                       common_V1_0::Dataspace dataspace) override;
+  Return<void> getColorModes(uint64_t display, getColorModes_cb _hidl_cb) override;
+  Return<void> getDisplayAttribute(uint64_t display, uint32_t config,
+                                   composer_V2_1::IComposerClient::Attribute attribute,
+                                   getDisplayAttribute_cb _hidl_cb) override;
+  Return<void> getDisplayConfigs(uint64_t display, getDisplayConfigs_cb _hidl_cb) override;
+  Return<void> getDisplayName(uint64_t display, getDisplayName_cb _hidl_cb) override;
+  Return<void> getDisplayType(uint64_t display, getDisplayType_cb _hidl_cb) override;
+  Return<void> getDozeSupport(uint64_t display, getDozeSupport_cb _hidl_cb) override;
+  Return<void> getHdrCapabilities(uint64_t display, getHdrCapabilities_cb _hidl_cb) override;
+  Return<Error> setClientTargetSlotCount(uint64_t display,
+                                         uint32_t clientTargetSlotCount) override;
+  Return<Error> setActiveConfig(uint64_t display, uint32_t config) override;
+  Return<Error> setColorMode(uint64_t display, common_V1_0::ColorMode mode) override;
+  Return<Error> setPowerMode(uint64_t display,
+                             composer_V2_1::IComposerClient::PowerMode mode) override;
+  Return<Error> setVsyncEnabled(uint64_t display,
+                                composer_V2_1::IComposerClient::Vsync enabled) override;
+  Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override;
+  Return<void> getOutputCommandQueue(getOutputCommandQueue_cb _hidl_cb) override;
+  Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                               executeCommands_cb _hidl_cb) override;
+
+  // Methods from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+  Return<void> getPerFrameMetadataKeys(uint64_t display,
+                                       getPerFrameMetadataKeys_cb _hidl_cb) override;
+  Return<void> getReadbackBufferAttributes(uint64_t display,
+                                          getReadbackBufferAttributes_cb _hidl_cb) override;
+  Return<void> getReadbackBufferFence(uint64_t display,
+                                      getReadbackBufferFence_cb _hidl_cb) override;
+  Return<Error> setReadbackBuffer(uint64_t display, const hidl_handle& buffer,
+                                  const hidl_handle& releaseFence) override;
+  Return<void> createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+                                        common_V1_1::PixelFormat formatHint,
+                                        uint32_t outputBufferSlotCount,
+                                        createVirtualDisplay_2_2_cb _hidl_cb) override;
+  Return<Error> getClientTargetSupport_2_2(uint64_t display, uint32_t width, uint32_t height,
+                                           common_V1_1::PixelFormat format,
+                                           common_V1_1::Dataspace dataspace) override;
+  Return<Error> setPowerMode_2_2(uint64_t display,
+                                 composer_V2_2::IComposerClient::PowerMode mode) override;
+  Return<void> getColorModes_2_2(uint64_t display, getColorModes_2_2_cb _hidl_cb) override;
+  Return<void> getRenderIntents(uint64_t display, common_V1_1::ColorMode mode,
+                                getRenderIntents_cb _hidl_cb) override;
+  Return<Error> setColorMode_2_2(uint64_t display, common_V1_1::ColorMode mode,
+                                 common_V1_1::RenderIntent intent) override;
+  Return<void> getDataspaceSaturationMatrix(common_V1_1::Dataspace dataspace,
+                                            getDataspaceSaturationMatrix_cb _hidl_cb) override;
+  Return<void> executeCommands_2_2(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                   executeCommands_2_2_cb _hidl_cb) override;
+
+  // Methods from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+  Return<void> getDisplayIdentificationData(uint64_t display,
+                                            getDisplayIdentificationData_cb _hidl_cb) override;
+  Return<void> getReadbackBufferAttributes_2_3(uint64_t display,
+                                             getReadbackBufferAttributes_2_3_cb _hidl_cb) override;
+  Return<Error> getClientTargetSupport_2_3(uint64_t display, uint32_t width, uint32_t height,
+                                           common_V1_2::PixelFormat format,
+                                           common_V1_2::Dataspace dataspace) override;
+  Return<void> getDisplayedContentSamplingAttributes(uint64_t display,
+                                       getDisplayedContentSamplingAttributes_cb _hidl_cb) override;
+  Return<Error> setDisplayedContentSamplingEnabled(uint64_t display,
+                                   composer_V2_3::IComposerClient::DisplayedContentSampling enable,
+                                   hidl_bitfield<FormatColorComponent> componentMask,
+                                   uint64_t maxFrames) override;
+  Return<void> getDisplayedContentSample(uint64_t display, uint64_t maxFrames,
+                                         uint64_t timestamp,
+                                         getDisplayedContentSample_cb _hidl_cb) override;
+  Return<void> executeCommands_2_3(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                   executeCommands_2_3_cb _hidl_cb) override;
+  Return<void> getRenderIntents_2_3(uint64_t display, common_V1_2::ColorMode mode,
+                                    getRenderIntents_2_3_cb _hidl_cb) override;
+  Return<void> getColorModes_2_3(uint64_t display, getColorModes_2_3_cb _hidl_cb) override;
+  Return<Error> setColorMode_2_3(uint64_t display, common_V1_2::ColorMode mode,
+                                 common_V1_1::RenderIntent intent) override;
+  Return<void> getDisplayCapabilities(uint64_t display,
+                                      getDisplayCapabilities_cb _hidl_cb) override;
+  Return<void> getPerFrameMetadataKeys_2_3(uint64_t display,
+                                           getPerFrameMetadataKeys_2_3_cb _hidl_cb) override;
+  Return<void> getHdrCapabilities_2_3(uint64_t display,
+                                      getHdrCapabilities_2_3_cb _hidl_cb) override;
+  Return<void> getDisplayBrightnessSupport(uint64_t display,
+                                           getDisplayBrightnessSupport_cb _hidl_cb) override;
+  Return<Error> setDisplayBrightness(uint64_t display, float brightness) override;
+
+  // Methods for RegisterCallback
+  void enableCallback(bool enable);
+  static void onHotplug(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                          int32_t connected);
+  static void onRefresh(hwc2_callback_data_t callbackData, hwc2_display_t display);
+  static void onVsync(hwc2_callback_data_t callbackData, hwc2_display_t display,
+                        int64_t timestamp);
+
+  // Methods for ConcurrentWriteBack
+  hidl_handle getFenceHandle(const android::base::unique_fd& fenceFd, char* handleStorage);
+  Error getFenceFd(const hidl_handle& fenceHandle, android::base::unique_fd* outFenceFd);
+  Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+                                 const native_handle_t** outHandle);
+
+  // Methods to check support of specific features like skip_validate
+  std::unordered_set<hwc2_capability_t> mCapabilities;
+  void getCapabilities();
+  bool hasCapability(hwc2_capability_t capability) {
+    return (mCapabilities.count(capability) > 0);
+  }
+
+ private:
+  struct LayerBuffers {
+    std::vector<BufferCacheEntry> Buffers;
+    // the handle is a sideband stream handle, not a buffer handle
+    BufferCacheEntry SidebandStream;
+  };
+
+  struct DisplayData {
+    bool IsVirtual;
+
+    std::vector<BufferCacheEntry> ClientTargets;
+    std::vector<BufferCacheEntry> OutputBuffers;
+
+    std::unordered_map<Layer, LayerBuffers> Layers;
+
+    DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
+  };
+
+  class CommandReader : public CommandReaderBase {
+   public:
+    CommandReader(QtiComposerClient& client);
+    Error parse();
+    Error validateDisplay(Display display, std::vector<Layer>& changedLayers,
+                          std::vector<IComposerClient::Composition>& compositionTypes,
+                          uint32_t& displayRequestMask, std::vector<Layer>& requestedLayers,
+                          std::vector<uint32_t>& requestMasks);
+    Error presentDisplay(Display display, int32_t& presentFence, std::vector<Layer>& layers,
+                         std::vector<int32_t>& releaseFences);
+
+   private:
+    // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+    bool parseSelectDisplay(uint16_t length);
+    bool parseSelectLayer(uint16_t length);
+    bool parseSetColorTransform(uint16_t length);
+    bool parseSetClientTarget(uint16_t length);
+    bool parseSetOutputBuffer(uint16_t length);
+    bool parseValidateDisplay(uint16_t length);
+    bool parseAcceptDisplayChanges(uint16_t length);
+    bool parsePresentDisplay(uint16_t length);
+    bool parsePresentOrValidateDisplay(uint16_t length);
+    bool parseSetLayerCursorPosition(uint16_t length);
+    bool parseSetLayerBuffer(uint16_t length);
+    bool parseSetLayerSurfaceDamage(uint16_t length);
+    bool parseSetLayerBlendMode(uint16_t length);
+    bool parseSetLayerColor(uint16_t length);
+    bool parseSetLayerCompositionType(uint16_t length);
+    bool parseSetLayerDataspace(uint16_t length);
+    bool parseSetLayerDisplayFrame(uint16_t length);
+    bool parseSetLayerPlaneAlpha(uint16_t length);
+    bool parseSetLayerSidebandStream(uint16_t length);
+    bool parseSetLayerSourceCrop(uint16_t length);
+    bool parseSetLayerTransform(uint16_t length);
+    bool parseSetLayerVisibleRegion(uint16_t length);
+    bool parseSetLayerZOrder(uint16_t length);
+
+    // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+    bool parseSetLayerPerFrameMetadata(uint16_t length);
+    bool parseSetLayerFloatColor(uint16_t length);
+
+    // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+    bool parseSetLayerColorTransform(uint16_t length);
+    bool parseSetLayerPerFrameMetadataBlobs(uint16_t length);
+
+    hwc_rect_t readRect();
+    std::vector<hwc_rect_t> readRegion(size_t count);
+    hwc_frect_t readFRect();
+    QtiComposerClient& mClient;
+    CommandWriter& mWriter;
+    Display mDisplay;
+    Layer mLayer;
+
+    // Buffer cache impl
+    enum class BufferCache {
+      CLIENT_TARGETS,
+      OUTPUT_BUFFERS,
+      LAYER_BUFFERS,
+      LAYER_SIDEBAND_STREAMS,
+    };
+
+    Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
+                                       BufferCacheEntry** outEntry);
+    Error lookupBuffer(BufferCache cache, uint32_t slot, bool useCache, buffer_handle_t handle,
+                       buffer_handle_t* outHandle);
+    Error updateBuffer(BufferCache cache, uint32_t slot, bool useCache, buffer_handle_t handle);
+
+    Error lookupLayerSidebandStream(buffer_handle_t handle, buffer_handle_t* outHandle) {
+      return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS, 0, false, handle, outHandle);
+    }
+    Error updateLayerSidebandStream(buffer_handle_t handle) {
+      return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS, 0, false, handle);
+    }
+  };
+
+  HWCSession *hwc_session_ = nullptr;
+  sp<composer_V2_1::IComposerCallback> mCallback;
+  std::mutex mCommandMutex;
+  // 64KiB minus a small space for metadata such as read/write pointers */
+  static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+  CommandWriter mWriter;
+  CommandReader mReader;
+  std::mutex mDisplayDataMutex;
+  std::unordered_map<Display, DisplayData> mDisplayData;
+};
+
+extern "C" IQtiComposerClient* HIDL_FETCH_IQtiComposerClient(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
+#endif  // __QTICOMPOSERCLIENT_H__
diff --git a/composer/QtiComposerCommandBuffer.h b/composer/QtiComposerCommandBuffer.h
new file mode 100644
index 0000000..9139906
--- /dev/null
+++ b/composer/QtiComposerCommandBuffer.h
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __QTICOMPOSERCOMMANDBUFFER_H__
+#define __QTICOMPOSERCOMMANDBUFFER_H__
+
+#include <limits>
+#include <algorithm>
+#include <vector>
+
+#include <log/log.h>
+#include <sync/sync.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+
+using ::android::hardware::graphics::common::V1_0::ColorTransform;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::Transform;
+using ::android::hardware::graphics::composer::V2_1::Error;
+using ::android::hardware::graphics::composer::V2_1::Display;
+using ::android::hardware::graphics::composer::V2_1::Layer;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_handle;
+
+using CommandQueueType = MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite>;
+
+// This class helps build a command queue.  Note that all sizes/lengths are in units of uint32_t's.
+class CommandWriter {
+ public:
+  CommandWriter(uint32_t initialMaxSize) : mDataMaxSize(initialMaxSize) {
+    mData = std::make_unique<uint32_t[]>(mDataMaxSize);
+    reset();
+  }
+
+  ~CommandWriter() { reset(); }
+
+  void reset() {
+    mDataWritten = 0;
+    mCommandEnd = 0;
+
+    // handles in mDataHandles are owned by the caller
+    mDataHandles.clear();
+
+    // handles in mTemporaryHandles are owned by the writer
+    for (auto handle : mTemporaryHandles) {
+      native_handle_close(handle);
+      native_handle_delete(handle);
+    }
+    mTemporaryHandles.clear();
+  }
+
+  IQtiComposerClient::Command getCommand(uint32_t offset) {
+    uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
+    return static_cast<IQtiComposerClient::Command>(val &
+      static_cast<uint32_t>(IQtiComposerClient::Command::OPCODE_MASK));
+  }
+
+  bool writeQueue(bool& queueChanged, uint32_t& commandLength,
+                  hidl_vec<hidl_handle>& commandHandles) {
+    if (mDataWritten == 0) {
+      queueChanged = false;
+      commandLength = 0;
+      commandHandles.setToExternal(nullptr, 0);
+      return true;
+    }
+
+    // After data are written to the queue, it may not be read by the
+    // remote reader when
+    //
+    //  - the writer does not send them (because of other errors)
+    //  - the hwbinder transaction fails
+    //  - the reader does not read them (because of other errors)
+    //
+    // Discard the stale data here.
+    size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
+    if (staleDataSize > 0) {
+      ALOGW("discarding stale data from message queue");
+      CommandQueueType::MemTransaction tx;
+      if (mQueue->beginRead(staleDataSize, &tx)) {
+        mQueue->commitRead(staleDataSize);
+      }
+    }
+    // write data to queue, optionally resizing it
+    if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
+      if (!mQueue->write(mData.get(), mDataWritten)) {
+        ALOGE("failed to write commands to message queue");
+        return false;
+      }
+
+      queueChanged = false;
+    } else {
+      auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
+      if (!newQueue->isValid() || !newQueue->write(mData.get(), mDataWritten)) {
+        ALOGE("failed to prepare a new message queue ");
+        return false;
+      }
+
+      mQueue = std::move(newQueue);
+      queueChanged = true;
+    }
+
+    commandLength = mDataWritten;
+    commandHandles.setToExternal(const_cast<hidl_handle*>(mDataHandles.data()),
+                                 mDataHandles.size());
+
+    return true;
+  }
+
+  const MQDescriptorSync<uint32_t>* getMQDescriptor() const {
+    return (mQueue) ? mQueue->getDesc() : nullptr;
+  }
+
+  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+  static constexpr uint16_t kSelectDisplayLength = 2;
+  void selectDisplay(Display display) {
+    beginCommand(IQtiComposerClient::Command::SELECT_DISPLAY, kSelectDisplayLength);
+    write64(display);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSelectLayerLength = 2;
+  void selectLayer(Layer layer) {
+    beginCommand(IQtiComposerClient::Command::SELECT_LAYER, kSelectLayerLength);
+    write64(layer);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetErrorLength = 2;
+  void setError(uint32_t location, Error error) {
+    beginCommand(IQtiComposerClient::Command::SET_ERROR, kSetErrorLength);
+    write(location);
+    writeSigned(static_cast<int32_t>(error));
+    endCommand();
+  }
+
+  static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
+  void setPresentOrValidateResult(uint32_t state) {
+    beginCommand(IQtiComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT,
+                 kPresentOrValidateDisplayResultLength);
+    write(state);
+    endCommand();
+  }
+
+  void setChangedCompositionTypes(const std::vector<Layer>& layers,
+                                  const std::vector<IQtiComposerClient::Composition>& types) {
+    size_t totalLayers = std::min(layers.size(), types.size());
+    size_t currentLayer = 0;
+
+    while (currentLayer < totalLayers) {
+      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
+
+      beginCommand(IQtiComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES, count * 3);
+      for (size_t i = 0; i < count; i++) {
+        write64(layers[currentLayer + i]);
+        writeSigned(static_cast<int32_t>(types[currentLayer + i]));
+      }
+      endCommand();
+
+      currentLayer += count;
+    }
+  }
+
+  void setDisplayRequests(uint32_t displayRequestMask, const std::vector<Layer>& layers,
+                          const std::vector<uint32_t>& layerRequestMasks) {
+    size_t totalLayers = std::min(layers.size(), layerRequestMasks.size());
+    size_t currentLayer = 0;
+
+    while (currentLayer < totalLayers) {
+      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength - 1) / 3);
+
+      beginCommand(IQtiComposerClient::Command::SET_DISPLAY_REQUESTS, 1 + count * 3);
+      write(displayRequestMask);
+      for (size_t i = 0; i < count; i++) {
+        write64(layers[currentLayer + i]);
+        write(static_cast<int32_t>(layerRequestMasks[currentLayer + i]));
+      }
+      endCommand();
+
+      currentLayer += count;
+    }
+  }
+
+  static constexpr uint16_t kSetPresentFenceLength = 1;
+  void setPresentFence(int presentFence) {
+    beginCommand(IQtiComposerClient::Command::SET_PRESENT_FENCE, kSetPresentFenceLength);
+    writeFence(presentFence);
+    endCommand();
+  }
+
+  void setReleaseFences(const std::vector<Layer>& layers, const std::vector<int>& releaseFences) {
+    size_t totalLayers = std::min(layers.size(), releaseFences.size());
+    size_t currentLayer = 0;
+
+    while (currentLayer < totalLayers) {
+      size_t count = std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
+
+      beginCommand(IQtiComposerClient::Command::SET_RELEASE_FENCES, count * 3);
+      for (size_t i = 0; i < count; i++) {
+        write64(layers[currentLayer + i]);
+        writeFence(releaseFences[currentLayer + i]);
+      }
+      endCommand();
+
+      currentLayer += count;
+    }
+  }
+
+  static constexpr uint16_t kSetColorTransformLength = 17;
+  void setColorTransform(const float* matrix, ColorTransform hint) {
+    beginCommand(IQtiComposerClient::Command::SET_COLOR_TRANSFORM, kSetColorTransformLength);
+    for (int i = 0; i < 16; i++) {
+      writeFloat(matrix[i]);
+    }
+    writeSigned(static_cast<int32_t>(hint));
+    endCommand();
+  }
+
+  void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                       Dataspace dataspace, const std::vector<IQtiComposerClient::Rect>& damage) {
+    bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
+    size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
+
+    beginCommand(IQtiComposerClient::Command::SET_CLIENT_TARGET, length);
+    write(slot);
+    writeHandle(target, true);
+    writeFence(acquireFence);
+    writeSigned(static_cast<int32_t>(dataspace));
+    // When there are too many rectangles in the damage region and doWrite
+    // is false, we write no rectangle at all which means the entire
+    // client target is damaged.
+    if (doWrite) {
+      writeRegion(damage);
+    }
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetOutputBufferLength = 3;
+  void setOutputBuffer(uint32_t slot, const native_handle_t* buffer, int releaseFence) {
+    beginCommand(IQtiComposerClient::Command::SET_OUTPUT_BUFFER, kSetOutputBufferLength);
+    write(slot);
+    writeHandle(buffer, true);
+    writeFence(releaseFence);
+    endCommand();
+  }
+
+  static constexpr uint16_t kValidateDisplayLength = 0;
+  void validateDisplay() {
+    beginCommand(IQtiComposerClient::Command::VALIDATE_DISPLAY, kValidateDisplayLength);
+    endCommand();
+  }
+
+  static constexpr uint16_t kPresentOrValidateDisplayLength = 0;
+  void presentOrvalidateDisplay() {
+    beginCommand(IQtiComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY,
+                 kPresentOrValidateDisplayLength);
+    endCommand();
+  }
+
+  static constexpr uint16_t kAcceptDisplayChangesLength = 0;
+  void acceptDisplayChanges() {
+    beginCommand(IQtiComposerClient::Command::ACCEPT_DISPLAY_CHANGES, kAcceptDisplayChangesLength);
+    endCommand();
+  }
+
+  static constexpr uint16_t kPresentDisplayLength = 0;
+  void presentDisplay() {
+    beginCommand(IQtiComposerClient::Command::PRESENT_DISPLAY, kPresentDisplayLength);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerCursorPositionLength = 2;
+  void setLayerCursorPosition(int32_t x, int32_t y) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_CURSOR_POSITION,
+                 kSetLayerCursorPositionLength);
+    writeSigned(x);
+    writeSigned(y);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerBufferLength = 3;
+  void setLayerBuffer(uint32_t slot, const native_handle_t* buffer, int acquireFence) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_BUFFER, kSetLayerBufferLength);
+    write(slot);
+    writeHandle(buffer, true);
+    writeFence(acquireFence);
+    endCommand();
+  }
+
+  void setLayerSurfaceDamage(const std::vector<IQtiComposerClient::Rect>& damage) {
+    bool doWrite = (damage.size() <= kMaxLength / 4);
+    size_t length = (doWrite) ? damage.size() * 4 : 0;
+
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_SURFACE_DAMAGE, length);
+    // When there are too many rectangles in the damage region and doWrite
+    // is false, we write no rectangle at all which means the entire
+    // layer is damaged.
+    if (doWrite) {
+      writeRegion(damage);
+    }
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerBlendModeLength = 1;
+  void setLayerBlendMode(IQtiComposerClient::BlendMode mode) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_BLEND_MODE, kSetLayerBlendModeLength);
+    writeSigned(static_cast<int32_t>(mode));
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerColorLength = 1;
+  void setLayerColor(IQtiComposerClient::Color color) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_COLOR, kSetLayerColorLength);
+    writeColor(color);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
+  void setLayerCompositionType(IQtiComposerClient::Composition type) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_COMPOSITION_TYPE,
+                 kSetLayerCompositionTypeLength);
+    writeSigned(static_cast<int32_t>(type));
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerDataspaceLength = 1;
+  void setLayerDataspace(Dataspace dataspace) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
+    writeSigned(static_cast<int32_t>(dataspace));
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
+  void setLayerDisplayFrame(const IQtiComposerClient::Rect& frame) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_DISPLAY_FRAME, kSetLayerDisplayFrameLength);
+    writeRect(frame);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
+  void setLayerPlaneAlpha(float alpha) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_PLANE_ALPHA, kSetLayerPlaneAlphaLength);
+    writeFloat(alpha);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
+  void setLayerSidebandStream(const native_handle_t* stream) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_SIDEBAND_STREAM,
+                 kSetLayerSidebandStreamLength);
+    writeHandle(stream);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerSourceCropLength = 4;
+  void setLayerSourceCrop(const IQtiComposerClient::FRect& crop) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_SOURCE_CROP, kSetLayerSourceCropLength);
+    writeFRect(crop);
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerTransformLength = 1;
+  void setLayerTransform(Transform transform) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_TRANSFORM, kSetLayerTransformLength);
+    writeSigned(static_cast<int32_t>(transform));
+    endCommand();
+  }
+
+  void setLayerVisibleRegion(const std::vector<IQtiComposerClient::Rect>& visible) {
+    bool doWrite = (visible.size() <= kMaxLength / 4);
+    size_t length = (doWrite) ? visible.size() * 4 : 0;
+
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_VISIBLE_REGION, length);
+    // When there are too many rectangles in the visible region and
+    // doWrite is false, we write no rectangle at all which means the
+    // entire layer is visible.
+    if (doWrite) {
+      writeRegion(visible);
+    }
+    endCommand();
+  }
+
+  static constexpr uint16_t kSetLayerZOrderLength = 1;
+  void setLayerZOrder(uint32_t z) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_Z_ORDER, kSetLayerZOrderLength);
+    write(z);
+    endCommand();
+  }
+
+  // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+  static constexpr uint16_t kSetLayerFloatColorLength = 4;
+  void setLayerFloatColor(IQtiComposerClient::FloatColor color) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_FLOAT_COLOR, kSetLayerFloatColorLength);
+    writeFloatColor(color);
+    endCommand();
+  }
+
+  void setLayerPerFrameMetadata(const hidl_vec<IQtiComposerClient::PerFrameMetadata>& metadataVec) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_PER_FRAME_METADATA,
+                 metadataVec.size() * 2);
+    for (const auto& metadata : metadataVec) {
+      writeSigned(static_cast<int32_t>(metadata.key));
+      writeFloat(metadata.value);
+    }
+    endCommand();
+  }
+
+  // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+  static constexpr uint16_t kSetLayerColorTransformLength = 16;
+  void setLayerColorTransform(const float* matrix) {
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_COLOR_TRANSFORM,
+                 kSetLayerColorTransformLength);
+    for (int i = 0; i < 16; i++) {
+      writeFloat(matrix[i]);
+    }
+    endCommand();
+  }
+
+  void setLayerPerFrameMetadataBlobs(
+    const hidl_vec<IQtiComposerClient::PerFrameMetadataBlob>& metadata) {
+    size_t commandLength = 0;
+
+    if (metadata.size() > std::numeric_limits<uint32_t>::max()) {
+      LOG_FATAL("too many metadata blobs - dynamic metadata size is too large");
+      return;
+    }
+
+    // number of blobs
+    commandLength += metadata.size();
+
+    for (auto metadataBlob : metadata) {
+      commandLength += sizeof(int32_t);  // key of metadata blob
+      commandLength += 1;                // size information of metadata blob
+
+      // metadata content size
+      size_t metadataSize = metadataBlob.blob.size() / sizeof(uint32_t);
+      commandLength += metadataSize;
+      commandLength += (metadataBlob.blob.size() - (metadataSize * sizeof(uint32_t)) > 0) ? 1 : 0;
+    }
+
+    if (commandLength > std::numeric_limits<uint16_t>::max()) {
+      LOG_FATAL("dynamic metadata size is too large");
+      return;
+    }
+
+    // Blobs are written as:
+    // {numElements, key1, size1, blob1, key2, size2, blob2, key3, size3...}
+    uint16_t length = static_cast<uint16_t>(commandLength);
+    beginCommand(IQtiComposerClient::Command::SET_LAYER_PER_FRAME_METADATA_BLOBS, length);
+    write(static_cast<uint32_t>(metadata.size()));
+    for (auto metadataBlob : metadata) {
+      writeSigned(static_cast<int32_t>(metadataBlob.key));
+      write(static_cast<uint32_t>(metadataBlob.blob.size()));
+      writeBlob(static_cast<uint32_t>(metadataBlob.blob.size()), metadataBlob.blob.data());
+    }
+    endCommand();
+  }
+
+ protected:
+  // Commands from ::android::hardware::graphics::composer::V2_1::IComposerClient follow.
+  void beginCommand(IQtiComposerClient::Command command, uint16_t length) {
+    if (mCommandEnd) {
+      LOG_FATAL("endCommand was not called before command 0x%x", command);
+    }
+
+    growData(1 + length);
+    write(static_cast<uint32_t>(command) | length);
+
+    mCommandEnd = mDataWritten + length;
+  }
+
+  void endCommand() {
+    if (!mCommandEnd) {
+      LOG_FATAL("beginCommand was not called");
+    } else if (mDataWritten > mCommandEnd) {
+      LOG_FATAL("too much data written");
+      mDataWritten = mCommandEnd;
+    } else if (mDataWritten < mCommandEnd) {
+      LOG_FATAL("too little data written");
+      while (mDataWritten < mCommandEnd) {
+        write(0);
+      }
+    }
+
+    mCommandEnd = 0;
+  }
+
+  void write(uint32_t val) { mData[mDataWritten++] = val; }
+
+  void writeSigned(int32_t val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
+
+  void writeFloat(float val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
+
+  void write64(uint64_t val) {
+    uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
+    uint32_t hi = static_cast<uint32_t>(val >> 32);
+    write(lo);
+    write(hi);
+  }
+
+  void writeRect(const IQtiComposerClient::Rect& rect) {
+    writeSigned(rect.left);
+    writeSigned(rect.top);
+    writeSigned(rect.right);
+    writeSigned(rect.bottom);
+  }
+
+  void writeRegion(const std::vector<IQtiComposerClient::Rect>& region) {
+    for (const auto& rect : region) {
+      writeRect(rect);
+    }
+  }
+
+  void writeFRect(const IQtiComposerClient::FRect& rect) {
+    writeFloat(rect.left);
+    writeFloat(rect.top);
+    writeFloat(rect.right);
+    writeFloat(rect.bottom);
+  }
+
+  void writeColor(const IQtiComposerClient::Color& color) {
+    write((color.r <<  0) | (color.g <<  8) | (color.b << 16) | (color.a << 24));
+  }
+
+  // ownership of handle is not transferred
+  void writeHandle(const native_handle_t* handle, bool useCache) {
+    if (!handle) {
+      writeSigned(static_cast<int32_t>((useCache) ?
+                IQtiComposerClient::HandleIndex::CACHED : IQtiComposerClient::HandleIndex::EMPTY));
+      return;
+    }
+
+    mDataHandles.push_back(handle);
+    writeSigned(mDataHandles.size() - 1);
+  }
+
+  void writeHandle(const native_handle_t* handle) {
+    writeHandle(handle, false);
+  }
+
+  // ownership of fence is transferred
+  void writeFence(int fence) {
+    native_handle_t* handle = nullptr;
+    if (fence >= 0) {
+      handle = getTemporaryHandle(1, 0);
+      if (handle) {
+        handle->data[0] = fence;
+      } else {
+        ALOGW("failed to get temporary handle for fence %d", fence);
+        sync_wait(fence, -1);
+        close(fence);
+      }
+    }
+
+    writeHandle(handle);
+  }
+
+  native_handle_t* getTemporaryHandle(int numFds, int numInts) {
+    native_handle_t* handle = native_handle_create(numFds, numInts);
+    if (handle) {
+      mTemporaryHandles.push_back(handle);
+    }
+    return handle;
+  }
+
+  static constexpr uint16_t kMaxLength = std::numeric_limits<uint16_t>::max();
+
+  // Commands from ::android::hardware::graphics::composer::V2_2::IComposerClient follow.
+  void writeFloatColor(const IQtiComposerClient::FloatColor& color) {
+    writeFloat(color.r);
+    writeFloat(color.g);
+    writeFloat(color.b);
+    writeFloat(color.a);
+  }
+
+  // Commands from ::android::hardware::graphics::composer::V2_3::IComposerClient follow.
+  void writeBlob(uint32_t length, const unsigned char* blob) {
+    memcpy(&mData[mDataWritten], blob, length);
+    uint32_t numElements = length / 4;
+    mDataWritten += numElements;
+    mDataWritten += (length - (numElements * 4) > 0) ? 1 : 0;
+  }
+
+ private:
+  void growData(uint32_t grow) {
+    uint32_t newWritten = mDataWritten + grow;
+    if (newWritten < mDataWritten) {
+      LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32
+                       ", growing by %" PRIu32, mDataWritten, grow);
+    }
+
+    if (newWritten <= mDataMaxSize) {
+      return;
+    }
+
+    uint32_t newMaxSize = mDataMaxSize << 1;
+    if (newMaxSize < newWritten) {
+      newMaxSize = newWritten;
+    }
+
+    auto newData = std::make_unique<uint32_t[]>(newMaxSize);
+    std::copy_n(mData.get(), mDataWritten, newData.get());
+    mDataMaxSize = newMaxSize;
+    mData = std::move(newData);
+  }
+
+  uint32_t mDataMaxSize;
+  std::unique_ptr<uint32_t[]> mData;
+
+  uint32_t mDataWritten;
+  // end offset of the current command
+  uint32_t mCommandEnd;
+
+  std::vector<hidl_handle> mDataHandles;
+  std::vector<native_handle_t *> mTemporaryHandles;
+
+  std::unique_ptr<CommandQueueType> mQueue;
+};
+
+// This class helps parse a command queue.  Note that all sizes/lengths are in units of uint32_t's.
+class CommandReaderBase {
+ public:
+  CommandReaderBase() : mDataMaxSize(0) { reset(); }
+
+  bool setMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+    mQueue = std::make_unique<CommandQueueType>(descriptor, false);
+    if (mQueue->isValid()) {
+      return true;
+    } else {
+      mQueue = nullptr;
+      return false;
+    }
+  }
+
+  bool readQueue(uint32_t commandLength, const hidl_vec<hidl_handle>& commandHandles) {
+    if (!mQueue) {
+      return false;
+    }
+
+    auto quantumCount = mQueue->getQuantumCount();
+    if (mDataMaxSize < quantumCount) {
+      mDataMaxSize = quantumCount;
+      mData = std::make_unique<uint32_t[]>(mDataMaxSize);
+    }
+
+    if (commandLength > mDataMaxSize || !mQueue->read(mData.get(), commandLength)) {
+      ALOGE("failed to read commands from message queue");
+      return false;
+    }
+
+    mDataSize = commandLength;
+    mDataRead = 0;
+    mCommandBegin = 0;
+    mCommandEnd = 0;
+    mDataHandles.setToExternal(const_cast<hidl_handle*>(commandHandles.data()),
+                               commandHandles.size());
+
+    return true;
+  }
+
+  void reset() {
+    mDataSize = 0;
+    mDataRead = 0;
+    mCommandBegin = 0;
+    mCommandEnd = 0;
+    mDataHandles.setToExternal(nullptr, 0);
+  }
+
+ protected:
+  bool isEmpty() const { return (mDataRead >= mDataSize); }
+
+  bool beginCommand(IQtiComposerClient::Command& command, uint16_t& length) {
+    if (mCommandEnd) {
+      LOG_FATAL("endCommand was not called before command 0x%x", command);
+    }
+
+    constexpr uint32_t opcode_mask =
+      static_cast<uint32_t>(IQtiComposerClient::Command::OPCODE_MASK);
+    constexpr uint32_t length_mask =
+      static_cast<uint32_t>(IQtiComposerClient::Command::LENGTH_MASK);
+
+    uint32_t val = read();
+    command = static_cast<IQtiComposerClient::Command>(val & opcode_mask);
+    length = static_cast<uint16_t>(val & length_mask);
+
+    if (mDataRead + length > mDataSize) {
+      ALOGE("command 0x%x has invalid command length %" PRIu16, command, length);
+      // undo the read() above
+      mDataRead--;
+      return false;
+    }
+
+    mCommandEnd = mDataRead + length;
+
+    return true;
+  }
+
+  void endCommand() {
+    if (!mCommandEnd) {
+      LOG_FATAL("beginCommand was not called");
+    } else if (mDataRead > mCommandEnd) {
+      LOG_FATAL("too much data read");
+      mDataRead = mCommandEnd;
+    } else if (mDataRead < mCommandEnd) {
+      LOG_FATAL("too little data read");
+      mDataRead = mCommandEnd;
+    }
+
+    mCommandBegin = mCommandEnd;
+    mCommandEnd = 0;
+  }
+
+  uint32_t getCommandLoc() const { return mCommandBegin; }
+
+  uint32_t read() { return mData[mDataRead++]; }
+
+  int32_t readSigned() {
+    int32_t val;
+    memcpy(&val, &mData[mDataRead++], sizeof(val));
+    return val;
+  }
+
+  float readFloat() {
+    float val;
+    memcpy(&val, &mData[mDataRead++], sizeof(val));
+    return val;
+  }
+
+  uint64_t read64() {
+    uint32_t lo = read();
+    uint32_t hi = read();
+    return (static_cast<uint64_t>(hi) << 32) | lo;
+  }
+
+  IQtiComposerClient::Color readColor() {
+    uint32_t val = read();
+    return IQtiComposerClient::Color{
+      static_cast<uint8_t>((val >>  0) & 0xff),
+      static_cast<uint8_t>((val >>  8) & 0xff),
+      static_cast<uint8_t>((val >> 16) & 0xff),
+      static_cast<uint8_t>((val >> 24) & 0xff),
+    };
+  }
+
+  // ownership of handle is not transferred
+  const native_handle_t* readHandle(bool& useCache) {
+    const native_handle_t* handle = nullptr;
+
+    int32_t index = readSigned();
+    switch (index) {
+    case static_cast<int32_t>(IQtiComposerClient::HandleIndex::EMPTY):
+      useCache = false;
+      break;
+    case static_cast<int32_t>(IQtiComposerClient::HandleIndex::CACHED):
+      useCache = true;
+      break;
+    default:
+      if (static_cast<size_t>(index) < mDataHandles.size()) {
+        handle = mDataHandles[index].getNativeHandle();
+      } else {
+        ALOGE("invalid handle index %zu", static_cast<size_t>(index));
+      }
+      useCache = false;
+      break;
+    }
+
+    return handle;
+  }
+
+  const native_handle_t* readHandle() {
+    bool useCache;
+    return readHandle(useCache);
+  }
+
+  // ownership of fence is transferred
+  int readFence() {
+    auto handle = readHandle();
+    if (!handle || handle->numFds == 0) {
+      return -1;
+    }
+
+    if (handle->numFds != 1) {
+      ALOGE("invalid fence handle with %d fds", handle->numFds);
+      return -1;
+    }
+
+    int fd = dup(handle->data[0]);
+    if (fd < 0) {
+      ALOGW("failed to dup fence %d", handle->data[0]);
+      sync_wait(handle->data[0], -1);
+      fd = -1;
+    }
+
+    return fd;
+  }
+
+ private:
+  std::unique_ptr<CommandQueueType> mQueue;
+  uint32_t mDataMaxSize;
+  std::unique_ptr<uint32_t[]> mData;
+
+  uint32_t mDataSize;
+  uint32_t mDataRead;
+
+  // begin/end offsets of the current command
+  uint32_t mCommandBegin;
+  uint32_t mCommandEnd;
+
+  hidl_vec<hidl_handle> mDataHandles;
+};
+
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
+#endif  // __QTICOMPOSERCOMMANDBUFFER_H__
diff --git a/composer/QtiComposerHandleImporter.cpp b/composer/QtiComposerHandleImporter.cpp
new file mode 100644
index 0000000..1518cbf
--- /dev/null
+++ b/composer/QtiComposerHandleImporter.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <log/log.h>
+
+#include "QtiComposerHandleImporter.h"
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+
+using MapperError = android::hardware::graphics::mapper::V2_0::Error;
+
+ComposerHandleImporter::ComposerHandleImporter() : mInitialized(false) {}
+
+void ComposerHandleImporter::initialize() {
+    // allow only one client
+  if (mInitialized) {
+    return;
+  }
+
+  mMapper = IMapper::getService();
+  if (mMapper == nullptr) {
+    ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
+    return;
+  }
+
+  mInitialized = true;
+  return;
+}
+
+void ComposerHandleImporter::cleanup() {
+  mMapper.clear();
+  mInitialized = false;
+}
+
+// In IComposer, any buffer_handle_t is owned by the caller and we need to
+// make a clone for hwcomposer2.  We also need to translate empty handle
+// to nullptr.  This function does that, in-place.
+bool ComposerHandleImporter::importBuffer(buffer_handle_t& handle) {
+  if (!handle) {
+    return true;
+  }
+
+  if (!handle->numFds && !handle->numInts) {
+    handle = nullptr;
+    return true;
+  }
+
+  Mutex::Autolock lock(mLock);
+  if (!mInitialized) {
+    initialize();
+  }
+
+  if (mMapper == nullptr) {
+    ALOGE("%s: mMapper is null!", __FUNCTION__);
+    return false;
+  }
+
+  MapperError error;
+  buffer_handle_t importedHandle;
+  auto ret = mMapper->importBuffer(
+    hidl_handle(handle),
+    [&](const auto& tmpError, const auto& tmpBufferHandle) {
+      error = tmpError;
+      importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
+    });
+
+  if (!ret.isOk()) {
+    ALOGE("%s: mapper importBuffer failed: %s", __FUNCTION__, ret.description().c_str());
+    return false;
+  }
+
+  if (error != MapperError::NONE) {
+    return false;
+  }
+
+  handle = importedHandle;
+
+  return true;
+}
+
+void ComposerHandleImporter::freeBuffer(buffer_handle_t handle) {
+  if (!handle) {
+    return;
+  }
+
+  Mutex::Autolock lock(mLock);
+  if (mMapper == nullptr) {
+    ALOGE("%s: mMapper is null!", __FUNCTION__);
+    return;
+  }
+
+  auto ret = mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
+  if (!ret.isOk()) {
+    ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
+  }
+}
+
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
diff --git a/composer/QtiComposerHandleImporter.h b/composer/QtiComposerHandleImporter.h
new file mode 100644
index 0000000..f110e68
--- /dev/null
+++ b/composer/QtiComposerHandleImporter.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __QTICOMPOSERHANDLEIMPORTER_H__
+#define __QTICOMPOSERHANDLEIMPORTER_H__
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <utils/Mutex.h>
+
+namespace vendor {
+namespace qti {
+namespace hardware {
+namespace display {
+namespace composer {
+namespace V1_0 {
+
+using ::android::hardware::graphics::mapper::V2_0::IMapper;
+using ::android::sp;
+using ::android::Mutex;
+using ::android::hardware::hidl_handle;
+
+class ComposerHandleImporter {
+ public:
+  ComposerHandleImporter();
+
+  // In IComposer, any buffer_handle_t is owned by the caller and we need to
+  // make a clone for hwcomposer2.  We also need to translate empty handle
+  // to nullptr.  This function does that, in-place.
+  bool importBuffer(buffer_handle_t& handle);
+  void freeBuffer(buffer_handle_t handle);
+  void initialize();
+  void cleanup();
+
+ private:
+  Mutex mLock;
+  bool mInitialized = false;
+  sp<IMapper> mMapper;
+};
+
+}  // namespace V1_0
+}  // namespace composer
+}  // namespace display
+}  // namespace hardware
+}  // namespace qti
+}  // namespace vendor
+
+#endif  // __QTICOMPOSERHANDLEIMPORTER_H__
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 2c840ff..3a3cbfd 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -51,22 +51,6 @@
 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
 #define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
 
-static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
-
-hwc_module_t HAL_MODULE_INFO_SYM = {
-  .common = {
-    .tag = HARDWARE_MODULE_TAG,
-    .version_major = 3,
-    .version_minor = 0,
-    .id = HWC_HARDWARE_MODULE_ID,
-    .name = "QTI Hardware Composer Module",
-    .author = "CodeAurora Forum",
-    .methods = &g_hwc_module_methods,
-    .dso = 0,
-    .reserved = {0},
-  }
-};
-
 namespace sdm {
 
 static HWCUEvent g_hwc_uevent_;
@@ -150,13 +134,13 @@
   uevent_listener_ = uevent_listener;
 }
 
-HWCSession::HWCSession(const hw_module_t *module) {
-  hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
-  hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
-  hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
-  hwc2_device_t::common.close = Close;
-  hwc2_device_t::getCapabilities = GetCapabilities;
-  hwc2_device_t::getFunction = GetFunction;
+HWCSession::HWCSession() {}
+
+HWCSession *HWCSession::GetInstance() {
+  // executed only once for the very first call.
+  // GetInstance called multiple times from Composer and ComposerClient
+  static HWCSession *hwc_session = new HWCSession();
+  return hwc_session;
 }
 
 int HWCSession::Init() {
@@ -353,47 +337,7 @@
   return INT(map_info->client_id);
 }
 
-int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
-  if (!module || !name || !device) {
-    DLOGE("Invalid parameters.");
-    return -EINVAL;
-  }
-
-  if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
-    HWCSession *hwc_session = new HWCSession(module);
-    if (!hwc_session) {
-      return -ENOMEM;
-    }
-
-    int status = hwc_session->Init();
-    if (status != 0) {
-      delete hwc_session;
-      hwc_session = NULL;
-      return status;
-    }
-
-    hwc2_device_t *composer_device = hwc_session;
-    *device = reinterpret_cast<hw_device_t *>(composer_device);
-  }
-
-  return 0;
-}
-
-int HWCSession::Close(hw_device_t *device) {
-  if (!device) {
-    return -EINVAL;
-  }
-
-  hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
-  HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
-
-  hwc_session->Deinit();
-
-  return 0;
-}
-
-void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
-                                 int32_t *outCapabilities) {
+void HWCSession::GetCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
   if (!outCount) {
     return;
   }
@@ -423,32 +367,28 @@
 // HWC2 functions returned in GetFunction
 // Defined in the same order as in the HWC2 header
 
-int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
+int32_t HWCSession::AcceptDisplayChanges(hwc2_display_t display) {
+  return CallDisplayFunction(display, &HWCDisplay::AcceptDisplayChanges);
 }
 
-int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
+int32_t HWCSession::CreateLayer(hwc2_display_t display,
                                 hwc2_layer_t *out_layer_id) {
   if (!out_layer_id) {
     return  HWC2_ERROR_BAD_PARAMETER;
   }
 
-  return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
+  return CallDisplayFunction(display, &HWCDisplay::CreateLayer, out_layer_id);
 }
 
-int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
-                                         int32_t *format, hwc2_display_t *out_display_id) {
+int32_t HWCSession::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format,
+                                         hwc2_display_t *out_display_id) {
   // TODO(user): Handle concurrency with HDMI
-  if (!device) {
-    return HWC2_ERROR_BAD_DISPLAY;
-  }
 
   if (!out_display_id || !width || !height || !format) {
     return  HWC2_ERROR_BAD_PARAMETER;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  auto status = hwc_session->CreateVirtualDisplayObj(width, height, format, out_display_id);
+  auto status = CreateVirtualDisplayObj(width, height, format, out_display_id);
   if (status == HWC2::Error::None) {
     DLOGI("Created virtual display id:% " PRIu64 ", res: %dx%d", *out_display_id, width, height);
   } else {
@@ -457,34 +397,32 @@
   return INT32(status);
 }
 
-int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
-                                 hwc2_layer_t layer) {
-  return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
+int32_t HWCSession::DestroyLayer(hwc2_display_t display, hwc2_layer_t layer) {
+  return CallDisplayFunction(display, &HWCDisplay::DestroyLayer, layer);
 }
 
-int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
-  if (!device || display >= HWCCallbacks::kNumDisplays) {
+int32_t HWCSession::DestroyVirtualDisplay(hwc2_display_t display) {
+  if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  auto *hwc_session = static_cast<HWCSession *>(device);
-  hwc2_display_t active_builtin_disp_id = hwc_session->GetActiveBuiltinDisplay();
+  hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
 
   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
     std::bitset<kSecureMax> secure_sessions = 0;
-    hwc_session->hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
+    hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
     if (secure_sessions.any()) {
       DLOGW("Secure session is active, defer destruction of virtual display id:%" PRIu64, display);
-      hwc_session->destroy_virtual_disp_pending_ = true;
+      destroy_virtual_disp_pending_ = true;
       return HWC2_ERROR_NONE;
     }
   }
 
-  for (auto &map_info : hwc_session->map_info_virtual_) {
+  for (auto &map_info : map_info_virtual_) {
     if (map_info.client_id == display) {
       DLOGI("Destroying virtual display id:%" PRIu64, display);
-      hwc_session->DestroyDisplay(&map_info);
+      DestroyDisplay(&map_info);
       break;
     }
   }
@@ -492,12 +430,11 @@
   return HWC2_ERROR_NONE;
 }
 
-void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
-  if (!device || !out_size) {
+void HWCSession::Dump(uint32_t *out_size, char *out_buffer) {
+  if (!out_size) {
     return;
   }
 
-  auto *hwc_session = static_cast<HWCSession *>(device);
   const size_t max_dump_size = 8192;
 
   if (out_buffer == nullptr) {
@@ -506,8 +443,8 @@
     std::string s {};
     for (int id = 0; id < HWCCallbacks::kNumDisplays; id++) {
       SCOPE_LOCK(locker_[id]);
-      if (hwc_session->hwc_display_[id]) {
-        s += hwc_session->hwc_display_[id]->Dump();
+      if (hwc_display_[id]) {
+        s += hwc_display_[id]->Dump();
       }
     }
     auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
@@ -515,49 +452,42 @@
   }
 }
 
-uint32_t HWCSession::GetMaxVirtualDisplayCount(hwc2_device_t *device) {
-  if (device == nullptr) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-
+uint32_t HWCSession::GetMaxVirtualDisplayCount() {
   return 1;
 }
 
-static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
-                               hwc2_config_t *out_config) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
+int32_t HWCSession::GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config) {
+  return CallDisplayFunction(display, &HWCDisplay::GetActiveConfig, out_config);
 }
 
-static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
-                                          uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-                                          int32_t *out_types) {
+int32_t HWCSession::GetChangedCompositionTypes(hwc2_display_t display, uint32_t *out_num_elements,
+                                               hwc2_layer_t *out_layers, int32_t *out_types) {
   // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
   if (!out_num_elements) {
     return  HWC2_ERROR_BAD_PARAMETER;
   }
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
-                                         out_num_elements, out_layers, out_types);
+  return CallDisplayFunction(display, &HWCDisplay::GetChangedCompositionTypes, out_num_elements,
+                             out_layers, out_types);
 }
 
-static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
-                                      uint32_t height, int32_t format, int32_t dataspace) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
-                                         width, height, format, dataspace);
+int32_t HWCSession::GetClientTargetSupport(hwc2_display_t display, uint32_t width, uint32_t height,
+                                           int32_t format, int32_t dataspace) {
+  return CallDisplayFunction(display, &HWCDisplay::GetClientTargetSupport, width, height, format,
+                             dataspace);
 }
 
-static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
-                             int32_t /*ColorMode*/ *int_out_modes) {
+int32_t HWCSession::GetColorModes(hwc2_display_t display, uint32_t *out_num_modes,
+                                  int32_t /*ColorMode*/ *int_out_modes) {
   auto out_modes = reinterpret_cast<ColorMode *>(int_out_modes);
   if (out_num_modes == nullptr) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
-                                         out_modes);
+  return CallDisplayFunction(display, &HWCDisplay::GetColorModes, out_num_modes, out_modes);
 }
 
-static int32_t GetRenderIntents(hwc2_device_t *device, hwc2_display_t display,
-                                int32_t /*ColorMode*/ int_mode, uint32_t *out_num_intents,
-                                int32_t /*RenderIntent*/ *int_out_intents) {
+int32_t HWCSession::GetRenderIntents(hwc2_display_t display, int32_t /*ColorMode*/ int_mode,
+                                     uint32_t *out_num_intents,
+                                     int32_t /*RenderIntent*/ *int_out_intents) {
   auto mode = static_cast<ColorMode>(int_mode);
   auto out_intents = reinterpret_cast<RenderIntent *>(int_out_intents);
   if (out_num_intents == nullptr) {
@@ -568,15 +498,14 @@
     DLOGE("Invalid ColorMode: %d", mode);
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetRenderIntents, mode,
-                                         out_num_intents, out_intents);
+  return CallDisplayFunction(display, &HWCDisplay::GetRenderIntents, mode, out_num_intents,
+                             out_intents);
 }
 
-static int32_t GetDataspaceSaturationMatrix(hwc2_device_t *device,
-                                            int32_t /*Dataspace*/ int_dataspace,
-                                            float *out_matrix) {
+int32_t HWCSession::GetDataspaceSaturationMatrix(int32_t /*Dataspace*/ int_dataspace,
+                                                 float *out_matrix) {
   auto dataspace = static_cast<Dataspace>(int_dataspace);
-  if (device == nullptr || out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
+  if (out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
   // We only have the matrix for sRGB
@@ -595,91 +524,82 @@
   return HWC2_ERROR_NONE;
 }
 
-static int32_t GetPerFrameMetadataKeys(hwc2_device_t *device, hwc2_display_t display,
-                                       uint32_t *out_num_keys, int32_t *int_out_keys) {
+int32_t HWCSession::GetPerFrameMetadataKeys(hwc2_display_t display, uint32_t *out_num_keys,
+                                            int32_t *int_out_keys) {
   auto out_keys = reinterpret_cast<PerFrameMetadataKey *>(int_out_keys);
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetPerFrameMetadataKeys,
-                                         out_num_keys, out_keys);
+  return CallDisplayFunction(display, &HWCDisplay::GetPerFrameMetadataKeys, out_num_keys,
+                             out_keys);
 }
 
-static int32_t SetLayerPerFrameMetadata(hwc2_device_t *device, hwc2_display_t display,
-                                        hwc2_layer_t layer, uint32_t num_elements,
-                                        const int32_t *int_keys, const float *metadata) {
+int32_t HWCSession::SetLayerPerFrameMetadata(hwc2_display_t display, hwc2_layer_t layer,
+                                             uint32_t num_elements, const int32_t *int_keys,
+                                             const float *metadata) {
   auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPerFrameMetadata,
-                                       num_elements, keys, metadata);
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadata, num_elements,
+                           keys, metadata);
 }
 
-static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
-                                   hwc2_config_t config, int32_t int_attribute,
-                                   int32_t *out_value) {
+int32_t HWCSession::GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+                                        int32_t int_attribute, int32_t *out_value) {
   if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
       int_attribute > HWC2_ATTRIBUTE_DPI_Y) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
   auto attribute = static_cast<HWC2::Attribute>(int_attribute);
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
-                                         attribute, out_value);
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayAttribute, config, attribute,
+                             out_value);
 }
 
-static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
-                                 uint32_t *out_num_configs, hwc2_config_t *out_configs) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
-                                         out_num_configs, out_configs);
+int32_t HWCSession::GetDisplayConfigs(hwc2_display_t display, uint32_t *out_num_configs,
+                                      hwc2_config_t *out_configs) {
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayConfigs, out_num_configs,
+                             out_configs);
 }
 
-static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
-                              char *out_name) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
-                                         out_name);
+int32_t HWCSession::GetDisplayName(hwc2_display_t display, uint32_t *out_size, char *out_name) {
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayName, out_size, out_name);
 }
 
-static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
-                                  int32_t *out_display_requests, uint32_t *out_num_elements,
-                                  hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
-                                         out_display_requests, out_num_elements, out_layers,
-                                         out_layer_requests);
+int32_t HWCSession::GetDisplayRequests(hwc2_display_t display, int32_t *out_display_requests,
+                                       uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                                       int32_t *out_layer_requests) {
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayRequests, out_display_requests,
+                             out_num_elements, out_layers, out_layer_requests);
 }
 
-static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
+int32_t HWCSession::GetDisplayType(hwc2_display_t display, int32_t *out_type) {
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayType, out_type);
 }
 
 
-static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
-                                  uint32_t* out_num_types, int32_t* out_types,
-                                  float* out_max_luminance, float* out_max_average_luminance,
-                                  float* out_min_luminance) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
-                                         out_num_types, out_types, out_max_luminance,
-                                         out_max_average_luminance, out_min_luminance);
+int32_t HWCSession::GetHdrCapabilities(hwc2_display_t display, uint32_t* out_num_types,
+                                       int32_t* out_types, float* out_max_luminance,
+                                       float* out_max_average_luminance,
+                                       float* out_min_luminance) {
+  return CallDisplayFunction(display, &HWCDisplay::GetHdrCapabilities, out_num_types, out_types,
+                             out_max_luminance, out_max_average_luminance, out_min_luminance);
 }
 
 
-static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
-                                uint32_t *out_num_elements, hwc2_layer_t *out_layers,
-                                int32_t *out_fences) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
-                                         out_num_elements, out_layers, out_fences);
+int32_t HWCSession::GetReleaseFences(hwc2_display_t display, uint32_t *out_num_elements,
+                                     hwc2_layer_t *out_layers, int32_t *out_fences) {
+  return CallDisplayFunction(display, &HWCDisplay::GetReleaseFences, out_num_elements, out_layers,
+                             out_fences);
 }
 
-int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
-                                   int32_t *out_retire_fence) {
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+int32_t HWCSession::PresentDisplay(hwc2_display_t display, int32_t *out_retire_fence) {
   auto status = HWC2::Error::BadDisplay;
   DTRACE_SCOPED();
 
-  if (!hwc_session || (display >= HWCCallbacks::kNumDisplays)) {
-    DLOGW("Invalid Display : hwc session = %s display = %" PRIu64,
-          hwc_session ? "Valid" : "NULL", display);
+  if (display >= HWCCallbacks::kNumDisplays) {
+    DLOGW("Invalid Display : display = %" PRIu64, display);
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  hwc_session->HandleSecureSession();
+  HandleSecureSession();
   {
     SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
-    if (!hwc_session->hwc_display_[display]) {
+    if (!hwc_display_[display]) {
       DLOGW("Removed Display : display = %" PRIu64, display);
       return HWC2_ERROR_BAD_DISPLAY;
     }
@@ -691,14 +611,14 @@
     if (power_on_pending_[display]) {
       status = HWC2::Error::None;
     } else {
-      status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
+      status = PresentDisplayInternal(display, out_retire_fence);
       if (status == HWC2::Error::None) {
         // Check if hwc's refresh trigger is getting exercised.
-        if (hwc_session->callbacks_.NeedsRefresh(display)) {
-          hwc_session->hwc_display_[display]->SetPendingRefresh();
-          hwc_session->callbacks_.ResetRefresh(display);
+        if (callbacks_.NeedsRefresh(display)) {
+          hwc_display_[display]->SetPendingRefresh();
+          callbacks_.ResetRefresh(display);
         }
-        status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
+        status = hwc_display_[display]->Present(out_retire_fence);
       }
     }
   }
@@ -707,9 +627,9 @@
     SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
   }
 
-  hwc_session->HandlePowerOnPending(display, *out_retire_fence);
-  hwc_session->HandleHotplugPending(display, *out_retire_fence);
-  hwc_session->HandlePendingRefresh();
+  HandlePowerOnPending(display, *out_retire_fence);
+  HandleHotplugPending(display, *out_retire_fence);
+  HandlePendingRefresh();
 
   return INT32(status);
 }
@@ -729,67 +649,59 @@
   pending_refresh_.reset();
 }
 
-int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
-                                     hwc2_callback_data_t callback_data,
-                                     hwc2_function_pointer_t pointer) {
-  if (!device) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  SCOPE_LOCK(hwc_session->callbacks_lock_);
+void HWCSession::RegisterCallback(int32_t descriptor, hwc2_callback_data_t callback_data,
+                                  hwc2_function_pointer_t pointer) {
+  SCOPE_LOCK(callbacks_lock_);
   auto desc = static_cast<HWC2::Callback>(descriptor);
-  auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
+  auto error = callbacks_.Register(desc, callback_data, pointer);
   if (error != HWC2::Error::None) {
-    return INT32(error);
+    return;
   }
 
   DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
   if (descriptor == HWC2_CALLBACK_HOTPLUG) {
-    if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
       DLOGI("Hotplugging primary...");
-      hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
+      callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
     }
     // Create displays since they should now have their final display indices set.
     DLOGI("Handling built-in displays...");
-    if (hwc_session->HandleBuiltInDisplays()) {
+    if (HandleBuiltInDisplays()) {
       DLOGW("Failed handling built-in displays.");
     }
     DLOGI("Handling pluggable displays...");
-    int32_t err = hwc_session->HandlePluggableDisplays(false);
+    int32_t err = HandlePluggableDisplays(false);
     if (err) {
       DLOGW("All displays could not be created. Error %d '%s'. Hotplug handling %s.", err,
-            strerror(abs(err)), hwc_session->hotplug_pending_event_ == kHotPlugEvent ? "deferred" :
+            strerror(abs(err)), hotplug_pending_event_ == kHotPlugEvent ? "deferred" :
             "dropped");
     }
-    hwc_session->client_connected_ = true;
+    client_connected_ = true;
   }
-  hwc_session->need_invalidate_ = false;
-  hwc_session->callbacks_lock_.Broadcast();
-  return HWC2_ERROR_NONE;
+  need_invalidate_ = false;
+  callbacks_lock_.Broadcast();
 }
 
-static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
-                               hwc2_config_t config) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
+int32_t HWCSession::SetActiveConfig(hwc2_display_t display, hwc2_config_t config) {
+  return CallDisplayFunction(display, &HWCDisplay::SetActiveConfig, config);
 }
 
-static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
-                               buffer_handle_t target, int32_t acquire_fence,
-                               int32_t dataspace, hwc_region_t damage) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
-                                         acquire_fence, dataspace, damage);
+int32_t HWCSession::SetClientTarget(hwc2_display_t display, buffer_handle_t target,
+                                    int32_t acquire_fence, int32_t dataspace,
+                                    hwc_region_t damage) {
+  return CallDisplayFunction(display, &HWCDisplay::SetClientTarget, target, acquire_fence,
+                             dataspace, damage);
 }
 
-int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
-                                 int32_t /*ColorMode*/ int_mode) {
+int32_t HWCSession::SetColorMode(hwc2_display_t display, int32_t /*ColorMode*/ int_mode) {
   auto mode = static_cast<ColorMode>(int_mode);
   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
+  return CallDisplayFunction(display, &HWCDisplay::SetColorMode, mode);
 }
 
-int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_display_t display,
+int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_display_t display,
                                                  int32_t /*ColorMode*/ int_mode,
                                                  int32_t /*RenderIntent*/ int_render_intent) {
   auto mode = static_cast<ColorMode>(int_mode);
@@ -803,128 +715,108 @@
   }
 
   auto render_intent = static_cast<RenderIntent>(int_render_intent);
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent,
-                                         mode, render_intent);
+  return CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode,
+                             render_intent);
 }
 
-int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
-                                      const float *matrix,
+int32_t HWCSession::SetColorTransform(hwc2_display_t display, const float *matrix,
                                       int32_t /*android_color_transform_t*/ hint) {
   if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
        hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
   android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
-                                         transform_hint);
+  return CallDisplayFunction(display, &HWCDisplay::SetColorTransform, matrix, transform_hint);
 }
 
-static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                 int32_t x, int32_t y) {
+int32_t HWCSession::SetCursorPosition(hwc2_display_t display, hwc2_layer_t layer, int32_t x,
+                                      int32_t y) {
   auto status = INT32(HWC2::Error::None);
-  status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
-                                           layer, x, y);
+  status = CallDisplayFunction(display, &HWCDisplay::SetCursorPosition, layer, x, y);
   if (status == INT32(HWC2::Error::None)) {
     // Update cursor position
-    HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
+    CallLayerFunction(display, layer, &HWCLayer::SetCursorPosition, x, y);
   }
   return status;
 }
 
-static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                 int32_t int_mode) {
+int32_t HWCSession::SetLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
+                                      int32_t int_mode) {
   if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
   auto mode = static_cast<HWC2::BlendMode>(int_mode);
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerBlendMode, mode);
 }
 
-static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                              buffer_handle_t buffer, int32_t acquire_fence) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
-                                       acquire_fence);
+int32_t HWCSession::SetLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
+                                   buffer_handle_t buffer, int32_t acquire_fence) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerBuffer, buffer, acquire_fence);
 }
 
-static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                             hwc_color_t color) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
+int32_t HWCSession::SetLayerColor(hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerColor, color);
 }
 
-static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
-                                       hwc2_layer_t layer, int32_t int_type) {
+int32_t HWCSession::SetLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
+                                            int32_t int_type) {
   auto type = static_cast<HWC2::Composition>(int_type);
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
-                                       type);
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerCompositionType, type);
 }
 
-static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                 int32_t dataspace) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
-                                       dataspace);
+int32_t HWCSession::SetLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
+                                      int32_t dataspace) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerDataspace, dataspace);
 }
 
-static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
-                                    hwc2_layer_t layer, hwc_rect_t frame) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
-                                       frame);
+int32_t HWCSession::SetLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
+                                         hwc_rect_t frame) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerDisplayFrame, frame);
 }
 
-static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                  float alpha) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
-                                       alpha);
+int32_t HWCSession::SetLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, float alpha) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerPlaneAlpha, alpha);
 }
 
-static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                  hwc_frect_t crop) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
+int32_t HWCSession::SetLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
+                                       hwc_frect_t crop) {
+  return HWCSession::CallLayerFunction(display, layer, &HWCLayer::SetLayerSourceCrop, crop);
 }
 
-static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
-                                     hwc2_layer_t layer, hwc_region_t damage) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
-                                       damage);
+int32_t HWCSession::SetLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
+                                          hwc_region_t damage) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerSurfaceDamage, damage);
 }
 
-static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                                 int32_t int_transform) {
+int32_t HWCSession::SetLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
+                                      int32_t int_transform) {
   auto transform = static_cast<HWC2::Transform>(int_transform);
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
-                                       transform);
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerTransform, transform);
 }
 
-static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
-                                     hwc2_layer_t layer, hwc_region_t visible) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
-                                       visible);
+int32_t HWCSession::SetLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
+                                          hwc_region_t visible) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerVisibleRegion, visible);
 }
 
-static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
-                              uint32_t z) {
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
+int32_t HWCSession::SetLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+  return CallDisplayFunction(display, &HWCDisplay::SetLayerZOrder, layer, z);
 }
 
-static int32_t SetLayerColorTransform(hwc2_device_t *device, hwc2_display_t display,
-                                      hwc2_layer_t layer, const float *matrix) {
-  return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColorTransform,
-                                       matrix);
+int32_t HWCSession::SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer,
+                                           const float *matrix) {
+  return CallLayerFunction(display, layer, &HWCLayer::SetLayerColorTransform, matrix);
 }
 
-int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
-                                    buffer_handle_t buffer, int32_t releaseFence) {
-  if (!device) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-
-  auto *hwc_session = static_cast<HWCSession *>(device);
-  if (INT32(display) != hwc_session->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
+int32_t HWCSession::SetOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
+                                    int32_t releaseFence) {
+  if (INT32(display) != GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
     return HWC2_ERROR_UNSUPPORTED;
   }
 
   SCOPE_LOCK(locker_[display]);
-  if (hwc_session->hwc_display_[display]) {
-    auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
+  if (hwc_display_[display]) {
+    auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_display_[display]);
     auto status = vds->SetOutputBuffer(buffer, releaseFence);
     return INT32(status);
   } else {
@@ -932,18 +824,17 @@
   }
 }
 
-int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
+int32_t HWCSession::SetPowerMode(hwc2_display_t display, int32_t int_mode) {
   if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
   //  validate device and also avoid undefined behavior in cast to HWC2::PowerMode
-  if (!device || int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
+  if (int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  if (hwc_session->power_on_pending_[display]) {
+  if (power_on_pending_[display]) {
     DLOGW("Set power mode is not allowed during secure display session");
     return HWC2_ERROR_UNSUPPORTED;
   }
@@ -952,7 +843,7 @@
 
   //  all displays support on/off. Check for doze modes
   int support = 0;
-  auto status = hwc_session->GetDozeSupport(device, display, &support);
+  auto status = GetDozeSupport(display, &support);
   if (status != HWC2_ERROR_NONE) {
     DLOGE("Failed to get doze support Error = %d", status);
     return INT32(status);
@@ -962,30 +853,29 @@
     return HWC2_ERROR_UNSUPPORTED;
   }
 
-  auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode,
-                                   false /* teardown */);
-  if (error != HWC2_ERROR_NONE) {
-    return error;
+  auto error = CallDisplayFunction(display, &HWCDisplay::SetPowerMode, mode, false /* teardown */);
+  if (INT32(error) != HWC2_ERROR_NONE) {
+    return INT32(error);
   }
   // Reset idle pc ref count on suspend, as we enable idle pc during suspend.
   if (mode == HWC2::PowerMode::Off) {
-    hwc_session->idle_pc_ref_cnt_ = 0;
+    idle_pc_ref_cnt_ = 0;
   }
 
-  hwc_session->UpdateThrottlingRate();
+
+  UpdateThrottlingRate();
 
   // Trigger refresh for doze mode to take effect.
   if (mode == HWC2::PowerMode::Doze) {
-    hwc_session->Refresh(display);
+    Refresh(display);
     // Trigger one more refresh for PP features to take effect.
-    hwc_session->pending_refresh_.set(UINT32(display));
+    pending_refresh_.set(UINT32(display));
   }
 
   return HWC2_ERROR_NONE;
 }
 
-int32_t HWCSession::SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
-                                    int32_t int_enabled) {
+int32_t HWCSession::SetVsyncEnabled(hwc2_display_t display, int32_t int_enabled) {
   //  avoid undefined behavior in cast to HWC2::Vsync
   if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
     return HWC2_ERROR_BAD_PARAMETER;
@@ -993,59 +883,50 @@
 
   auto enabled = static_cast<HWC2::Vsync>(int_enabled);
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-
   if (int_enabled == HWC2_VSYNC_ENABLE) {
-    hwc_session->callbacks_.UpdateVsyncSource(display);
+    callbacks_.UpdateVsyncSource(display);
   }
 
-  return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
+  return CallDisplayFunction(display, &HWCDisplay::SetVsyncEnabled, enabled);
 }
 
-int32_t HWCSession::GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
-                                   int32_t *out_support) {
-  if (!device || !out_support) {
+int32_t HWCSession::GetDozeSupport(hwc2_display_t display, int32_t *out_support) {
+  if (!out_support) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];;
-  if (display >= HWCCallbacks::kNumDisplays || (hwc_display == nullptr)) {
-    DLOGE("Invalid Display %d Handle %s ", display, hwc_display ?
+  if (display >= HWCCallbacks::kNumDisplays || (hwc_display_[display] == nullptr)) {
+    DLOGE("Invalid Display %d Handle %s ", display, hwc_display_[display] ?
           "Valid" : "NULL");
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
   *out_support = 0;
-  if (hwc_display->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
+  if (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
     *out_support = 1;
   }
 
   return HWC2_ERROR_NONE;
 }
 
-int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
-                                    uint32_t *out_num_types, uint32_t *out_num_requests) {
+int32_t HWCSession::ValidateDisplay(hwc2_display_t display, uint32_t *out_num_types,
+                                    uint32_t *out_num_requests) {
   //  out_num_types and out_num_requests will be non-NULL
-  if (!device) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
 
   if (display >= HWCCallbacks::kNumDisplays) {
     return HWC2_ERROR_BAD_DISPLAY;
   }
   DTRACE_SCOPED();
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
   // TODO(user): Handle secure session, handle QDCM solid fill
   auto status = HWC2::Error::BadDisplay;
-  hwc_session->HandleSecureSession();
+  HandleSecureSession();
   {
     SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
     if (power_on_pending_[display]) {
       status = HWC2::Error::None;
-    } else if (hwc_session->hwc_display_[display]) {
-      hwc_session->hwc_display_[display]->SetFastPathComposition(false);
-      status = hwc_session->ValidateDisplayInternal(display, out_num_types, out_num_requests);
+    } else if (hwc_display_[display]) {
+      hwc_display_[display]->SetFastPathComposition(false);
+      status = ValidateDisplayInternal(display, out_num_types, out_num_requests);
     }
   }
 
@@ -1057,133 +938,6 @@
   return INT32(status);
 }
 
-hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
-                                                int32_t int_descriptor) {
-  auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
-
-  switch (descriptor) {
-    case HWC2::FunctionDescriptor::AcceptDisplayChanges:
-      return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
-    case HWC2::FunctionDescriptor::CreateLayer:
-      return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
-    case HWC2::FunctionDescriptor::CreateVirtualDisplay:
-      return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
-    case HWC2::FunctionDescriptor::DestroyLayer:
-      return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
-    case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
-      return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
-    case HWC2::FunctionDescriptor::Dump:
-      return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
-    case HWC2::FunctionDescriptor::GetActiveConfig:
-      return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
-    case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
-      return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
-    case HWC2::FunctionDescriptor::GetClientTargetSupport:
-      return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
-    case HWC2::FunctionDescriptor::GetColorModes:
-      return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
-    case HWC2::FunctionDescriptor::GetDisplayAttribute:
-      return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
-    case HWC2::FunctionDescriptor::GetDisplayConfigs:
-      return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
-    case HWC2::FunctionDescriptor::GetDisplayName:
-      return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
-    case HWC2::FunctionDescriptor::GetDisplayRequests:
-      return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
-    case HWC2::FunctionDescriptor::GetDisplayType:
-      return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
-    case HWC2::FunctionDescriptor::GetHdrCapabilities:
-      return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
-    case HWC2::FunctionDescriptor::GetDozeSupport:
-      return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
-    case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
-      return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(HWCSession::GetMaxVirtualDisplayCount);
-    case HWC2::FunctionDescriptor::GetReleaseFences:
-      return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
-    case HWC2::FunctionDescriptor::PresentDisplay:
-      return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
-    case HWC2::FunctionDescriptor::RegisterCallback:
-      return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
-    case HWC2::FunctionDescriptor::SetActiveConfig:
-      return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
-    case HWC2::FunctionDescriptor::SetClientTarget:
-      return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
-    case HWC2::FunctionDescriptor::SetColorMode:
-      return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
-    case HWC2::FunctionDescriptor::SetColorTransform:
-      return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
-    case HWC2::FunctionDescriptor::SetCursorPosition:
-      return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
-    case HWC2::FunctionDescriptor::SetLayerBlendMode:
-      return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
-    case HWC2::FunctionDescriptor::SetLayerBuffer:
-      return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
-    case HWC2::FunctionDescriptor::SetLayerColor:
-      return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
-    case HWC2::FunctionDescriptor::SetLayerCompositionType:
-      return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
-    case HWC2::FunctionDescriptor::SetLayerDataspace:
-      return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
-    case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
-      return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
-    case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
-      return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
-    // Sideband stream is not supported
-    // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
-    case HWC2::FunctionDescriptor::SetLayerSourceCrop:
-      return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
-    case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
-      return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
-    case HWC2::FunctionDescriptor::SetLayerTransform:
-      return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
-    case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
-      return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
-    case HWC2::FunctionDescriptor::SetLayerZOrder:
-      return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
-    case HWC2::FunctionDescriptor::SetOutputBuffer:
-      return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
-    case HWC2::FunctionDescriptor::SetPowerMode:
-      return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
-    case HWC2::FunctionDescriptor::SetVsyncEnabled:
-      return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
-    case HWC2::FunctionDescriptor::ValidateDisplay:
-      return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
-    case HWC2::FunctionDescriptor::SetReadbackBuffer:
-      return AsFP<HWC2_PFN_SET_READBACK_BUFFER>(HWCSession::SetReadbackBuffer);
-    case HWC2::FunctionDescriptor::GetReadbackBufferAttributes:
-      return AsFP<HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES>(HWCSession::GetReadbackBufferAttributes);
-    case HWC2::FunctionDescriptor::GetReadbackBufferFence:
-      return AsFP<HWC2_PFN_GET_READBACK_BUFFER_FENCE>(HWCSession::GetReadbackBufferFence);
-    case HWC2::FunctionDescriptor::GetRenderIntents:
-      return AsFP<HWC2_PFN_GET_RENDER_INTENTS>(GetRenderIntents);
-    case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
-      return AsFP<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>
-             (HWCSession::SetColorModeWithRenderIntent);
-    case HWC2::FunctionDescriptor::GetDataspaceSaturationMatrix:
-      return AsFP<HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX>(GetDataspaceSaturationMatrix);
-    case HWC2::FunctionDescriptor::GetPerFrameMetadataKeys:
-      return AsFP<HWC2_PFN_GET_PER_FRAME_METADATA_KEYS>(GetPerFrameMetadataKeys);
-    case HWC2::FunctionDescriptor::SetLayerPerFrameMetadata:
-      return AsFP<HWC2_PFN_SET_LAYER_PER_FRAME_METADATA>(SetLayerPerFrameMetadata);
-    case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
-      return AsFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>
-             (HWCSession::GetDisplayIdentificationData);
-    case HWC2::FunctionDescriptor::SetLayerColorTransform:
-      return AsFP<HWC2_PFN_SET_LAYER_COLOR_TRANSFORM>(SetLayerColorTransform);
-    case HWC2::FunctionDescriptor::GetDisplayCapabilities:
-      return AsFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(HWCSession::GetDisplayCapabilities);
-    case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport:
-      return AsFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(HWCSession::GetDisplayBrightnessSupport);
-    case HWC2::FunctionDescriptor::SetDisplayBrightness:
-      return AsFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(HWCSession::SetDisplayBrightness);
-    default:
-      DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
-            to_string(descriptor).c_str());
-      return nullptr;
-  }
-  return nullptr;
-}
-
 HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
                                                 hwc2_display_t *out_display_id) {
   if (!client_connected_) {
@@ -1457,11 +1211,10 @@
           break;
         }
         int level = input_parcel->readInt32();
-        hwc2_device_t *device = static_cast<hwc2_device_t *>(this);
         if (level == 0) {
-          status = SetDisplayBrightness(device, HWC_DISPLAY_PRIMARY, -1.0f);
+          status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f);
         } else {
-          status = SetDisplayBrightness(device, HWC_DISPLAY_PRIMARY, (level - 1)/254.0f);
+          status = SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f);
         }
         output_parcel->writeInt32(status);
       }
@@ -1795,7 +1548,6 @@
 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
   int display = static_cast<int>(input_parcel->readInt32());
   auto mode = static_cast<ColorMode>(input_parcel->readInt32());
-  auto device = static_cast<hwc2_device_t *>(this);
 
   int disp_idx = GetDisplayIndex(display);
   if (disp_idx == -1) {
@@ -1807,8 +1559,8 @@
     DLOGE("Invalid ColorMode: %d", mode);
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
-                                 &HWCDisplay::SetColorMode, mode);
+  auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx), &HWCDisplay::SetColorMode,
+                                 mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
@@ -1828,9 +1580,8 @@
   return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
                                                             v_e, f_in, f_out));
 #else
-  auto err = CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
-                                 &HWCDisplay::SetDisplayDppsAdROI, h_s, h_e, v_s, v_e,
-                                 f_in, f_out);
+  auto err = CallDisplayFunction(display_id, &HWCDisplay::SetDisplayDppsAdROI,
+                                 h_s, h_e, v_s, v_e, f_in, f_out);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
@@ -1848,8 +1599,7 @@
     return -EINVAL;
   }
 
-  auto err = CallDisplayFunction(static_cast<hwc2_device_t *>(this),
-                                 static_cast<hwc2_display_t>(disp_idx),
+  auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
                                  &HWCDisplay::SetFrameTriggerMode, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -1862,7 +1612,6 @@
   auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
   auto mode = static_cast<ColorMode>(input_parcel->readInt32());
   auto int_intent = static_cast<int>(input_parcel->readInt32());
-  auto device = static_cast<hwc2_device_t *>(this);
 
   if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
     DLOGE("Invalid ColorMode: %d", mode);
@@ -1876,7 +1625,7 @@
 
   auto intent = static_cast<RenderIntent>(int_intent);
   auto err =
-      CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
+      CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
 
@@ -1885,7 +1634,6 @@
 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
   int display = input_parcel->readInt32();
   auto mode = input_parcel->readInt32();
-  auto device = static_cast<hwc2_device_t *>(this);
 
   int disp_idx = GetDisplayIndex(display);
   if (disp_idx == -1) {
@@ -1893,7 +1641,7 @@
     return -EINVAL;
   }
 
-  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+  auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
                                  &HWCDisplay::SetColorModeById, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -1904,7 +1652,6 @@
 android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
   int display = input_parcel->readInt32();
   auto mode = input_parcel->readInt32();
-  auto device = static_cast<hwc2_device_t *>(this);
 
   int disp_idx = GetDisplayIndex(display);
   if (disp_idx == -1) {
@@ -1912,7 +1659,7 @@
     return -EINVAL;
   }
 
-  auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
+  auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
                                  &HWCDisplay::SetColorModeFromClientApi, mode);
   if (err != HWC2_ERROR_NONE)
     return -EINVAL;
@@ -2017,9 +1764,7 @@
     return ret;
   }
 
-  ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload,
-                                                       resp_payload,
-                                                       pending_action);
+  ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, resp_payload, pending_action);
 
   return ret;
 }
@@ -2105,13 +1850,11 @@
           if (brightness == NULL) {
             DLOGE("Brightness payload is Null");
           } else {
-            ret = INT(SetDisplayBrightness(static_cast<hwc2_device_t *>(this),
-                      static_cast<hwc2_display_t>(display_id), *brightness));
+            ret = INT(SetDisplayBrightness(static_cast<hwc2_display_t>(display_id), *brightness));
           }
           break;
         case kEnableFrameCapture:
-          ret = color_mgr_->SetFrameCapture(pending_action.params, true,
-                                            hwc_display_[display_id]);
+          ret = color_mgr_->SetFrameCapture(pending_action.params, true, hwc_display_[display_id]);
           Refresh(display_id);
           break;
         case kDisableFrameCapture:
@@ -2119,8 +1862,7 @@
                                             hwc_display_[display_id]);
           break;
         case kConfigureDetailedEnhancer:
-          ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
-                                                hwc_display_[display_id]);
+          ret = color_mgr_->SetDetailedEnhancer(pending_action.params, hwc_display_[display_id]);
           Refresh(display_id);
           break;
         case kModeSet:
@@ -2136,8 +1878,7 @@
             if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
               int result = 0;
               resp_payload.DestroyPayload();
-              result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
-                                                              &resp_payload,
+              result = hwc_display_[id]->ColorSVCRequestRoute(req_payload, &resp_payload,
                                                               &pending_action);
               if (result) {
                 DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
@@ -3013,9 +2754,9 @@
   }
 }
 
-int32_t HWCSession::GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
-                                                int32_t *format, int32_t *dataspace) {
-  if (!device || !format || !dataspace) {
+int32_t HWCSession::GetReadbackBufferAttributes(hwc2_display_t display, int32_t *format,
+                                                int32_t *dataspace) {
+  if (!format || !dataspace) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
@@ -3023,8 +2764,7 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
+  HWCDisplay *hwc_display = hwc_display_[display];
 
   if (hwc_display) {
     *format = HAL_PIXEL_FORMAT_RGB_888;
@@ -3035,8 +2775,8 @@
   return HWC2_ERROR_BAD_DISPLAY;
 }
 
-int32_t HWCSession::SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,
-                                      const native_handle_t *buffer, int32_t acquire_fence) {
+int32_t HWCSession::SetReadbackBuffer(hwc2_display_t display, const native_handle_t *buffer,
+                                      int32_t acquire_fence) {
   if (!buffer) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
@@ -3045,18 +2785,16 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] ||
-      hwc_session->hwc_display_[qdutils::DISPLAY_VIRTUAL]) {
+  if (hwc_display_[HWC_DISPLAY_EXTERNAL] ||
+      hwc_display_[qdutils::DISPLAY_VIRTUAL]) {
     return HWC2_ERROR_UNSUPPORTED;
   }
 
-  return CallDisplayFunction(device, display, &HWCDisplay::SetReadbackBuffer,
-                             buffer, acquire_fence, false);
+  return CallDisplayFunction(display, &HWCDisplay::SetReadbackBuffer, buffer, acquire_fence,
+                             false);
 }
 
-int32_t HWCSession::GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
-                                           int32_t *release_fence) {
+int32_t HWCSession::GetReadbackBufferFence(hwc2_display_t display, int32_t *release_fence) {
   if (!release_fence) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
@@ -3065,12 +2803,11 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  return CallDisplayFunction(device, display, &HWCDisplay::GetReadbackBufferFence, release_fence);
+  return CallDisplayFunction(display, &HWCDisplay::GetReadbackBufferFence, release_fence);
 }
 
-int32_t HWCSession::GetDisplayIdentificationData(hwc2_device_t *device, hwc2_display_t display,
-                                                 uint8_t *outPort, uint32_t *outDataSize,
-                                                 uint8_t *outData) {
+int32_t HWCSession::GetDisplayIdentificationData(hwc2_display_t display, uint8_t *outPort,
+                                                 uint32_t *outDataSize, uint8_t *outData) {
   if (!outPort || !outDataSize) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
@@ -3079,14 +2816,13 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  return CallDisplayFunction(device, display, &HWCDisplay::GetDisplayIdentificationData, outPort,
+  return CallDisplayFunction(display, &HWCDisplay::GetDisplayIdentificationData, outPort,
                              outDataSize, outData);
 }
 
-int32_t HWCSession::GetDisplayCapabilities(hwc2_device_t *device, hwc2_display_t display,
-                                           uint32_t *outNumCapabilities,
+int32_t HWCSession::GetDisplayCapabilities(hwc2_display_t display, uint32_t *outNumCapabilities,
                                            uint32_t *outCapabilities) {
-  if (!outNumCapabilities || !device) {
+  if (!outNumCapabilities) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
@@ -3094,13 +2830,11 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
-  if (!hwc_display) {
+  if (!hwc_display_[display]) {
     DLOGE("Expected valid hwc_display");
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  bool isBuiltin = (hwc_display->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
+  bool isBuiltin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
   if (!outCapabilities) {
     *outNumCapabilities = 0;
     if (isBuiltin) {
@@ -3119,9 +2853,8 @@
   }
 }
 
-int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_device_t *device, hwc2_display_t display,
-                                                bool *outSupport) {
-  if (!device || !outSupport) {
+int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_display_t display, bool *outSupport) {
+  if (!outSupport) {
     return HWC2_ERROR_BAD_PARAMETER;
   }
 
@@ -3129,24 +2862,20 @@
     return HWC2_ERROR_BAD_DISPLAY;
   }
 
-  HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
-  if (!hwc_display) {
+  if (!hwc_display_[display]) {
     DLOGE("Expected valid hwc_display");
     return HWC2_ERROR_BAD_PARAMETER;
   }
-  *outSupport = (hwc_display->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
+  *outSupport = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
   return HWC2_ERROR_NONE;
 }
 
-int32_t HWCSession::SetDisplayBrightness(hwc2_device_t *device, hwc2_display_t display,
-                                         float brightness) {
-  return CallDisplayFunction(device, display, &HWCDisplay::SetPanelBrightness, brightness);
+int32_t HWCSession::SetDisplayBrightness(hwc2_display_t display, float brightness) {
+  return CallDisplayFunction(display, &HWCDisplay::SetPanelBrightness, brightness);
 }
 
 android::status_t HWCSession::SetQSyncMode(const android::Parcel *input_parcel) {
   auto mode = input_parcel->readInt32();
-  auto device = static_cast<hwc2_device_t *>(this);
 
   QSyncMode qsync_mode = kQSyncModeNone;
   switch (mode) {
@@ -3163,7 +2892,7 @@
       DLOGE("Qsync mode not supported %d", mode);
       return -EINVAL;
   }
-  return CallDisplayFunction(device, HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
+  return CallDisplayFunction(HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
 }
 
 void HWCSession::UpdateThrottlingRate() {
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index e8ab1ff..7a858fa 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -121,64 +121,49 @@
 class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient,
                    public HWCDisplayEventHandler {
  public:
-  struct HWCModuleMethods : public hw_module_methods_t {
-    HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
-  };
-
   enum HotPlugEvent {
     kHotPlugNone,
     kHotPlugEvent,
   };
 
-  explicit HWCSession(const hw_module_t *module);
+  HWCSession();
   int Init();
   int Deinit();
   HWC2::Error CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
                                       hwc2_display_t *out_display_id);
 
   template <typename... Args>
-  static int32_t CallDisplayFunction(hwc2_device_t *device, hwc2_display_t display,
-                                     HWC2::Error (HWCDisplay::*member)(Args...), Args... args) {
-    if (!device) {
-      return HWC2_ERROR_BAD_PARAMETER;
-    }
-
+  int32_t CallDisplayFunction(hwc2_display_t display, HWC2::Error (HWCDisplay::*member)(Args...),
+                              Args... args) {
     if (display >= HWCCallbacks::kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
     SCOPE_LOCK(locker_[display]);
-    HWCSession *hwc_session = static_cast<HWCSession *>(device);
     auto status = HWC2::Error::BadDisplay;
-    if (hwc_session->hwc_display_[display]) {
-      auto hwc_display = hwc_session->hwc_display_[display];
+    if (hwc_display_[display]) {
+      auto hwc_display = hwc_display_[display];
       status = (hwc_display->*member)(std::forward<Args>(args)...);
     }
     return INT32(status);
   }
 
   template <typename... Args>
-  static int32_t CallLayerFunction(hwc2_device_t *device, hwc2_display_t display,
-                                   hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
-                                   Args... args) {
-    if (!device) {
-      return HWC2_ERROR_BAD_PARAMETER;
-    }
-
+  int32_t CallLayerFunction(hwc2_display_t display, hwc2_layer_t layer,
+                            HWC2::Error (HWCLayer::*member)(Args...), Args... args) {
     if (display >= HWCCallbacks::kNumDisplays) {
       return HWC2_ERROR_BAD_DISPLAY;
     }
 
     SCOPE_LOCK(locker_[display]);
-    HWCSession *hwc_session = static_cast<HWCSession *>(device);
     auto status = HWC2::Error::BadDisplay;
-    if (hwc_session->hwc_display_[display]) {
+    if (hwc_display_[display]) {
       status = HWC2::Error::BadLayer;
-      auto hwc_layer = hwc_session->hwc_display_[display]->GetHWCLayer(layer);
+      auto hwc_layer = hwc_display_[display]->GetHWCLayer(layer);
       if (hwc_layer != nullptr) {
         status = (hwc_layer->*member)(std::forward<Args>(args)...);
-        if (hwc_session->hwc_display_[display]->GetGeometryChanges()) {
-          hwc_session->hwc_display_[display]->ResetValidation();
+        if (hwc_display_[display]->GetGeometryChanges()) {
+          hwc_display_[display]->ResetValidation();
         }
       }
     }
@@ -187,55 +172,97 @@
 
   // HWC2 Functions that require a concrete implementation in hwc session
   // and hence need to be member functions
-  static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display);
-  static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display,
-                             hwc2_layer_t *out_layer_id);
-  static int32_t CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
-                                      int32_t *format, hwc2_display_t *out_display_id);
-  static int32_t DestroyLayer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer);
-  static int32_t DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display);
-  static void Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer);
-  static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
-                                int32_t *out_retire_fence);
-  static int32_t RegisterCallback(hwc2_device_t *device, int32_t descriptor,
-                                  hwc2_callback_data_t callback_data,
-                                  hwc2_function_pointer_t pointer);
-  static int32_t SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
-                                 buffer_handle_t buffer, int32_t releaseFence);
-  static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode);
-  static int32_t ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
-                                 uint32_t *out_num_types, uint32_t *out_num_requests);
-  static int32_t SetColorMode(hwc2_device_t *device, hwc2_display_t display,
-                              int32_t /*ColorMode*/ int_mode);
-  static int32_t SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_display_t display,
-                                              int32_t /*ColorMode*/ int_mode,
-                                              int32_t /*RenderIntent*/ int_render_intent);
-  static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
-                                   const float *matrix, int32_t /*android_color_transform_t*/ hint);
-  static int32_t GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
-                                             int32_t *format, int32_t *dataspace);
-  static int32_t SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,
-                                   const native_handle_t *buffer, int32_t acquire_fence);
-  static int32_t GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
-                                        int32_t *release_fence);
-  static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device);
-  static int32_t GetDisplayIdentificationData(hwc2_device_t *device, hwc2_display_t display,
-                                              uint8_t *outPort, uint32_t *outDataSize,
-                                              uint8_t *outData);
-  static int32_t GetDisplayCapabilities(hwc2_device_t *device, hwc2_display_t display,
-                                        uint32_t *outNumCapabilities, uint32_t *outCapabilities);
-  static int32_t GetDisplayBrightnessSupport(hwc2_device_t *device, hwc2_display_t display,
-                                             bool *outSupport);
-  static int32_t SetDisplayBrightness(hwc2_device_t *device, hwc2_display_t display,
-                                      float brightness);
+  static HWCSession *GetInstance();
+  void GetCapabilities(uint32_t *outCount, int32_t *outCapabilities);
+  void Dump(uint32_t *out_size, char *out_buffer);
+
+  int32_t AcceptDisplayChanges(hwc2_display_t display);
+  int32_t CreateLayer(hwc2_display_t display, hwc2_layer_t *out_layer_id);
+  int32_t CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format,
+                               hwc2_display_t *out_display_id);
+  int32_t DestroyLayer(hwc2_display_t display, hwc2_layer_t layer);
+  int32_t DestroyVirtualDisplay(hwc2_display_t display);
+  int32_t PresentDisplay(hwc2_display_t display, int32_t *out_retire_fence);
+  void RegisterCallback(int32_t descriptor, hwc2_callback_data_t callback_data,
+                        hwc2_function_pointer_t pointer);
+  int32_t SetOutputBuffer(hwc2_display_t display, buffer_handle_t buffer, int32_t releaseFence);
+  int32_t SetPowerMode(hwc2_display_t display, int32_t int_mode);
+  int32_t ValidateDisplay(hwc2_display_t display, uint32_t *out_num_types,
+                          uint32_t *out_num_requests);
+  int32_t SetColorMode(hwc2_display_t display, int32_t /*ColorMode*/ int_mode);
+  int32_t SetColorModeWithRenderIntent(hwc2_display_t display, int32_t /*ColorMode*/ int_mode,
+                                       int32_t /*RenderIntent*/ int_render_intent);
+  int32_t SetColorTransform(hwc2_display_t display, const float *matrix,
+                            int32_t /*android_color_transform_t*/ hint);
+  int32_t GetReadbackBufferAttributes(hwc2_display_t display,
+                                      int32_t *format, int32_t *dataspace);
+  int32_t SetReadbackBuffer(hwc2_display_t display, const native_handle_t *buffer,
+                            int32_t acquire_fence);
+  int32_t GetReadbackBufferFence(hwc2_display_t display, int32_t *release_fence);
+  uint32_t GetMaxVirtualDisplayCount();
+  int32_t GetDisplayIdentificationData(hwc2_display_t display, uint8_t *outPort,
+                                       uint32_t *outDataSize, uint8_t *outData);
+  int32_t GetDisplayCapabilities(hwc2_display_t display, uint32_t *outNumCapabilities,
+                                 uint32_t *outCapabilities);
+  int32_t GetDisplayBrightnessSupport(hwc2_display_t display, bool *outSupport);
+  int32_t SetDisplayBrightness(hwc2_display_t display, float brightness);
+
+  // newly added
+  int32_t GetDisplayType(hwc2_display_t display, int32_t *out_type);
+  int32_t GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+                              int32_t int_attribute, int32_t *out_value);
+  int32_t GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config);
+  int32_t GetColorModes(hwc2_display_t display, uint32_t *out_num_modes,
+                        int32_t /*ColorMode*/ *int_out_modes);
+  int32_t GetRenderIntents(hwc2_display_t display, int32_t /*ColorMode*/ int_mode,
+                           uint32_t *out_num_intents, int32_t /*RenderIntent*/ *int_out_intents);
+  int32_t GetHdrCapabilities(hwc2_display_t display, uint32_t* out_num_types, int32_t* out_types,
+                             float* out_max_luminance, float* out_max_average_luminance,
+                             float* out_min_luminance);
+  int32_t GetPerFrameMetadataKeys(hwc2_display_t display, uint32_t *out_num_keys,
+                                  int32_t *int_out_keys);
+  int32_t GetClientTargetSupport(hwc2_display_t display, uint32_t width, uint32_t height,
+                                 int32_t format, int32_t dataspace);
+  int32_t GetDisplayName(hwc2_display_t display, uint32_t *out_size, char *out_name);
+  int32_t SetActiveConfig(hwc2_display_t display, hwc2_config_t config);
+  int32_t GetChangedCompositionTypes(hwc2_display_t display, uint32_t *out_num_elements,
+                                     hwc2_layer_t *out_layers, int32_t *out_types);
+  int32_t GetDisplayRequests(hwc2_display_t display, int32_t *out_display_requests,
+                             uint32_t *out_num_elements, hwc2_layer_t *out_layers,
+                             int32_t *out_layer_requests);
+  int32_t GetReleaseFences(hwc2_display_t display, uint32_t *out_num_elements,
+                           hwc2_layer_t *out_layers, int32_t *out_fences);
+  int32_t SetClientTarget(hwc2_display_t display, buffer_handle_t target, int32_t acquire_fence,
+                          int32_t dataspace, hwc_region_t damage);
+  int32_t SetCursorPosition(hwc2_display_t display, hwc2_layer_t layer, int32_t x, int32_t y);
+  int32_t GetDataspaceSaturationMatrix(int32_t /*Dataspace*/ int_dataspace, float *out_matrix);
+
+  // Layer functions
+  int32_t SetLayerBuffer(hwc2_display_t display, hwc2_layer_t layer, buffer_handle_t buffer,
+                         int32_t acquire_fence);
+  int32_t SetLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer, int32_t int_mode);
+  int32_t SetLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer, hwc_rect_t frame);
+  int32_t SetLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, float alpha);
+  int32_t SetLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer, hwc_frect_t crop);
+  int32_t SetLayerTransform(hwc2_display_t display, hwc2_layer_t layer, int32_t int_transform);
+  int32_t SetLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, uint32_t z);
+  int32_t SetLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer, hwc_region_t damage);
+  int32_t SetLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer, hwc_region_t damage);
+  int32_t SetLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer, int32_t int_type);
+  int32_t SetLayerColor(hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color);
+  int32_t SetLayerDataspace(hwc2_display_t display, hwc2_layer_t layer, int32_t dataspace);
+  int32_t SetLayerPerFrameMetadata(hwc2_display_t display, hwc2_layer_t layer,
+                                   uint32_t num_elements, const int32_t *int_keys,
+                                   const float *metadata);
+  int32_t SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer, const float *matrix);
 
   // HWCDisplayEventHandler
   virtual void DisplayPowerReset();
 
-  static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
-                                 int32_t int_enabled);
-  static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
-                                int32_t *out_support);
+  int32_t SetVsyncEnabled(hwc2_display_t display, int32_t int_enabled);
+  int32_t GetDozeSupport(hwc2_display_t display, int32_t *out_support);
+  int32_t GetDisplayConfigs(hwc2_display_t display, uint32_t *out_num_configs,
+                            hwc2_config_t *out_configs);
 
   static Locker locker_[HWCCallbacks::kNumDisplays];
 
@@ -258,12 +285,6 @@
   uint32_t throttling_refresh_rate_ = 60;
   void UpdateThrottlingRate();
   void SetNewThrottlingRate(uint32_t new_rate);
-  // hwc methods
-  static int Open(const hw_module_t *module, const char *name, hw_device_t **device);
-  static int Close(hw_device_t *device);
-  static void GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
-                              int32_t *outCapabilities);
-  static hwc2_function_pointer_t GetFunction(struct hwc2_device *device, int32_t descriptor);
 
   // Uevent handler
   virtual void UEventHandler(const char *uevent_data, int length);
@@ -298,9 +319,9 @@
   Return<void> isDisplayConnected(IDisplayConfig::DisplayType dpy,
                                   isDisplayConnected_cb _hidl_cb) override;
   Return<int32_t> setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
-                                  IDisplayConfig::DisplayExternalStatus status) override;
+                                           IDisplayConfig::DisplayExternalStatus status) override;
   Return<int32_t> configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
-                                  uint32_t refreshRate) override;
+                                         uint32_t refreshRate) override;
   Return<void> getConfigCount(IDisplayConfig::DisplayType dpy,
                               getConfigCount_cb _hidl_cb) override;
   Return<void> getActiveConfig(IDisplayConfig::DisplayType dpy,
@@ -450,7 +471,6 @@
   float set_min_lum_ = -1.0;
   std::bitset<HWCCallbacks::kNumDisplays> pending_refresh_;
 };
-
 }  // namespace sdm
 
 #endif  // __HWC_SESSION_H__
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index fb5a8dc..8232b94 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -295,11 +295,10 @@
     return -EINVAL;
   }
 
-  hwc2_device_t *device = static_cast<hwc2_device_t *>(this);
   if (level == 0) {
-    return INT32(SetDisplayBrightness(device, HWC_DISPLAY_PRIMARY, -1.0f));
+    return INT32(SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f));
   } else {
-    return INT32(SetDisplayBrightness(device, HWC_DISPLAY_PRIMARY, (level - 1)/254.0f));
+    return INT32(SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f));
   }
 }
 
@@ -548,7 +547,7 @@
 
 #ifdef DISPLAY_CONFIG_1_1
 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
-  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+  return CallDisplayFunction(display_id,
                              &HWCDisplay::SetDisplayAnimating, animating);
 }
 #endif
@@ -639,7 +638,7 @@
 Return<int32_t> HWCSession::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) {
-  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+  return CallDisplayFunction(display_id,
                              &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
                              factor_in, factor_out);
 }
@@ -799,8 +798,7 @@
 }
 
 int32_t HWCSession::setDisplayBrightness(uint32_t display, float brightness) {
-  return SetDisplayBrightness(static_cast<hwc2_device_t *>(this),
-                              static_cast<hwc2_display_t>(display), brightness);
+  return SetDisplayBrightness(static_cast<hwc2_display_t>(display), brightness);
 }
 
 #ifdef DISPLAY_CONFIG_1_9
diff --git a/composer/service.cpp b/composer/service.cpp
new file mode 100644
index 0000000..b0f757a
--- /dev/null
+++ b/composer/service.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2019, 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 <hidl/LegacySupport.h>
+#include "QtiComposer.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::ProcessState;
+using vendor::qti::hardware::display::composer::V1_0::implementation::QtiComposer;
+using vendor::qti::hardware::display::composer::V1_0::IQtiComposer;
+using android::hardware::graphics::composer::V2_3::IComposer;
+using android::sp;
+
+int main(int, char **) {
+  // TODO(user): double-check for SCHED_FIFO logic
+  // the conventional HAL might start binder services
+  ProcessState::initWithDriver("/dev/vndbinder");
+  sp<ProcessState> ps(ProcessState::self());
+  ps->setThreadPoolMaxThreadCount(4);
+  ps->startThreadPool();
+
+  // same as SF main thread
+  struct sched_param param = {0};
+  param.sched_priority = 2;
+  if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+    ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+  }
+
+  sp<IQtiComposer> composer = QtiComposer::initialize();
+  if (composer == nullptr) {
+    ALOGE("Cannot initialize composer");
+    return -EINVAL;
+  }
+
+  configureRpcThreadpool(4, true /*callerWillJoin*/);
+  if (composer->registerAsService() != android::OK) {
+    ALOGE("Cannot register QTI composer service");
+    return -EINVAL;
+  }
+
+  ALOGI("Initialized qti-composer");
+  joinRpcThreadpool();
+  return 0;
+}
diff --git a/composer/vendor.qti.hardware.display.composer@1.0-service.rc b/composer/vendor.qti.hardware.display.composer@1.0-service.rc
new file mode 100644
index 0000000..ad56c05
--- /dev/null
+++ b/composer/vendor.qti.hardware.display.composer@1.0-service.rc
@@ -0,0 +1,6 @@
+service vendor.qti.hardware.display.composer /vendor/bin/hw/vendor.qti.hardware.display.composer@1.0-service
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
diff --git a/config/display-product.mk b/config/display-product.mk
index a39e1c6..6831002 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -1,9 +1,8 @@
 # Display product definitions
 PRODUCT_PACKAGES += \
-    android.hardware.graphics.composer@2.3-impl \
-    android.hardware.graphics.composer@2.3-service \
     android.hardware.graphics.mapper@2.0-impl-qti-display \
     vendor.qti.hardware.display.allocator-service \
+    vendor.qti.hardware.display.composer@1.0-service \
     android.hardware.memtrack@1.0-impl \
     android.hardware.memtrack@1.0-service \
     android.hardware.light@2.0-impl \