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