graphics: move ComposerClient to HAL support library

libhwcomposer-client is empty and can be removed.  Note that
ComposerClient::initialize is renamed and can fail now.

Test: boots and VTS
Change-Id: Iacd3f995bc094c7dd6b7f91ae64aad0522b3f3d3
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index d3476c5..6f25cbf 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,35 +1,9 @@
-cc_library_static {
-    name: "libhwcomposer-client",
-    vendor_available: true,
-    defaults: ["hidl_defaults"],
-    export_include_dirs: ["."],
-    srcs: ["ComposerClient.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.composer@2.1",
-        "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libsync",
-        "libutils",
-    ],
-    header_libs: [
-        "android.hardware.graphics.composer@2.1-command-buffer",
-        "android.hardware.graphics.composer@2.1-hal",
-    ],
-}
-
 cc_library_shared {
     name: "android.hardware.graphics.composer@2.1-impl",
     defaults: ["hidl_defaults"],
     proprietary: true,
     relative_install_path: "hw",
     srcs: ["Hwc.cpp"],
-    static_libs: ["libhwcomposer-client"],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
@@ -58,7 +32,6 @@
     relative_install_path: "hw",
     srcs: ["service.cpp"],
     init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
-    static_libs: ["libhwcomposer-client"],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
         "libbase",
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
deleted file mode 100644
index 4fda5ae..0000000
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "HwcPassthrough"
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <log/log.h>
-
-#include "ComposerClient.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-ComposerClient::ComposerClient(ComposerHal& hal)
-    : mHal(hal)
-{
-}
-
-ComposerClient::~ComposerClient()
-{
-    ALOGD("destroying composer client");
-
-    mHal.enableCallback(false);
-    destroyResources();
-    mHal.removeClient();
-
-    ALOGD("removed composer client");
-}
-
-void ComposerClient::destroyResources()
-{
-    // 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.
-    mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
-        ALOGW("destroying client resources for display %" PRIu64, display);
-
-        for (auto layer : layers) {
-            mHal.destroyLayer(display, layer);
-        }
-
-        if (isVirtual) {
-            mHal.destroyVirtualDisplay(display);
-        } 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;
-            mHal.validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask,
-                                 &requestedLayers, &requestMasks);
-
-            mHal.acceptDisplayChanges(display);
-
-            int32_t presentFence = -1;
-            std::vector<Layer> releasedLayers;
-            std::vector<int32_t> releaseFences;
-            mHal.presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
-            if (presentFence >= 0) {
-                close(presentFence);
-            }
-            for (auto fence : releaseFences) {
-                if (fence >= 0) {
-                    close(fence);
-                }
-            }
-        }
-    });
-
-    mResources.reset();
-}
-
-void ComposerClient::initialize()
-{
-    mResources = createResources();
-    if (!mResources) {
-        LOG_ALWAYS_FATAL("failed to create resources");
-    }
-
-    mCommandEngine = createCommandEngine();
-}
-
-void ComposerClient::onHotplug(Display display,
-        IComposerCallback::Connection connected)
-{
-    if (connected == IComposerCallback::Connection::CONNECTED) {
-        mResources->addPhysicalDisplay(display);
-    } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
-        mResources->removeDisplay(display);
-    }
-
-    auto ret = mCallback->onHotplug(display, connected);
-    ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onRefresh(Display display)
-{
-    auto ret = mCallback->onRefresh(display);
-    ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s",
-            ret.description().c_str());
-}
-
-void ComposerClient::onVsync(Display display, int64_t timestamp)
-{
-    auto ret = mCallback->onVsync(display, timestamp);
-    ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s",
-            ret.description().c_str());
-}
-
-Return<void> ComposerClient::registerCallback(
-        const sp<IComposerCallback>& callback)
-{
-    // no locking as we require this function to be called only once
-    mCallback = callback;
-    mHal.enableCallback(callback != nullptr);
-
-    return Void();
-}
-
-Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount()
-{
-    return mHal.getMaxVirtualDisplayCount();
-}
-
-Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
-        uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
-        createVirtualDisplay_cb hidl_cb)
-{
-    Display display = 0;
-    Error err = mHal.createVirtualDisplay(width, height,
-            &formatHint, &display);
-    if (err == Error::NONE) {
-        mResources->addVirtualDisplay(display, outputBufferSlotCount);
-    }
-
-    hidl_cb(err, display, formatHint);
-    return Void();
-}
-
-Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
-{
-    Error err = mHal.destroyVirtualDisplay(display);
-    if (err == Error::NONE) {
-        mResources->removeDisplay(display);
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::createLayer(Display display,
-        uint32_t bufferSlotCount, createLayer_cb hidl_cb)
-{
-    Layer layer = 0;
-    Error err = mHal.createLayer(display, &layer);
-    if (err == Error::NONE) {
-        err = mResources->addLayer(display, layer, bufferSlotCount);
-        if (err != Error::NONE) {
-            // The display entry may have already been removed by onHotplug.
-            // 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> ComposerClient::destroyLayer(Display display, Layer layer)
-{
-    Error err = mHal.destroyLayer(display, layer);
-    if (err == Error::NONE) {
-        mResources->removeLayer(display, layer);
-    }
-
-    return err;
-}
-
-Return<void> ComposerClient::getActiveConfig(Display display,
-        getActiveConfig_cb hidl_cb)
-{
-    Config config = 0;
-    Error err = mHal.getActiveConfig(display, &config);
-
-    hidl_cb(err, config);
-    return Void();
-}
-
-Return<Error> ComposerClient::getClientTargetSupport(Display display,
-        uint32_t width, uint32_t height,
-        PixelFormat format, Dataspace dataspace)
-{
-    Error err = mHal.getClientTargetSupport(display,
-            width, height, format, dataspace);
-    return err;
-}
-
-Return<void> ComposerClient::getColorModes(Display display,
-          getColorModes_cb hidl_cb)
-{
-    hidl_vec<ColorMode> modes;
-    Error err = mHal.getColorModes(display, &modes);
-
-    hidl_cb(err, modes);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayAttribute(Display display,
-        Config config, Attribute attribute,
-        getDisplayAttribute_cb hidl_cb)
-{
-    int32_t value = 0;
-    Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
-
-    hidl_cb(err, value);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayConfigs(Display display,
-        getDisplayConfigs_cb hidl_cb)
-{
-    hidl_vec<Config> configs;
-    Error err = mHal.getDisplayConfigs(display, &configs);
-
-    hidl_cb(err, configs);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayName(Display display,
-        getDisplayName_cb hidl_cb)
-{
-    hidl_string name;
-    Error err = mHal.getDisplayName(display, &name);
-
-    hidl_cb(err, name);
-    return Void();
-}
-
-Return<void> ComposerClient::getDisplayType(Display display,
-        getDisplayType_cb hidl_cb)
-{
-    DisplayType type = DisplayType::INVALID;
-    Error err = mHal.getDisplayType(display, &type);
-
-    hidl_cb(err, type);
-    return Void();
-}
-
-Return<void> ComposerClient::getDozeSupport(Display display,
-        getDozeSupport_cb hidl_cb)
-{
-    bool support = false;
-    Error err = mHal.getDozeSupport(display, &support);
-
-    hidl_cb(err, support);
-    return Void();
-}
-
-Return<void> ComposerClient::getHdrCapabilities(Display display,
-        getHdrCapabilities_cb hidl_cb)
-{
-    hidl_vec<Hdr> types;
-    float max_lumi = 0.0f;
-    float max_avg_lumi = 0.0f;
-    float min_lumi = 0.0f;
-    Error err = mHal.getHdrCapabilities(display, &types,
-            &max_lumi, &max_avg_lumi, &min_lumi);
-
-    hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
-    return Void();
-}
-
-Return<Error> ComposerClient::setClientTargetSlotCount(Display display,
-        uint32_t clientTargetSlotCount)
-{
-    return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
-}
-
-Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
-{
-    Error err = mHal.setActiveConfig(display, config);
-    return err;
-}
-
-Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode)
-{
-    Error err = mHal.setColorMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode)
-{
-    Error err = mHal.setPowerMode(display, mode);
-    return err;
-}
-
-Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled)
-{
-    Error err = mHal.setVsyncEnabled(display, enabled);
-    return err;
-}
-
-Return<Error> ComposerClient::setInputCommandQueue(
-        const MQDescriptorSync<uint32_t>& descriptor)
-{
-    std::lock_guard<std::mutex> lock(mCommandEngineMutex);
-    return mCommandEngine->setInputMQDescriptor(descriptor) ?
-        Error::NONE : Error::NO_RESOURCES;
-}
-
-Return<void> ComposerClient::getOutputCommandQueue(
-        getOutputCommandQueue_cb hidl_cb)
-{
-    // no locking as we require this function to be called inside
-    // executeCommands_cb
-
-    auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
-    if (outDescriptor) {
-        hidl_cb(Error::NONE, *outDescriptor);
-    } else {
-        hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
-    }
-
-    return Void();
-}
-
-Return<void> ComposerClient::executeCommands(uint32_t inLength,
-        const hidl_vec<hidl_handle>& inHandles,
-        executeCommands_cb hidl_cb)
-{
-    std::lock_guard<std::mutex> lock(mCommandEngineMutex);
-
-    bool outChanged = false;
-    uint32_t outLength = 0;
-    hidl_vec<hidl_handle> outHandles;
-    Error error = mCommandEngine->execute(inLength, inHandles,
-            &outChanged, &outLength, &outHandles);
-
-    hidl_cb(error, outChanged, outLength, outHandles);
-
-    mCommandEngine->reset();
-
-    return Void();
-}
-
-std::unique_ptr<ComposerResources> ComposerClient::createResources()
-{
-    return ComposerResources::create();
-}
-
-std::unique_ptr<ComposerCommandEngine>
-ComposerClient::createCommandEngine()
-{
-    return std::make_unique<ComposerCommandEngine>(&mHal, mResources.get());
-}
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
deleted file mode 100644
index bbb0522..0000000
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
-
-#include <mutex>
-#include <unordered_map>
-#include <vector>
-
-#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
-#include <composer-hal/2.1/ComposerCommandEngine.h>
-#include <composer-hal/2.1/ComposerHal.h>
-#include <composer-hal/2.1/ComposerResources.h>
-#include <hardware/hwcomposer2.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace implementation {
-
-using namespace hal;
-
-class ComposerClient : public IComposerClient {
-public:
-    ComposerClient(ComposerHal& hal);
-    virtual ~ComposerClient();
-
-    void initialize();
-
-    void onHotplug(Display display, IComposerCallback::Connection connected);
-    void onRefresh(Display display);
-    void onVsync(Display display, int64_t timestamp);
-
-    // IComposerClient interface
-    Return<void> registerCallback(
-            const sp<IComposerCallback>& callback) override;
-    Return<uint32_t> getMaxVirtualDisplayCount() override;
-    Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat formatHint, uint32_t outputBufferSlotCount,
-            createVirtualDisplay_cb hidl_cb) override;
-    Return<Error> destroyVirtualDisplay(Display display) override;
-    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
-            createLayer_cb hidl_cb) override;
-    Return<Error> destroyLayer(Display display, Layer layer) override;
-    Return<void> getActiveConfig(Display display,
-            getActiveConfig_cb hidl_cb) override;
-    Return<Error> getClientTargetSupport(Display display,
-            uint32_t width, uint32_t height,
-            PixelFormat format, Dataspace dataspace) override;
-    Return<void> getColorModes(Display display,
-            getColorModes_cb hidl_cb) override;
-    Return<void> getDisplayAttribute(Display display,
-            Config config, Attribute attribute,
-            getDisplayAttribute_cb hidl_cb) override;
-    Return<void> getDisplayConfigs(Display display,
-            getDisplayConfigs_cb hidl_cb) override;
-    Return<void> getDisplayName(Display display,
-            getDisplayName_cb hidl_cb) override;
-    Return<void> getDisplayType(Display display,
-            getDisplayType_cb hidl_cb) override;
-    Return<void> getDozeSupport(Display display,
-            getDozeSupport_cb hidl_cb) override;
-    Return<void> getHdrCapabilities(Display display,
-            getHdrCapabilities_cb hidl_cb) override;
-    Return<Error> setActiveConfig(Display display, Config config) override;
-    Return<Error> setColorMode(Display display, ColorMode mode) override;
-    Return<Error> setPowerMode(Display display, PowerMode mode) override;
-    Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
-    Return<Error> setClientTargetSlotCount(Display display,
-            uint32_t clientTargetSlotCount) 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;
-
-protected:
-    virtual std::unique_ptr<ComposerResources> createResources();
-    virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine();
-
-    void destroyResources();
-
-    ComposerHal& mHal;
-
-    std::unique_ptr<ComposerResources> mResources;
-
-    std::mutex mCommandEngineMutex;
-    std::unique_ptr<ComposerCommandEngine> mCommandEngine;
-
-    sp<IComposerCallback> mCallback;
-};
-
-} // namespace implementation
-} // namespace V2_1
-} // namespace composer
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
index cb393ec..e108fca 100644
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -22,7 +22,6 @@
 #include <type_traits>
 #include <log/log.h>
 
-#include "ComposerClient.h"
 #include "hardware/fb.h"
 #include "hardware/hwcomposer.h"
 #include "hwc2on1adapter/HWC2On1Adapter.h"
@@ -281,9 +280,14 @@
 
         // only one client is allowed
         if (mClient == nullptr) {
-            client = new ComposerClient(*this);
-            client->initialize();
-            mClient = client;
+            // We assume Composer outlives ComposerClient here.  It is true
+            // only because Composer is binderized.
+            client = ComposerClient::create(this).release();
+            if (client) {
+                mClient = client;
+            } else {
+                err = Error::NO_RESOURCES;
+            }
         } else {
             err = Error::NO_RESOURCES;
         }
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
index 40daa0c..ce91dd6 100644
--- a/graphics/composer/2.1/default/Hwc.h
+++ b/graphics/composer/2.1/default/Hwc.h
@@ -30,6 +30,7 @@
 #include <hardware/hwcomposer2.h>
 #undef HWC2_INCLUDE_STRINGIFICATION
 #undef HWC2_USE_CPP11
+#include <composer-hal/2.1/ComposerClient.h>
 #include <composer-hal/2.1/ComposerHal.h>
 
 namespace android {
@@ -53,8 +54,6 @@
 using android::hardware::graphics::common::V1_0::ColorTransform;
 using android::hardware::graphics::common::V1_0::Hdr;
 
-class ComposerClient;
-
 class HwcHal : public IComposer, public ComposerHal {
 public:
     HwcHal(const hw_module_t* module);
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
new file mode 100644
index 0000000..b8a3f75
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public Interface {
+   public:
+    static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+        auto client = std::make_unique<ComposerClientImpl>(hal);
+        return client->init() ? std::move(client) : nullptr;
+    }
+
+    ComposerClientImpl(Hal* hal) : mHal(hal) {}
+
+    virtual ~ComposerClientImpl() {
+        // not initialized
+        if (!mCommandEngine) {
+            return;
+        }
+
+        ALOGD("destroying composer client");
+
+        mHal->enableCallback(false);
+        destroyResources();
+        mHal->removeClient();
+
+        ALOGD("removed composer client");
+    }
+
+    bool init() {
+        mResources = createResources();
+        if (!mResources) {
+            ALOGE("failed to create composer resources");
+            return false;
+        }
+
+        mCommandEngine = createCommandEngine();
+
+        return true;
+    }
+
+    void onHotplug(Display display, IComposerCallback::Connection connected) {
+        if (connected == IComposerCallback::Connection::CONNECTED) {
+            mResources->addPhysicalDisplay(display);
+        } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
+            mResources->removeDisplay(display);
+        }
+
+        auto ret = mCallback->onHotplug(display, connected);
+        ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
+    }
+
+    void onRefresh(Display display) {
+        auto ret = mCallback->onRefresh(display);
+        ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
+    }
+
+    void onVsync(Display display, int64_t timestamp) {
+        auto ret = mCallback->onVsync(display, timestamp);
+        ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
+    }
+
+    // IComposerClient 2.1 interface
+
+    Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
+        // no locking as we require this function to be called only once
+        mCallback = callback;
+        mHal->enableCallback(callback != nullptr);
+
+        return Void();
+    }
+
+    Return<uint32_t> getMaxVirtualDisplayCount() override {
+        return mHal->getMaxVirtualDisplayCount();
+    }
+
+    Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
+                                      uint32_t outputBufferSlotCount,
+                                      IComposerClient::createVirtualDisplay_cb hidl_cb) override {
+        Display display = 0;
+        Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display);
+        if (err == Error::NONE) {
+            mResources->addVirtualDisplay(display, outputBufferSlotCount);
+        }
+
+        hidl_cb(err, display, formatHint);
+        return Void();
+    }
+
+    Return<Error> destroyVirtualDisplay(Display display) override {
+        Error err = mHal->destroyVirtualDisplay(display);
+        if (err == Error::NONE) {
+            mResources->removeDisplay(display);
+        }
+
+        return err;
+    }
+
+    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
+                             IComposerClient::createLayer_cb hidl_cb) override {
+        Layer layer = 0;
+        Error err = mHal->createLayer(display, &layer);
+        if (err == Error::NONE) {
+            err = mResources->addLayer(display, layer, bufferSlotCount);
+            if (err != Error::NONE) {
+                // The display entry may have already been removed by onHotplug.
+                // 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.
+                layer = 0;
+            }
+        }
+
+        hidl_cb(err, layer);
+        return Void();
+    }
+
+    Return<Error> destroyLayer(Display display, Layer layer) override {
+        Error err = mHal->destroyLayer(display, layer);
+        if (err == Error::NONE) {
+            mResources->removeLayer(display, layer);
+        }
+
+        return err;
+    }
+
+    Return<void> getActiveConfig(Display display,
+                                 IComposerClient::getActiveConfig_cb hidl_cb) override {
+        Config config = 0;
+        Error err = mHal->getActiveConfig(display, &config);
+        hidl_cb(err, config);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+                                         PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace);
+        return err;
+    }
+
+    Return<void> getColorModes(Display display,
+                               IComposerClient::getColorModes_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getDisplayAttribute(Display display, Config config,
+                                     IComposerClient::Attribute attribute,
+                                     IComposerClient::getDisplayAttribute_cb hidl_cb) override {
+        int32_t value = 0;
+        Error err = mHal->getDisplayAttribute(display, config, attribute, &value);
+        hidl_cb(err, value);
+        return Void();
+    }
+
+    Return<void> getDisplayConfigs(Display display,
+                                   IComposerClient::getDisplayConfigs_cb hidl_cb) override {
+        hidl_vec<Config> configs;
+        Error err = mHal->getDisplayConfigs(display, &configs);
+        hidl_cb(err, configs);
+        return Void();
+    }
+
+    Return<void> getDisplayName(Display display,
+                                IComposerClient::getDisplayName_cb hidl_cb) override {
+        hidl_string name;
+        Error err = mHal->getDisplayName(display, &name);
+        hidl_cb(err, name);
+        return Void();
+    }
+
+    Return<void> getDisplayType(Display display,
+                                IComposerClient::getDisplayType_cb hidl_cb) override {
+        IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
+        Error err = mHal->getDisplayType(display, &type);
+        hidl_cb(err, type);
+        return Void();
+    }
+
+    Return<void> getDozeSupport(Display display,
+                                IComposerClient::getDozeSupport_cb hidl_cb) override {
+        bool support = false;
+        Error err = mHal->getDozeSupport(display, &support);
+        hidl_cb(err, support);
+        return Void();
+    }
+
+    Return<void> getHdrCapabilities(Display display,
+                                    IComposerClient::getHdrCapabilities_cb hidl_cb) override {
+        hidl_vec<Hdr> types;
+        float max_lumi = 0.0f;
+        float max_avg_lumi = 0.0f;
+        float min_lumi = 0.0f;
+        Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi);
+        hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
+        return Void();
+    }
+
+    Return<Error> setActiveConfig(Display display, Config config) override {
+        Error err = mHal->setActiveConfig(display, config);
+        return err;
+    }
+
+    Return<Error> setColorMode(Display display, ColorMode mode) override {
+        Error err = mHal->setColorMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+        Error err = mHal->setPowerMode(display, mode);
+        return err;
+    }
+
+    Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+        Error err = mHal->setVsyncEnabled(display, enabled);
+        return err;
+    }
+
+    Return<Error> setClientTargetSlotCount(Display display,
+                                           uint32_t clientTargetSlotCount) override {
+        return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
+    }
+
+    Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
+    }
+
+    Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override {
+        // no locking as we require this function to be called inside
+        // executeCommands_cb
+        auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
+        if (outDescriptor) {
+            hidl_cb(Error::NONE, *outDescriptor);
+        } else {
+            hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
+        }
+
+        return Void();
+    }
+
+    Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                 IComposerClient::executeCommands_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
+   protected:
+    virtual std::unique_ptr<ComposerResources> createResources() {
+        return ComposerResources::create();
+    }
+
+    virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {
+        return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
+    }
+
+    void destroyResources() {
+        // 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.
+        mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
+            ALOGW("destroying client resources for display %" PRIu64, display);
+
+            for (auto layer : layers) {
+                mHal->destroyLayer(display, layer);
+            }
+
+            if (isVirtual) {
+                mHal->destroyVirtualDisplay(display);
+            } 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;
+                mHal->validateDisplay(display, &changedLayers, &compositionTypes,
+                                      &displayRequestMask, &requestedLayers, &requestMasks);
+
+                mHal->acceptDisplayChanges(display);
+
+                int32_t presentFence = -1;
+                std::vector<Layer> releasedLayers;
+                std::vector<int32_t> releaseFences;
+                mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
+                if (presentFence >= 0) {
+                    close(presentFence);
+                }
+                for (auto fence : releaseFences) {
+                    if (fence >= 0) {
+                        close(fence);
+                    }
+                }
+            }
+        });
+
+        mResources.reset();
+    }
+
+    Hal* const mHal;
+
+    std::unique_ptr<ComposerResources> mResources;
+
+    std::mutex mCommandEngineMutex;
+    std::unique_ptr<ComposerCommandEngine> mCommandEngine;
+
+    sp<IComposerCallback> mCallback;
+};
+
+}  // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android