summaryrefslogtreecommitdiff
authorbaocheng sun <baocheng.sun@amlogic.com>2019-12-24 05:58:07 (GMT)
committer sky zhou <sky.zhou@amlogic.com>2020-05-21 11:08:47 (GMT)
commit734918da9d1ec127eedc10a54ce408752443236c (patch)
treec100aaf76a7a940a9ddd21a9a6eeb7e0667b9788
parentbe100acbec50b07d02bfbae495ea2cb4f4ca278e (diff)
downloadhwcomposer-734918da9d1ec127eedc10a54ce408752443236c.zip
hwcomposer-734918da9d1ec127eedc10a54ce408752443236c.tar.gz
hwcomposer-734918da9d1ec127eedc10a54ce408752443236c.tar.bz2
hwc: add vendor composer service [1/3]
PD#SWPL-18099 Problem: When playing a 4k video and press back in YouTube, SurfaceView will not be destroyed. And in composer service process, there is a composerLayer. CompserLayer has a ComposerHandleCache which will hold the graphic buffer handles cached in it and lead to ion orphaned memory. Solution: Add vendor composer service. Verify: Verify on newton Change-Id: Ia7cac783941354ada82639990eadadac38603dc8 Signed-off-by: baocheng sun <baocheng.sun@amlogic.com>
Diffstat
-rw-r--r--service/2.1/utils/hal/Android.bp39
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/Composer.h156
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h397
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h598
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h137
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h592
-rw-r--r--service/2.1/utils/passthrough/Android.bp22
-rw-r--r--service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h679
-rw-r--r--service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h152
-rw-r--r--service/2.2/utils/passthrough/Android.bp14
-rw-r--r--service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h301
-rw-r--r--service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h79
-rw-r--r--service/2.3/default/Android.bp46
-rw-r--r--service/2.3/default/android.hardware.graphics.composer@2.3-service.rc7
-rw-r--r--service/2.3/default/service.cpp55
-rw-r--r--service/2.3/utils/passthrough/Android.bp30
-rw-r--r--service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h441
-rw-r--r--service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h79
18 files changed, 3824 insertions, 0 deletions
diff --git a/service/2.1/utils/hal/Android.bp b/service/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..7a501fc
--- a/dev/null
+++ b/service/2.1/utils/hal/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 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.
+
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.1-hal",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "libhardware", // TODO remove hwcomposer2.h dependency
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "libhardware",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h
new file mode 100644
index 0000000..90d9b98
--- a/dev/null
+++ b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <array>
+#include <chrono>
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public Interface {
+ public:
+ static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+ return std::make_unique<ComposerImpl>(std::move(hal));
+ }
+
+ ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {}
+
+ // IComposer 2.1 interface
+
+ Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override {
+ 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,
+ }};
+
+ std::vector<IComposer::Capability> caps;
+ for (auto cap : all_caps) {
+ if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) {
+ 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> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override {
+ hidl_cb(mHal->dumpDebugInfo());
+ return Void();
+ }
+
+ Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
+ std::unique_lock<std::mutex> lock(mClientMutex);
+ bool destroyed = waitForClientDestroyedLocked(lock);
+ if (!destroyed) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ sp<IComposerClient> client = createClient();
+ if (!client) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ mClient = client;
+ hidl_cb(Error::NONE, client);
+ return Void();
+ }
+
+ protected:
+ bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) {
+ if (mClient != nullptr) {
+ using namespace std::chrono_literals;
+
+ // In surface flinger we delete a composer client on one thread and
+ // then create a new client on another thread. Although surface
+ // flinger ensures the calls are made in that sequence (destroy and
+ // then create), sometimes the calls land in the composer service
+ // inverted (create and then destroy). Wait for a brief period to
+ // see if the existing client is destroyed.
+ ALOGD("waiting for previous client to be destroyed");
+ mClientDestroyedCondition.wait_for(lock, 1s,
+ [this]() -> bool { return mClient == nullptr; });
+ if (mClient != nullptr) {
+ ALOGD("previous client was not destroyed");
+ }
+ }
+
+ return mClient == nullptr;
+ }
+
+ void onClientDestroyed() {
+ std::lock_guard<std::mutex> lock(mClientMutex);
+ mClient.clear();
+ mClientDestroyedCondition.notify_all();
+ }
+
+ virtual IComposerClient* createClient() {
+ auto client = ComposerClient::create(mHal.get());
+ if (!client) {
+ return nullptr;
+ }
+
+ auto clientDestroyed = [this]() { onClientDestroyed(); };
+ client->setOnClientDestroyed(clientDestroyed);
+
+ return client.release();
+ }
+
+ const std::unique_ptr<Hal> mHal;
+
+ std::mutex mClientMutex;
+ wp<IComposerClient> mClient;
+ std::condition_variable mClientDestroyedCondition;
+};
+
+} // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
new file mode 100644
index 0000000..095189f
--- a/dev/null
+++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -0,0 +1,397 @@
+/*
+ * 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->unregisterEventCallback();
+ destroyResources();
+ if (mOnClientDestroyed) {
+ mOnClientDestroyed();
+ }
+
+ ALOGD("removed composer client");
+ }
+
+ bool init() {
+ mResources = createResources();
+ if (!mResources) {
+ ALOGE("failed to create composer resources");
+ return false;
+ }
+
+ mCommandEngine = createCommandEngine();
+
+ return true;
+ }
+
+ void setOnClientDestroyed(std::function<void()> onClientDestroyed) {
+ mOnClientDestroyed = onClientDestroyed;
+ }
+
+ // IComposerClient 2.1 interface
+
+ class HalEventCallback : public Hal::EventCallback {
+ public:
+ HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources)
+ : mCallback(callback), mResources(resources) {}
+
+ 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) {
+ mResources->setDisplayMustValidateState(display, true);
+ 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());
+ }
+
+ protected:
+ const sp<IComposerCallback> mCallback;
+ ComposerResources* const mResources;
+ };
+
+ Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
+ // no locking as we require this function to be called only once
+ mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get());
+ mHal->registerEventCallback(mHalEventCallback.get());
+ 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;
+
+ std::function<void()> mOnClientDestroyed;
+ std::unique_ptr<HalEventCallback> mHalEventCallback;
+};
+
+} // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..d87110a
--- a/dev/null
+++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,598 @@
+/*
+ * 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 "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <vector>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+// TODO remove hwcomposer_defs.h dependency
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// TODO own a CommandReaderBase rather than subclassing
+class ComposerCommandEngine : protected CommandReaderBase {
+ public:
+ ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+ : mHal(hal), mResources(resources) {}
+
+ virtual ~ComposerCommandEngine() = default;
+
+ bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+ return setMQDescriptor(descriptor);
+ }
+
+ Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged,
+ uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) {
+ if (!readQueue(inLength, inHandles)) {
+ return Error::BAD_PARAMETER;
+ }
+
+ IComposerClient::Command command;
+ uint16_t length = 0;
+ while (!isEmpty()) {
+ if (!beginCommand(&command, &length)) {
+ break;
+ }
+
+ bool parsed = executeCommand(command, length);
+ endCommand();
+
+ if (!parsed) {
+ ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length);
+ break;
+ }
+ }
+
+ if (!isEmpty()) {
+ return Error::BAD_PARAMETER;
+ }
+
+ return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+ ? Error::NONE
+ : Error::NO_RESOURCES;
+ }
+
+ const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+
+ void reset() {
+ CommandReaderBase::reset();
+ mWriter.reset();
+ }
+
+ protected:
+ virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
+ switch (command) {
+ case IComposerClient::Command::SELECT_DISPLAY:
+ return executeSelectDisplay(length);
+ case IComposerClient::Command::SELECT_LAYER:
+ return executeSelectLayer(length);
+ case IComposerClient::Command::SET_COLOR_TRANSFORM:
+ return executeSetColorTransform(length);
+ case IComposerClient::Command::SET_CLIENT_TARGET:
+ return executeSetClientTarget(length);
+ case IComposerClient::Command::SET_OUTPUT_BUFFER:
+ return executeSetOutputBuffer(length);
+ case IComposerClient::Command::VALIDATE_DISPLAY:
+ return executeValidateDisplay(length);
+ case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+ return executePresentOrValidateDisplay(length);
+ case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+ return executeAcceptDisplayChanges(length);
+ case IComposerClient::Command::PRESENT_DISPLAY:
+ return executePresentDisplay(length);
+ case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+ return executeSetLayerCursorPosition(length);
+ case IComposerClient::Command::SET_LAYER_BUFFER:
+ return executeSetLayerBuffer(length);
+ case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+ return executeSetLayerSurfaceDamage(length);
+ case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+ return executeSetLayerBlendMode(length);
+ case IComposerClient::Command::SET_LAYER_COLOR:
+ return executeSetLayerColor(length);
+ case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+ return executeSetLayerCompositionType(length);
+ case IComposerClient::Command::SET_LAYER_DATASPACE:
+ return executeSetLayerDataspace(length);
+ case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+ return executeSetLayerDisplayFrame(length);
+ case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+ return executeSetLayerPlaneAlpha(length);
+ case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+ return executeSetLayerSidebandStream(length);
+ case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+ return executeSetLayerSourceCrop(length);
+ case IComposerClient::Command::SET_LAYER_TRANSFORM:
+ return executeSetLayerTransform(length);
+ case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+ return executeSetLayerVisibleRegion(length);
+ case IComposerClient::Command::SET_LAYER_Z_ORDER:
+ return executeSetLayerZOrder(length);
+ default:
+ return false;
+ }
+ }
+
+ bool executeSelectDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kSelectDisplayLength) {
+ return false;
+ }
+
+ mCurrentDisplay = read64();
+ mWriter.selectDisplay(mCurrentDisplay);
+
+ return true;
+ }
+
+ bool executeSelectLayer(uint16_t length) {
+ if (length != CommandWriterBase::kSelectLayerLength) {
+ return false;
+ }
+
+ mCurrentLayer = read64();
+
+ return true;
+ }
+
+ bool executeSetColorTransform(uint16_t length) {
+ if (length != CommandWriterBase::kSetColorTransformLength) {
+ return false;
+ }
+
+ float matrix[16];
+ for (int i = 0; i < 16; i++) {
+ matrix[i] = readFloat();
+ }
+ auto transform = readSigned();
+
+ auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetClientTarget(uint16_t length) {
+ // 4 parameters followed by N rectangles
+ if ((length - 4) % 4 != 0) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawHandle = readHandle(&useCache);
+ auto fence = readFence();
+ auto dataspace = readSigned();
+ auto damage = readRegion((length - 4) / 4);
+ bool closeFence = true;
+
+ const native_handle_t* clientTarget;
+ ComposerResources::ReplacedBufferHandle replacedClientTarget;
+ auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
+ &clientTarget, &replacedClientTarget);
+ if (err == Error::NONE) {
+ err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetOutputBuffer(uint16_t length) {
+ if (length != CommandWriterBase::kSetOutputBufferLength) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawhandle = readHandle(&useCache);
+ auto fence = readFence();
+ bool closeFence = true;
+
+ const native_handle_t* outputBuffer;
+ ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+ auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
+ &outputBuffer, &replacedOutputBuffer);
+ if (err == Error::NONE) {
+ err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeValidateDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kValidateDisplayLength) {
+ return false;
+ }
+
+ std::vector<Layer> changedLayers;
+ std::vector<IComposerClient::Composition> compositionTypes;
+ uint32_t displayRequestMask = 0x0;
+ std::vector<Layer> requestedLayers;
+ std::vector<uint32_t> requestMasks;
+
+ auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+ &displayRequestMask, &requestedLayers, &requestMasks);
+ mResources->setDisplayMustValidateState(mCurrentDisplay, false);
+ if (err == Error::NONE) {
+ mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+ mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+ } else {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executePresentOrValidateDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+ return false;
+ }
+
+ // First try to Present as is.
+ if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+ int presentFence = -1;
+ std::vector<Layer> layers;
+ std::vector<int> fences;
+ auto err = mResources->mustValidateDisplay(mCurrentDisplay)
+ ? Error::NOT_VALIDATED
+ : mHal->presentDisplay(mCurrentDisplay, &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 = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+ &displayRequestMask, &requestedLayers, &requestMasks);
+ mResources->setDisplayMustValidateState(mCurrentDisplay, 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 executeAcceptDisplayChanges(uint16_t length) {
+ if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+ return false;
+ }
+
+ auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executePresentDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kPresentDisplayLength) {
+ return false;
+ }
+
+ int presentFence = -1;
+ std::vector<Layer> layers;
+ std::vector<int> fences;
+ auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+ if (err == Error::NONE) {
+ mWriter.setPresentFence(presentFence);
+ mWriter.setReleaseFences(layers, fences);
+ } else {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerCursorPosition(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
+ readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerBuffer(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerBufferLength) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawHandle = readHandle(&useCache);
+ auto fence = readFence();
+ bool closeFence = true;
+
+ const native_handle_t* buffer;
+ ComposerResources::ReplacedBufferHandle replacedBuffer;
+ auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
+ rawHandle, &buffer, &replacedBuffer);
+ if (err == Error::NONE) {
+ err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSurfaceDamage(uint16_t length) {
+ // N rectangles
+ if (length % 4 != 0) {
+ return false;
+ }
+
+ auto damage = readRegion(length / 4);
+ auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerBlendMode(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerColor(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerColorLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerCompositionType(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerDataspace(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerDisplayFrame(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerPlaneAlpha(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSidebandStream(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+ return false;
+ }
+
+ auto rawHandle = readHandle();
+
+ const native_handle_t* stream;
+ ComposerResources::ReplacedStreamHandle replacedStream;
+ auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle,
+ &stream, &replacedStream);
+ if (err == Error::NONE) {
+ err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSourceCrop(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerTransform(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerTransformLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerVisibleRegion(uint16_t length) {
+ // N rectangles
+ if (length % 4 != 0) {
+ return false;
+ }
+
+ auto region = readRegion(length / 4);
+ auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerZOrder(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerZOrderLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ hwc_rect_t readRect() {
+ return hwc_rect_t{
+ readSigned(), readSigned(), readSigned(), readSigned(),
+ };
+ }
+
+ std::vector<hwc_rect_t> 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 readFRect() {
+ return hwc_frect_t{
+ readFloat(), readFloat(), readFloat(), readFloat(),
+ };
+ }
+
+ ComposerHal* mHal;
+ ComposerResources* mResources;
+
+ // 64KiB minus a small space for metadata such as read/write pointers
+ static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+ CommandWriterBase mWriter{kWriterInitialSize};
+
+ Display mCurrentDisplay = 0;
+ Layer mCurrentLayer = 0;
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
new file mode 100644
index 0000000..c9793fd
--- a/dev/null
+++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h
@@ -0,0 +1,137 @@
+/*
+ * 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
+
+#include <string>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
+
+// TODO remove hwcomposer2.h dependency
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+using common::V1_0::ColorMode;
+using common::V1_0::ColorTransform;
+using common::V1_0::Dataspace;
+using common::V1_0::Hdr;
+using common::V1_0::PixelFormat;
+using common::V1_0::Transform;
+
+class ComposerHal {
+ public:
+ virtual ~ComposerHal() = default;
+
+ virtual bool hasCapability(hwc2_capability_t capability) = 0;
+
+ // dump the debug information
+ virtual std::string dumpDebugInfo() = 0;
+
+ class EventCallback {
+ public:
+ virtual ~EventCallback() = default;
+ virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0;
+ virtual void onRefresh(Display display) = 0;
+ virtual void onVsync(Display display, int64_t timestamp) = 0;
+ };
+
+ // Register the event callback object. The event callback object is valid
+ // until it is unregistered. A hotplug event must be generated for each
+ // connected physical display, before or after this function returns.
+ virtual void registerEventCallback(EventCallback* callback) = 0;
+
+ // Unregister the event callback object. It must block if there is any
+ // callback in-flight.
+ virtual void unregisterEventCallback() = 0;
+
+ virtual uint32_t getMaxVirtualDisplayCount() = 0;
+ virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+ Display* outDisplay) = 0;
+ virtual Error destroyVirtualDisplay(Display display) = 0;
+ virtual Error createLayer(Display display, Layer* outLayer) = 0;
+ virtual Error destroyLayer(Display display, Layer layer) = 0;
+
+ virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
+ virtual Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) = 0;
+ virtual Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) = 0;
+ virtual Error getDisplayAttribute(Display display, Config config,
+ IComposerClient::Attribute attribute, int32_t* outValue) = 0;
+ virtual Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) = 0;
+ virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
+ virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0;
+ virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+ virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
+ float* outMaxLuminance, float* outMaxAverageLuminance,
+ float* outMinLuminance) = 0;
+
+ virtual Error setActiveConfig(Display display, Config config) = 0;
+ virtual Error setColorMode(Display display, ColorMode mode) = 0;
+ virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0;
+ virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0;
+
+ virtual Error setColorTransform(Display display, const float* matrix, int32_t hint) = 0;
+ virtual Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+ int32_t dataspace, const std::vector<hwc_rect_t>& damage) = 0;
+ virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
+ int32_t releaseFence) = 0;
+ virtual Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+ std::vector<IComposerClient::Composition>* outCompositionTypes,
+ uint32_t* outDisplayRequestMask,
+ std::vector<Layer>* outRequestedLayers,
+ std::vector<uint32_t>* outRequestMasks) = 0;
+ virtual Error acceptDisplayChanges(Display display) = 0;
+ virtual Error presentDisplay(Display display, int32_t* outPresentFence,
+ std::vector<Layer>* outLayers,
+ std::vector<int32_t>* outReleaseFences) = 0;
+
+ virtual Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0;
+ virtual Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+ int32_t acquireFence) = 0;
+ virtual Error setLayerSurfaceDamage(Display display, Layer layer,
+ const std::vector<hwc_rect_t>& damage) = 0;
+ virtual Error setLayerBlendMode(Display display, Layer layer, int32_t mode) = 0;
+ virtual Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) = 0;
+ virtual Error setLayerCompositionType(Display display, Layer layer, int32_t type) = 0;
+ virtual Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) = 0;
+ virtual Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) = 0;
+ virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0;
+ virtual Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) = 0;
+ virtual Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) = 0;
+ virtual Error setLayerTransform(Display display, Layer layer, int32_t transform) = 0;
+ virtual Error setLayerVisibleRegion(Display display, Layer layer,
+ const std::vector<hwc_rect_t>& visible) = 0;
+ virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
new file mode 100644
index 0000000..18d184e
--- a/dev/null
+++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -0,0 +1,592 @@
+/*
+ * 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 "ComposerResources.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// wrapper for IMapper to import buffers and sideband streams
+class ComposerHandleImporter {
+ public:
+ bool init() {
+ mMapper3 = mapper::V3_0::IMapper::getService();
+ if (mMapper3) {
+ return true;
+ }
+ ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");
+
+ mMapper2 = mapper::V2_0::IMapper::getService();
+ ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
+
+ return mMapper2 != nullptr;
+ }
+
+ Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
+ if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
+ *outBufferHandle = nullptr;
+ return Error::NONE;
+ }
+
+ const native_handle_t* bufferHandle;
+ if (mMapper2) {
+ mapper::V2_0::Error error;
+ mMapper2->importBuffer(
+ rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+ });
+ if (error != mapper::V2_0::Error::NONE) {
+ return Error::NO_RESOURCES;
+ }
+ }
+ if (mMapper3) {
+ mapper::V3_0::Error error;
+ mMapper3->importBuffer(
+ rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+ });
+ if (error != mapper::V3_0::Error::NONE) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outBufferHandle = bufferHandle;
+ return Error::NONE;
+ }
+
+ void freeBuffer(const native_handle_t* bufferHandle) {
+ if (bufferHandle) {
+ if (mMapper2) {
+ mMapper2->freeBuffer(
+ static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+ } else if (mMapper3) {
+ mMapper3->freeBuffer(
+ static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+ }
+ }
+ }
+
+ Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) {
+ const native_handle_t* streamHandle = nullptr;
+ if (rawHandle) {
+ streamHandle = native_handle_clone(rawHandle);
+ if (!streamHandle) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outStreamHandle = streamHandle;
+ return Error::NONE;
+ }
+
+ void freeStream(const native_handle_t* streamHandle) {
+ if (streamHandle) {
+ native_handle_close(streamHandle);
+ native_handle_delete(const_cast<native_handle_t*>(streamHandle));
+ }
+ }
+
+ private:
+ sp<mapper::V2_0::IMapper> mMapper2;
+ sp<mapper::V3_0::IMapper> mMapper3;
+};
+
+class ComposerHandleCache {
+ public:
+ enum class HandleType {
+ INVALID,
+ BUFFER,
+ STREAM,
+ };
+
+ ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize)
+ : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
+
+ // must be initialized later with initCache
+ ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
+
+ ~ComposerHandleCache() {
+ switch (mHandleType) {
+ case HandleType::BUFFER:
+ for (auto handle : mHandles) {
+ mImporter.freeBuffer(handle);
+ }
+ break;
+ case HandleType::STREAM:
+ for (auto handle : mHandles) {
+ mImporter.freeStream(handle);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ComposerHandleCache(const ComposerHandleCache&) = delete;
+ ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
+
+ bool initCache(HandleType type, uint32_t cacheSize) {
+ // already initialized
+ if (mHandleType != HandleType::INVALID) {
+ return false;
+ }
+
+ mHandleType = type;
+ mHandles.resize(cacheSize, nullptr);
+
+ return true;
+ }
+
+ Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
+ if (slot >= 0 && slot < mHandles.size()) {
+ *outHandle = mHandles[slot];
+ return Error::NONE;
+ } else {
+ return Error::BAD_PARAMETER;
+ }
+ }
+
+ Error updateCache(uint32_t slot, const native_handle_t* handle,
+ const native_handle** outReplacedHandle) {
+ if (slot >= 0 && slot < mHandles.size()) {
+ auto& cachedHandle = mHandles[slot];
+ *outReplacedHandle = cachedHandle;
+ cachedHandle = handle;
+ return Error::NONE;
+ } else {
+ return Error::BAD_PARAMETER;
+ }
+ }
+
+ // when fromCache is true, look up in the cache; otherwise, update the cache
+ Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+ if (fromCache) {
+ *outReplacedHandle = nullptr;
+ return lookupCache(slot, outHandle);
+ } else {
+ *outHandle = inHandle;
+ return updateCache(slot, inHandle, outReplacedHandle);
+ }
+ }
+
+ private:
+ ComposerHandleImporter& mImporter;
+ HandleType mHandleType = HandleType::INVALID;
+ std::vector<const native_handle_t*> mHandles;
+};
+
+// layer resource
+class ComposerLayerResource {
+ public:
+ ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize)
+ : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
+ mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
+
+ virtual ~ComposerLayerResource() = default;
+
+ Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
+ return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
+ }
+
+ Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle,
+ outReplacedHandle);
+ }
+
+ protected:
+ ComposerHandleCache mBufferCache;
+ ComposerHandleCache mSidebandStreamCache;
+};
+
+// display resource
+class ComposerDisplayResource {
+ public:
+ enum class DisplayType {
+ PHYSICAL,
+ VIRTUAL,
+ };
+
+ virtual ~ComposerDisplayResource() = default;
+
+ ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : mType(type),
+ mClientTargetCache(importer),
+ mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
+ outputBufferCacheSize),
+ mMustValidate(true) {}
+
+ bool initClientTargetCache(uint32_t cacheSize) {
+ return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
+ }
+
+ bool isVirtual() const { return mType == DisplayType::VIRTUAL; }
+
+ Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle,
+ outReplacedHandle);
+ }
+
+ Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+ outReplacedHandle);
+ }
+
+ bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) {
+ auto result = mLayerResources.emplace(layer, std::move(layerResource));
+ return result.second;
+ }
+
+ bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; }
+
+ ComposerLayerResource* findLayerResource(Layer layer) {
+ auto layerIter = mLayerResources.find(layer);
+ if (layerIter == mLayerResources.end()) {
+ return nullptr;
+ }
+
+ return layerIter->second.get();
+ }
+
+ std::vector<Layer> getLayers() const {
+ std::vector<Layer> layers;
+ layers.reserve(mLayerResources.size());
+ for (const auto& layerKey : mLayerResources) {
+ layers.push_back(layerKey.first);
+ }
+ return layers;
+ }
+
+ void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; }
+
+ bool mustValidate() const { return mMustValidate; }
+
+ protected:
+ const DisplayType mType;
+ ComposerHandleCache mClientTargetCache;
+ ComposerHandleCache mOutputBufferCache;
+ bool mMustValidate;
+
+ std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
+};
+
+class ComposerResources {
+ private:
+ template <bool isBuffer>
+ class ReplacedHandle;
+
+ public:
+ static std::unique_ptr<ComposerResources> create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+ }
+
+ ComposerResources() = default;
+ virtual ~ComposerResources() = default;
+
+ bool init() { return mImporter.init(); }
+
+ using RemoveDisplay =
+ std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
+ void clear(RemoveDisplay removeDisplay) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ for (const auto& displayKey : mDisplayResources) {
+ Display display = displayKey.first;
+ const ComposerDisplayResource& displayResource = *displayKey.second;
+ removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
+ }
+ mDisplayResources.clear();
+ }
+
+ Error addPhysicalDisplay(Display display) {
+ auto displayResource =
+ createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto result = mDisplayResources.emplace(display, std::move(displayResource));
+ return result.second ? Error::NONE : Error::BAD_DISPLAY;
+ }
+
+ Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
+ auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
+ outputBufferCacheSize);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto result = mDisplayResources.emplace(display, std::move(displayResource));
+ return result.second ? Error::NONE : Error::BAD_DISPLAY;
+ }
+
+ Error removeDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
+ }
+
+ Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
+ : Error::BAD_PARAMETER;
+ }
+
+ Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
+ auto layerResource = createLayerResource(bufferCacheSize);
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
+ : Error::BAD_LAYER;
+ }
+
+ Error removeLayer(Display display, Layer layer) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ if (!displayResource) {
+ return Error::BAD_DISPLAY;
+ }
+
+ return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
+ }
+
+ using ReplacedBufferHandle = ReplacedHandle<true>;
+ using ReplacedStreamHandle = ReplacedHandle<false>;
+
+ Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedBufferHandle* outReplacedBuffer) {
+ return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle,
+ outBufferHandle, outReplacedBuffer);
+ }
+
+ Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedBufferHandle* outReplacedBuffer) {
+ return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle,
+ outBufferHandle, outReplacedBuffer);
+ }
+
+ Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
+ ReplacedBufferHandle* outReplacedBuffer) {
+ return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle,
+ outBufferHandle, outReplacedBuffer);
+ }
+
+ Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle,
+ ReplacedStreamHandle* outReplacedStream) {
+ return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle,
+ outStreamHandle, outReplacedStream);
+ }
+
+ void setDisplayMustValidateState(Display display, bool mustValidate) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ displayResource->setMustValidateState(mustValidate);
+ }
+ }
+
+ bool mustValidateDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ return displayResource->mustValidate();
+ }
+ return false;
+ }
+
+ protected:
+ virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
+ return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+ }
+
+ virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) {
+ return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
+ }
+
+ ComposerDisplayResource* findDisplayResourceLocked(Display display) {
+ auto iter = mDisplayResources.find(display);
+ if (iter == mDisplayResources.end()) {
+ return nullptr;
+ }
+ return iter->second.get();
+ }
+
+ ComposerHandleImporter mImporter;
+
+ std::mutex mDisplayResourcesMutex;
+ std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
+
+ private:
+ enum class Cache {
+ CLIENT_TARGET,
+ OUTPUT_BUFFER,
+ LAYER_BUFFER,
+ LAYER_SIDEBAND_STREAM,
+ };
+
+ // When a buffer in the cache is replaced by a new one, we must keep it
+ // alive until it has been replaced in ComposerHal.
+ template <bool isBuffer>
+ class ReplacedHandle {
+ public:
+ ReplacedHandle() = default;
+ ReplacedHandle(const ReplacedHandle&) = delete;
+ ReplacedHandle& operator=(const ReplacedHandle&) = delete;
+
+ ~ReplacedHandle() { reset(); }
+
+ void reset(ComposerHandleImporter* importer = nullptr,
+ const native_handle_t* handle = nullptr) {
+ if (mHandle) {
+ if (isBuffer) {
+ mImporter->freeBuffer(mHandle);
+ } else {
+ mImporter->freeStream(mHandle);
+ }
+ }
+
+ mImporter = importer;
+ mHandle = handle;
+ }
+
+ private:
+ ComposerHandleImporter* mImporter = nullptr;
+ const native_handle_t* mHandle = nullptr;
+ };
+
+ template <Cache cache, bool isBuffer>
+ Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outHandle,
+ ReplacedHandle<isBuffer>* outReplacedHandle) {
+ Error error;
+
+ // import the raw handle (or ignore raw handle when fromCache is true)
+ const native_handle_t* importedHandle = nullptr;
+ if (!fromCache) {
+ error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle)
+ : mImporter.importStream(rawHandle, &importedHandle);
+ if (error != Error::NONE) {
+ return error;
+ }
+ }
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+ // find display/layer resource
+ const bool needLayerResource =
+ (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM);
+ ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
+ ComposerLayerResource* layerResource = (displayResource && needLayerResource)
+ ? displayResource->findLayerResource(layer)
+ : nullptr;
+
+ // lookup or update cache
+ const native_handle_t* replacedHandle = nullptr;
+ if (displayResource && (!needLayerResource || layerResource)) {
+ switch (cache) {
+ case Cache::CLIENT_TARGET:
+ error = displayResource->getClientTarget(slot, fromCache, importedHandle,
+ outHandle, &replacedHandle);
+ break;
+ case Cache::OUTPUT_BUFFER:
+ error = displayResource->getOutputBuffer(slot, fromCache, importedHandle,
+ outHandle, &replacedHandle);
+ break;
+ case Cache::LAYER_BUFFER:
+ error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case Cache::LAYER_SIDEBAND_STREAM:
+ error = layerResource->getSidebandStream(slot, fromCache, importedHandle,
+ outHandle, &replacedHandle);
+ break;
+ default:
+ error = Error::BAD_PARAMETER;
+ break;
+ }
+
+ if (error != Error::NONE) {
+ ALOGW("invalid cache %d slot %d", int(cache), int(slot));
+ }
+ } else if (!displayResource) {
+ error = Error::BAD_DISPLAY;
+ } else {
+ error = Error::BAD_LAYER;
+ }
+
+ // clean up on errors
+ if (error != Error::NONE) {
+ if (!fromCache) {
+ if (isBuffer) {
+ mImporter.freeBuffer(importedHandle);
+ } else {
+ mImporter.freeStream(importedHandle);
+ }
+ }
+ return error;
+ }
+
+ outReplacedHandle->reset(&mImporter, replacedHandle);
+
+ return Error::NONE;
+ }
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/passthrough/Android.bp b/service/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4d3c976
--- a/dev/null
+++ b/service/2.1/utils/passthrough/Android.bp
@@ -0,0 +1,22 @@
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.1-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "libhardware",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ ],
+ export_shared_lib_headers: [
+ "libhardware",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
new file mode 100644
index 0000000..5826b12
--- a/dev/null
+++ b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -0,0 +1,679 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <atomic>
+#include <cstring> // for strerror
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+namespace detail {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public Hal {
+ public:
+ virtual ~HwcHalImpl() {
+ if (mDevice) {
+ hwc2_close(mDevice);
+ }
+ }
+
+ bool initWithModule(const hw_module_t* module) {
+ hwc2_device_t* device;
+ int result = hwc2_open(module, &device);
+ if (result) {
+ ALOGE("failed to open hwcomposer2 device: %s", strerror(-result));
+ return false;
+ }
+
+ return initWithDevice(std::move(device), true);
+ }
+
+ bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) {
+ // we own the device from this point on
+ mDevice = device;
+
+ initCapabilities();
+ if (requireReliablePresentFence &&
+ hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) {
+ ALOGE("present fence must be reliable");
+ mDevice->common.close(&mDevice->common);
+ mDevice = nullptr;
+ return false;
+ }
+
+ if (!initDispatch()) {
+ mDevice->common.close(&mDevice->common);
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool hasCapability(hwc2_capability_t capability) override {
+ return (mCapabilities.count(capability) > 0);
+ }
+
+ std::string dumpDebugInfo() override {
+ uint32_t len = 0;
+ mDispatch.dump(mDevice, &len, nullptr);
+
+ std::vector<char> buf(len + 1);
+ mDispatch.dump(mDevice, &len, buf.data());
+ buf.resize(len + 1);
+ buf[len] = '\0';
+
+ return buf.data();
+ }
+
+ void registerEventCallback(hal::ComposerHal::EventCallback* callback) override {
+ mEventCallback = callback;
+
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+ reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+ reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+ }
+
+ void unregisterEventCallback() override {
+ // we assume the callback functions
+ //
+ // - can be unregistered
+ // - can be in-flight
+ // - will never be called afterward
+ //
+ // which is likely incorrect
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+ mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr);
+
+ mEventCallback = nullptr;
+ }
+
+ uint32_t getMaxVirtualDisplayCount() override {
+ return mDispatch.getMaxVirtualDisplayCount(mDevice);
+ }
+
+ Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+ Display* outDisplay) override {
+ int32_t hwc_format = static_cast<int32_t>(*format);
+ int32_t err =
+ mDispatch.createVirtualDisplay(mDevice, width, height, &hwc_format, outDisplay);
+ *format = static_cast<PixelFormat>(hwc_format);
+
+ return static_cast<Error>(err);
+ }
+
+ Error destroyVirtualDisplay(Display display) override {
+ int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
+ return static_cast<Error>(err);
+ }
+
+ Error createLayer(Display display, Layer* outLayer) override {
+ int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
+ return static_cast<Error>(err);
+ }
+
+ Error destroyLayer(Display display, Layer layer) override {
+ int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+ onLayerDestroyed(display, layer);
+ return static_cast<Error>(err);
+ }
+
+ Error getActiveConfig(Display display, Config* outConfig) override {
+ int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
+ return static_cast<Error>(err);
+ }
+
+ Error getClientTargetSupport(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) override {
+ int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height,
+ static_cast<int32_t>(format),
+ static_cast<int32_t>(dataspace));
+ return static_cast<Error>(err);
+ }
+
+ Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override {
+ uint32_t count = 0;
+ int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ outModes->resize(count);
+ err = mDispatch.getColorModes(
+ mDevice, display, &count,
+ reinterpret_cast<std::underlying_type<ColorMode>::type*>(outModes->data()));
+ if (err != HWC2_ERROR_NONE) {
+ *outModes = hidl_vec<ColorMode>();
+ return static_cast<Error>(err);
+ }
+
+ return Error::NONE;
+ }
+
+ Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
+ int32_t* outValue) override {
+ int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
+ static_cast<int32_t>(attribute), outValue);
+ return static_cast<Error>(err);
+ }
+
+ Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override {
+ uint32_t count = 0;
+ int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ outConfigs->resize(count);
+ err = mDispatch.getDisplayConfigs(mDevice, display, &count, outConfigs->data());
+ if (err != HWC2_ERROR_NONE) {
+ *outConfigs = hidl_vec<Config>();
+ return static_cast<Error>(err);
+ }
+
+ return Error::NONE;
+ }
+
+ Error getDisplayName(Display display, hidl_string* outName) override {
+ uint32_t count = 0;
+ int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ std::vector<char> buf(count + 1);
+ err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+ buf.resize(count + 1);
+ buf[count] = '\0';
+
+ *outName = buf.data();
+
+ return Error::NONE;
+ }
+
+ Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override {
+ int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
+ int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
+ *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
+
+ return static_cast<Error>(err);
+ }
+
+ Error getDozeSupport(Display display, bool* outSupport) override {
+ int32_t hwc_support = 0;
+ int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
+ *outSupport = hwc_support;
+
+ return static_cast<Error>(err);
+ }
+
+ Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance) override {
+ uint32_t count = 0;
+ int32_t err =
+ mDispatch.getHdrCapabilities(mDevice, display, &count, nullptr, outMaxLuminance,
+ outMaxAverageLuminance, outMinLuminance);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ outTypes->resize(count);
+ err = mDispatch.getHdrCapabilities(
+ mDevice, display, &count,
+ reinterpret_cast<std::underlying_type<Hdr>::type*>(outTypes->data()), outMaxLuminance,
+ outMaxAverageLuminance, outMinLuminance);
+ if (err != HWC2_ERROR_NONE) {
+ *outTypes = hidl_vec<Hdr>();
+ return static_cast<Error>(err);
+ }
+
+ return Error::NONE;
+ }
+
+ Error setActiveConfig(Display display, Config config) override {
+ int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
+ return static_cast<Error>(err);
+ }
+
+ Error setColorMode(Display display, ColorMode mode) override {
+ int32_t err = mDispatch.setColorMode(mDevice, display, static_cast<int32_t>(mode));
+ return static_cast<Error>(err);
+ }
+
+ Error setPowerMode(Display display, IComposerClient::PowerMode mode) override {
+ int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast<int32_t>(mode));
+ return static_cast<Error>(err);
+ }
+
+ Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
+ int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast<int32_t>(enabled));
+ return static_cast<Error>(err);
+ }
+
+ Error setColorTransform(Display display, const float* matrix, int32_t hint) override {
+ int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
+ return static_cast<Error>(err);
+ }
+
+ Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence,
+ int32_t dataspace, const std::vector<hwc_rect_t>& damage) override {
+ hwc_region region = {damage.size(), damage.data()};
+ int32_t err =
+ mDispatch.setClientTarget(mDevice, display, target, acquireFence, dataspace, region);
+ return static_cast<Error>(err);
+ }
+
+ Error setOutputBuffer(Display display, buffer_handle_t buffer, int32_t releaseFence) override {
+ int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, releaseFence);
+ // unlike in setClientTarget, releaseFence is owned by us
+ if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
+ close(releaseFence);
+ }
+
+ return static_cast<Error>(err);
+ }
+
+ Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers,
+ std::vector<IComposerClient::Composition>* outCompositionTypes,
+ uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
+ std::vector<uint32_t>* outRequestMasks) override {
+ onBeforeValidateDisplay(display);
+ uint32_t typesCount = 0;
+ uint32_t reqsCount = 0;
+ int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
+
+ if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+ return static_cast<Error>(err);
+ }
+
+ err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ std::vector<Layer> changedLayers(typesCount);
+ std::vector<IComposerClient::Composition> compositionTypes(typesCount);
+ err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(),
+ compositionTypes.data());
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ int32_t displayReqs = 0;
+ err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, nullptr,
+ nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ std::vector<Layer> requestedLayers(reqsCount);
+ std::vector<uint32_t> requestMasks(reqsCount);
+ err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount,
+ requestedLayers.data(),
+ reinterpret_cast<int32_t*>(requestMasks.data()));
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ *outChangedLayers = std::move(changedLayers);
+ *outCompositionTypes = std::move(compositionTypes);
+ *outDisplayRequestMask = displayReqs;
+ *outRequestedLayers = std::move(requestedLayers);
+ *outRequestMasks = std::move(requestMasks);
+
+ return static_cast<Error>(err);
+ }
+
+ Error acceptDisplayChanges(Display display) override {
+ int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
+ return static_cast<Error>(err);
+ }
+
+ Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers,
+ std::vector<int32_t>* outReleaseFences) override {
+ *outPresentFence = -1;
+ int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
+ if (err != HWC2_ERROR_NONE) {
+ return static_cast<Error>(err);
+ }
+
+ uint32_t count = 0;
+ err = mDispatch.getReleaseFences(mDevice, display, &count, nullptr, nullptr);
+ if (err != HWC2_ERROR_NONE) {
+ ALOGW("failed to get release fences");
+ return Error::NONE;
+ }
+
+ outLayers->resize(count);
+ outReleaseFences->resize(count);
+ err = mDispatch.getReleaseFences(mDevice, display, &count, outLayers->data(),
+ outReleaseFences->data());
+ if (err != HWC2_ERROR_NONE) {
+ ALOGW("failed to get release fences");
+ outLayers->clear();
+ outReleaseFences->clear();
+ return Error::NONE;
+ }
+
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override {
+ int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer,
+ int32_t acquireFence) override {
+ int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, buffer, acquireFence);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerSurfaceDamage(Display display, Layer layer,
+ const std::vector<hwc_rect_t>& damage) override {
+ hwc_region region = {damage.size(), damage.data()};
+ int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, region);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override {
+ int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) override {
+ hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
+ int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerCompositionType(Display display, Layer layer, int32_t type) override {
+ int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, type);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) override {
+ int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, dataspace);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) override {
+ int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, frame);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override {
+ int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) override {
+ int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, stream);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) override {
+ int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerTransform(Display display, Layer layer, int32_t transform) override {
+ int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, transform);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerVisibleRegion(Display display, Layer layer,
+ const std::vector<hwc_rect_t>& visible) override {
+ hwc_region_t region = {visible.size(), visible.data()};
+ int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, region);
+ return static_cast<Error>(err);
+ }
+
+ Error setLayerZOrder(Display display, Layer layer, uint32_t z) override {
+ int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
+ return static_cast<Error>(err);
+ }
+
+ protected:
+ virtual void initCapabilities() {
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> caps(count);
+ mDevice->getCapabilities(mDevice, &count, caps.data());
+ caps.resize(count);
+
+ mCapabilities.reserve(count);
+ for (auto cap : caps) {
+ mCapabilities.insert(static_cast<hwc2_capability_t>(cap));
+ }
+ }
+
+ template <typename T>
+ bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (pfn) {
+ *outPfn = reinterpret_cast<T>(pfn);
+ return true;
+ } else {
+ ALOGE("failed to get hwcomposer2 function %d", desc);
+ return false;
+ }
+ }
+
+ virtual bool initDispatch() {
+ if (!initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, &mDispatch.acceptDisplayChanges) ||
+ !initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer) ||
+ !initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, &mDispatch.createVirtualDisplay) ||
+ !initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer) ||
+ !initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+ &mDispatch.destroyVirtualDisplay) ||
+ !initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump) ||
+ !initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig) ||
+ !initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+ &mDispatch.getChangedCompositionTypes) ||
+ !initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+ &mDispatch.getClientTargetSupport) ||
+ !initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes) ||
+ !initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, &mDispatch.getDisplayAttribute) ||
+ !initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, &mDispatch.getDisplayConfigs) ||
+ !initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName) ||
+ !initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, &mDispatch.getDisplayRequests) ||
+ !initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType) ||
+ !initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport) ||
+ !initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, &mDispatch.getHdrCapabilities) ||
+ !initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+ &mDispatch.getMaxVirtualDisplayCount) ||
+ !initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, &mDispatch.getReleaseFences) ||
+ !initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay) ||
+ !initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback) ||
+ !initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig) ||
+ !initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget) ||
+ !initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode) ||
+ !initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, &mDispatch.setColorTransform) ||
+ !initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, &mDispatch.setCursorPosition) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, &mDispatch.setLayerBlendMode) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+ &mDispatch.setLayerCompositionType) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, &mDispatch.setLayerDataspace) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, &mDispatch.setLayerDisplayFrame) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, &mDispatch.setLayerPlaneAlpha)) {
+ return false;
+ }
+
+ if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) {
+ if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+ &mDispatch.setLayerSidebandStream)) {
+ return false;
+ }
+ }
+
+ if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, &mDispatch.setLayerSourceCrop) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+ &mDispatch.setLayerSurfaceDamage) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, &mDispatch.setLayerTransform) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+ &mDispatch.setLayerVisibleRegion) ||
+ !initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder) ||
+ !initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer) ||
+ !initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode) ||
+ !initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled) ||
+ !initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) {
+ return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers,
+ outCompositionTypes);
+ }
+ virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {}
+ virtual void onBeforeValidateDisplay(Display /* display */) {}
+
+ static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+ int32_t connected) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback->onHotplug(display,
+ static_cast<IComposerCallback::Connection>(connected));
+ }
+
+ static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback->onRefresh(display);
+ }
+
+ static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+ int64_t timestamp) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback->onVsync(display, timestamp);
+ }
+
+ int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) {
+ return mDispatch.getChangedCompositionTypes(
+ mDevice, display, outTypesCount, outChangedLayers,
+ reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+ outCompositionTypes));
+ }
+
+ hwc2_device_t* mDevice = nullptr;
+
+ std::unordered_set<hwc2_capability_t> mCapabilities;
+
+ struct {
+ HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
+ HWC2_PFN_CREATE_LAYER createLayer;
+ HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
+ HWC2_PFN_DESTROY_LAYER destroyLayer;
+ HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
+ HWC2_PFN_DUMP dump;
+ HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
+ HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
+ HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
+ HWC2_PFN_GET_COLOR_MODES getColorModes;
+ HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
+ HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
+ HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
+ HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
+ HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
+ HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
+ HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
+ HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
+ HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
+ HWC2_PFN_PRESENT_DISPLAY presentDisplay;
+ HWC2_PFN_REGISTER_CALLBACK registerCallback;
+ HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
+ HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
+ HWC2_PFN_SET_COLOR_MODE setColorMode;
+ HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
+ HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
+ HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
+ HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
+ HWC2_PFN_SET_LAYER_COLOR setLayerColor;
+ HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
+ HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
+ HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
+ HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
+ HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
+ HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
+ HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
+ HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
+ HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
+ HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
+ HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
+ HWC2_PFN_SET_POWER_MODE setPowerMode;
+ HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
+ HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
+ } mDispatch = {};
+
+ hal::ComposerHal::EventCallback* mEventCallback = nullptr;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
new file mode 100644
index 0000000..33c914d
--- a/dev/null
+++ b/service/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <composer-hal/2.1/Composer.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+#include <hardware/fb.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer2.h>
+#include <hwc2on1adapter/HWC2On1Adapter.h>
+#include <hwc2onfbadapter/HWC2OnFbAdapter.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace passthrough {
+
+class HwcLoader {
+ public:
+ static IComposer* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+
+ auto hal = createHalWithAdapter(module);
+ if (!hal) {
+ return nullptr;
+ }
+
+ return createComposer(std::move(hal));
+ }
+
+ // load hwcomposer2 module
+ static const hw_module_t* loadModule() {
+ const hw_module_t* module;
+ int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
+ if (error) {
+ ALOGI("falling back to gralloc module");
+ error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ }
+
+ if (error) {
+ ALOGE("failed to get hwcomposer or gralloc module");
+ return nullptr;
+ }
+
+ return module;
+ }
+
+ // create a ComposerHal instance
+ static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+
+ // create a ComposerHal instance, insert an adapter if necessary
+ static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+ bool adapted;
+ hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+ if (!device) {
+ return nullptr;
+ }
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+ }
+
+ // create an IComposer instance
+ static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+ return hal::Composer::create(std::move(hal)).release();
+ }
+
+ protected:
+ // open hwcomposer2 device, install an adapter if necessary
+ static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) {
+ if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) {
+ *outAdapted = true;
+ return adaptGrallocModule(module);
+ }
+
+ hw_device_t* device;
+ int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+ if (error) {
+ ALOGE("failed to open hwcomposer device: %s", strerror(-error));
+ return nullptr;
+ }
+
+ int major = (device->version >> 24) & 0xf;
+ if (major != 2) {
+ *outAdapted = true;
+ return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device)));
+ }
+
+ *outAdapted = false;
+ return reinterpret_cast<hwc2_device_t*>(device);
+ }
+
+ private:
+ static hwc2_device_t* adaptGrallocModule(const hw_module_t* module) {
+ framebuffer_device_t* device;
+ int error = framebuffer_open(module, &device);
+ if (error) {
+ ALOGE("failed to open framebuffer device: %s", strerror(-error));
+ return nullptr;
+ }
+
+ return new HWC2OnFbAdapter(device);
+ }
+
+ static hwc2_device_t* adaptHwc1Device(hwc_composer_device_1* device) {
+ int minor = (device->common.version >> 16) & 0xf;
+ if (minor < 1) {
+ ALOGE("hwcomposer 1.0 is not supported");
+ device->common.close(&device->common);
+ return nullptr;
+ }
+
+ return new HWC2On1Adapter(device);
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.2/utils/passthrough/Android.bp b/service/2.2/utils/passthrough/Android.bp
new file mode 100644
index 0000000..318ce91
--- a/dev/null
+++ b/service/2.2/utils/passthrough/Android.bp
@@ -0,0 +1,14 @@
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.2-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-passthrough",
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-passthrough",
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
new file mode 100644
index 0000000..93da0a5
--- a/dev/null
+++ b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -0,0 +1,301 @@
+/*
+ * 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 "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
+ public:
+ // XXX when can we return Error::UNSUPPORTED?
+
+ Error getPerFrameMetadataKeys(
+ Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override {
+ if (!mDispatch.getPerFrameMetadataKeys) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t count = 0;
+ int32_t error = mDispatch.getPerFrameMetadataKeys(mDevice, display, &count, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ std::vector<IComposerClient::PerFrameMetadataKey> keys(count);
+ error = mDispatch.getPerFrameMetadataKeys(
+ mDevice, display, &count,
+ reinterpret_cast<std::underlying_type<IComposerClient::PerFrameMetadataKey>::type*>(
+ keys.data()));
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ keys.resize(count);
+ *outKeys = std::move(keys);
+ return Error::NONE;
+ }
+
+ Error setLayerPerFrameMetadata(
+ Display display, Layer layer,
+ const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+ if (!mDispatch.setLayerPerFrameMetadata) {
+ return Error::UNSUPPORTED;
+ }
+
+ 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);
+ }
+
+ int32_t error = mDispatch.setLayerPerFrameMetadata(mDevice, display, layer, metadata.size(),
+ keys.data(), values.data());
+ return static_cast<Error>(error);
+ }
+
+ Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+ Dataspace* outDataspace) override {
+ if (!mDispatch.getReadbackBufferAttributes) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t format = 0;
+ int32_t dataspace = 0;
+ int32_t error =
+ mDispatch.getReadbackBufferAttributes(mDevice, display, &format, &dataspace);
+ if (error == HWC2_ERROR_NONE) {
+ *outFormat = static_cast<PixelFormat>(format);
+ *outDataspace = static_cast<Dataspace>(dataspace);
+ }
+ return static_cast<Error>(error);
+ }
+
+ Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+ base::unique_fd fenceFd) override {
+ if (!mDispatch.setReadbackBuffer) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error =
+ mDispatch.setReadbackBuffer(mDevice, display, bufferHandle, fenceFd.release());
+ return static_cast<Error>(error);
+ }
+
+ Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) override {
+ if (!mDispatch.getReadbackBufferFence) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t fenceFd = -1;
+ int32_t error = mDispatch.getReadbackBufferFence(mDevice, display, &fenceFd);
+ outFenceFd->reset(fenceFd);
+ return static_cast<Error>(error);
+ }
+
+ Error createVirtualDisplay_2_2(uint32_t width, uint32_t height, PixelFormat* format,
+ Display* outDisplay) override {
+ return createVirtualDisplay(
+ width, height, reinterpret_cast<common::V1_0::PixelFormat*>(format), outDisplay);
+ }
+
+ Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) override {
+ return getClientTargetSupport(display, width, height,
+ static_cast<common::V1_0::PixelFormat>(format),
+ static_cast<common::V1_0::Dataspace>(dataspace));
+ }
+
+ Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+ if (mode == IComposerClient::PowerMode::ON_SUSPEND) {
+ return Error::UNSUPPORTED;
+ }
+ return setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode));
+ }
+
+ Error setLayerFloatColor(Display display, Layer layer,
+ IComposerClient::FloatColor color) override {
+ if (!mDispatch.setLayerFloatColor) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error = mDispatch.setLayerFloatColor(
+ mDevice, display, layer, hwc_float_color{color.r, color.g, color.b, color.a});
+ return static_cast<Error>(error);
+ }
+
+ Error getColorModes_2_2(Display display, hidl_vec<ColorMode>* outModes) override {
+ return getColorModes(display,
+ reinterpret_cast<hidl_vec<common::V1_0::ColorMode>*>(outModes));
+ }
+
+ Error getRenderIntents(Display display, ColorMode mode,
+ std::vector<RenderIntent>* outIntents) override {
+ if (!mDispatch.getRenderIntents) {
+ *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC});
+ return Error::NONE;
+ }
+
+ uint32_t count = 0;
+ int32_t error =
+ mDispatch.getRenderIntents(mDevice, display, int32_t(mode), &count, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ std::vector<RenderIntent> intents(count);
+ error = mDispatch.getRenderIntents(
+ mDevice, display, int32_t(mode), &count,
+ reinterpret_cast<std::underlying_type<RenderIntent>::type*>(intents.data()));
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ intents.resize(count);
+
+ *outIntents = std::move(intents);
+ return Error::NONE;
+ }
+
+ Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
+ if (!mDispatch.setColorModeWithRenderIntent) {
+ if (intent != RenderIntent::COLORIMETRIC) {
+ return Error::UNSUPPORTED;
+ }
+ return setColorMode(display, static_cast<common::V1_0::ColorMode>(mode));
+ }
+
+ int32_t err = mDispatch.setColorModeWithRenderIntent(
+ mDevice, display, static_cast<int32_t>(mode), static_cast<int32_t>(intent));
+ return static_cast<Error>(err);
+ }
+
+ std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace) override {
+ std::array<float, 16> matrix;
+
+ int32_t error = HWC2_ERROR_UNSUPPORTED;
+ if (mDispatch.getDataspaceSaturationMatrix) {
+ error = mDispatch.getDataspaceSaturationMatrix(mDevice, static_cast<int32_t>(dataspace),
+ matrix.data());
+ }
+ if (error != HWC2_ERROR_NONE) {
+ return std::array<float, 16>{
+ 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,
+ };
+ }
+
+ return matrix;
+ }
+
+ protected:
+ template <typename T>
+ bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (pfn) {
+ *outPfn = reinterpret_cast<T>(pfn);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool initDispatch() override {
+ if (!BaseType2_1::initDispatch()) {
+ return false;
+ }
+
+ initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor);
+
+ initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA,
+ &mDispatch.setLayerPerFrameMetadata);
+ initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS,
+ &mDispatch.getPerFrameMetadataKeys);
+
+ initOptionalDispatch(HWC2_FUNCTION_SET_READBACK_BUFFER, &mDispatch.setReadbackBuffer);
+ initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_ATTRIBUTES,
+ &mDispatch.getReadbackBufferAttributes);
+ initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE,
+ &mDispatch.getReadbackBufferFence);
+
+ initOptionalDispatch(HWC2_FUNCTION_GET_RENDER_INTENTS, &mDispatch.getRenderIntents);
+ initOptionalDispatch(HWC2_FUNCTION_SET_COLOR_MODE_WITH_RENDER_INTENT,
+ &mDispatch.setColorModeWithRenderIntent);
+ initOptionalDispatch(HWC2_FUNCTION_GET_DATASPACE_SATURATION_MATRIX,
+ &mDispatch.getDataspaceSaturationMatrix);
+
+ return true;
+ }
+
+ struct {
+ HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
+ HWC2_PFN_SET_LAYER_PER_FRAME_METADATA setLayerPerFrameMetadata;
+ HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys;
+ HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer;
+ HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes;
+ HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence;
+ HWC2_PFN_GET_RENDER_INTENTS getRenderIntents;
+ HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT setColorModeWithRenderIntent;
+ HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX getDataspaceSaturationMatrix;
+ } mDispatch = {};
+
+ private:
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::getColorModes;
+ using BaseType2_1::mDevice;
+ using BaseType2_1::setColorMode;
+ using BaseType2_1::createVirtualDisplay;
+ using BaseType2_1::getClientTargetSupport;
+ using BaseType2_1::setPowerMode;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
new file mode 100644
index 0000000..cb4a238
--- a/dev/null
+++ b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * 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 "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.2/Composer.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace passthrough {
+
+class HwcLoader : public V2_1::passthrough::HwcLoader {
+ public:
+ static IComposer* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+
+ auto hal = createHalWithAdapter(module);
+ if (!hal) {
+ return nullptr;
+ }
+
+ return createComposer(std::move(hal)).release();
+ }
+
+ // create a ComposerHal instance
+ static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+
+ // create a ComposerHal instance, insert an adapter if necessary
+ static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+ bool adapted;
+ hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+ if (!device) {
+ return nullptr;
+ }
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+ }
+
+ // create an IComposer instance
+ static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+ return hal::Composer::create(std::move(hal));
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.3/default/Android.bp b/service/2.3/default/Android.bp
new file mode 100644
index 0000000..07afd6c
--- a/dev/null
+++ b/service/2.3/default/Android.bp
@@ -0,0 +1,46 @@
+//
+// Copyright (C) 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.
+//
+
+cc_binary {
+ name: "android.hardware.graphics.composer@2.3-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.3-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.3-passthrough",
+ ],
+ shared_libs: [
+ "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@3.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
diff --git a/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc
new file mode 100644
index 0000000..81ce890
--- a/dev/null
+++ b/service/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -0,0 +1,7 @@
+service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@2.3-service
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
+ writepid /dev/cpuset/system-background/tasks
diff --git a/service/2.3/default/service.cpp b/service/2.3/default/service.cpp
new file mode 100644
index 0000000..347d8be
--- a/dev/null
+++ b/service/2.3/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#include <sched.h>
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.3/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_3::IComposer;
+using android::hardware::graphics::composer::V2_3::passthrough::HwcLoader;
+
+int main() {
+ // the conventional HAL might start binder services
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+ android::ProcessState::self()->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);
+ }
+
+ android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+ android::sp<IComposer> composer = HwcLoader::load();
+ if (composer == nullptr) {
+ return 1;
+ }
+ if (composer->registerAsService() != android::NO_ERROR) {
+ ALOGE("failed to register service");
+ return 1;
+ }
+
+ android::hardware::joinRpcThreadpool();
+
+ ALOGE("service is terminating");
+ return 1;
+}
diff --git a/service/2.3/utils/passthrough/Android.bp b/service/2.3/utils/passthrough/Android.bp
new file mode 100644
index 0000000..3ae6b16
--- a/dev/null
+++ b/service/2.3/utils/passthrough/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 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.
+//
+
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.3-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
new file mode 100644
index 0000000..d3b29bb
--- a/dev/null
+++ b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -0,0 +1,441 @@
+/*
+ * 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 "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_1::RenderIntent;
+using common::V1_2::ColorMode;
+using common::V1_2::Dataspace;
+using common::V1_2::Hdr;
+using common::V1_2::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+
+namespace {
+
+bool isIdentityMatrix(const float* matrix) {
+ if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 &&
+ matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 &&
+ matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 &&
+ matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
+ public:
+ Error getPerFrameMetadataKeys_2_3(
+ Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override {
+ std::vector<V2_2::IComposerClient::PerFrameMetadataKey> castKeys;
+ Error error = getPerFrameMetadataKeys(display, &castKeys);
+ if (error != Error::NONE) {
+ return error;
+ }
+ outKeys->clear();
+ for (auto key : castKeys) {
+ outKeys->push_back(static_cast<IComposerClient::PerFrameMetadataKey>(key));
+ }
+ return Error::NONE;
+ }
+
+ Error setLayerPerFrameMetadata_2_3(
+ Display display, Layer layer,
+ const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+ return setLayerPerFrameMetadata(
+ display, layer,
+ reinterpret_cast<const std::vector<V2_2::IComposerClient::PerFrameMetadata>&>(
+ metadata));
+ }
+
+ Error setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) override {
+ return setColorMode_2_2(display, static_cast<common::V1_1::ColorMode>(mode), intent);
+ }
+
+ Error getRenderIntents_2_3(Display display, ColorMode mode,
+ std::vector<RenderIntent>* outIntents) override {
+ return getRenderIntents(display, static_cast<common::V1_1::ColorMode>(mode), outIntents);
+ }
+
+ Error getColorModes_2_3(Display display, hidl_vec<ColorMode>* outModes) override {
+ return getColorModes_2_2(display,
+ reinterpret_cast<hidl_vec<common::V1_1::ColorMode>*>(outModes));
+ }
+
+ Error getHdrCapabilities_2_3(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance,
+ float* outMaxAverageLuminance, float* outMinLuminance) override {
+ return getHdrCapabilities(display, reinterpret_cast<hidl_vec<common::V1_0::Hdr>*>(outTypes),
+ outMaxLuminance, outMaxAverageLuminance, outMinLuminance);
+ }
+
+ Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) override {
+ return getClientTargetSupport_2_2(display, width, height,
+ static_cast<common::V1_1::PixelFormat>(format),
+ static_cast<common::V1_1::Dataspace>(dataspace));
+ }
+
+ Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
+ Dataspace* outDataspace) override {
+ return getReadbackBufferAttributes(
+ display, reinterpret_cast<common::V1_1::PixelFormat*>(outFormat),
+ reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
+ }
+
+ Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) override {
+ if (!mDispatch.getDisplayIdentificationData) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t size = 0;
+ int32_t error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ std::vector<uint8_t> data(size);
+ error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, data.data());
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ data.resize(size);
+ *outData = std::move(data);
+ return Error::NONE;
+ }
+
+ Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override {
+ if (!mDispatch.setLayerColorTransform) {
+ if (isIdentityMatrix(matrix)) {
+ // If an identity matrix is set, then we can remove the layer from client
+ // composition list.
+ mClientCompositionLayers[display].erase(layer);
+ return Error::UNSUPPORTED;
+ }
+ // if setLayerColorTransform is not implemented, per spec we want to make sure the
+ // layer marked as client composition, and thus we maintain a list, and mark all these
+ // layers as client composition later before validate the display.
+ mClientCompositionLayers[display].insert(layer);
+ return Error::UNSUPPORTED;
+ }
+ int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix);
+ return static_cast<Error>(err);
+ }
+
+ Error getDisplayedContentSamplingAttributes(
+ uint64_t display, PixelFormat& format, Dataspace& dataspace,
+ hidl_bitfield<IComposerClient::FormatColorComponent>& componentMask) override {
+ if (!mDispatch.getDisplayedContentSamplingAttributes) {
+ return Error::UNSUPPORTED;
+ }
+ int32_t formatRaw = 0;
+ int32_t dataspaceRaw = 0;
+ uint8_t componentMaskRaw = 0;
+ int32_t errorRaw = mDispatch.getDisplayedContentSamplingAttributes(
+ mDevice, display, &formatRaw, &dataspaceRaw, &componentMaskRaw);
+ auto error = static_cast<Error>(errorRaw);
+ if (error == Error::NONE) {
+ format = static_cast<PixelFormat>(formatRaw);
+ dataspace = static_cast<Dataspace>(dataspaceRaw);
+ componentMask =
+ static_cast<hidl_bitfield<IComposerClient::FormatColorComponent>>(componentMaskRaw);
+ }
+ return error;
+ };
+
+ Error setDisplayedContentSamplingEnabled(
+ uint64_t display, IComposerClient::DisplayedContentSampling enable,
+ hidl_bitfield<IComposerClient::FormatColorComponent> componentMask,
+ uint64_t maxFrames) override {
+ if (!mDispatch.setDisplayedContentSamplingEnabled) {
+ return Error::UNSUPPORTED;
+ }
+ return static_cast<Error>(mDispatch.setDisplayedContentSamplingEnabled(
+ mDevice, display, static_cast<int32_t>(enable), componentMask, maxFrames));
+ }
+
+ Error getDisplayedContentSample(uint64_t display, uint64_t maxFrames, uint64_t timestamp,
+ uint64_t& frameCount, hidl_vec<uint64_t>& sampleComponent0,
+ hidl_vec<uint64_t>& sampleComponent1,
+ hidl_vec<uint64_t>& sampleComponent2,
+ hidl_vec<uint64_t>& sampleComponent3) override {
+ if (!mDispatch.getDisplayedContentSample) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t size[4] = {0};
+ auto errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp,
+ &frameCount, size, nullptr);
+ if (errorRaw != HWC2_ERROR_NONE) {
+ return static_cast<Error>(errorRaw);
+ }
+
+ sampleComponent0.resize(size[0]);
+ sampleComponent1.resize(size[1]);
+ sampleComponent2.resize(size[2]);
+ sampleComponent3.resize(size[3]);
+ uint64_t* samples[] = {sampleComponent0.data(), sampleComponent1.data(),
+ sampleComponent2.data(), sampleComponent3.data()};
+ errorRaw = mDispatch.getDisplayedContentSample(mDevice, display, maxFrames, timestamp,
+ &frameCount, size, samples);
+ return static_cast<Error>(errorRaw);
+ }
+
+ Error getDisplayCapabilities(
+ Display display,
+ std::vector<IComposerClient::DisplayCapability>* outCapabilities) override {
+ uint32_t count = 0;
+ int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ outCapabilities->resize(count);
+ error = mDispatch.getDisplayCapabilities(
+ mDevice, display, &count,
+ reinterpret_cast<std::underlying_type<IComposerClient::DisplayCapability>::type*>(
+ outCapabilities->data()));
+ if (error != HWC2_ERROR_NONE) {
+ *outCapabilities = std::vector<IComposerClient::DisplayCapability>();
+ return static_cast<Error>(error);
+ }
+ return Error::NONE;
+ }
+
+ Error setLayerPerFrameMetadataBlobs(
+ Display display, Layer layer,
+ std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override {
+ if (!mDispatch.setLayerPerFrameMetadataBlobs) {
+ return Error::UNSUPPORTED;
+ }
+
+ std::vector<IComposerClient::PerFrameMetadataKey> keys;
+ std::vector<uint32_t> sizes;
+ std::vector<uint8_t> blobs;
+
+ for (auto metadataBlob : metadata) {
+ keys.push_back(metadataBlob.key);
+ sizes.push_back(metadataBlob.blob.size());
+
+ int writeIndex = blobs.size();
+ blobs.resize(blobs.size() + metadataBlob.blob.size());
+ memcpy(blobs.data() + writeIndex, metadataBlob.blob.data(), metadataBlob.blob.size());
+ }
+
+ int32_t err = mDispatch.setLayerPerFrameMetadataBlobs(
+ mDevice, display, layer, static_cast<uint32_t>(metadata.size()),
+ reinterpret_cast<int32_t*>(keys.data()), reinterpret_cast<uint32_t*>(sizes.data()),
+ blobs.data());
+ return static_cast<Error>(err);
+ }
+
+ Error getDisplayBrightnessSupport(Display display, bool* outSupport) {
+ if (!mDispatch.getDisplayBrightnessSupport) {
+ // Preemptively set to false.
+ *outSupport = false;
+ // Try to query from getDisplayCapabilities.
+ std::vector<IComposerClient::DisplayCapability> capabilities;
+ Error error = getDisplayCapabilities(display, &capabilities);
+ if (error != Error::NONE) {
+ // This function is not registered, always return UNSUPPORTED.
+ return Error::UNSUPPORTED;
+ }
+ *outSupport =
+ std::find(capabilities.begin(), capabilities.end(),
+ IComposerClient::DisplayCapability::BRIGHTNESS) != capabilities.end();
+ // This function is not registered, always return UNSUPPORTED.
+ return Error::UNSUPPORTED;
+ }
+ bool support = false;
+ int32_t error = mDispatch.getDisplayBrightnessSupport(mDevice, display, &support);
+ *outSupport = support;
+ return static_cast<Error>(error);
+ }
+
+ Error setDisplayBrightness(Display display, float brightness) {
+ if (std::isnan(brightness) || brightness > 1.0f ||
+ (brightness < 0.0f && brightness != -1.0f)) {
+ return Error::BAD_PARAMETER;
+ }
+ if (!mDispatch.setDisplayBrightness) {
+ return Error::UNSUPPORTED;
+ }
+ int32_t error = mDispatch.setDisplayBrightness(mDevice, display, brightness);
+ return static_cast<Error>(error);
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_2::initDispatch()) {
+ return false;
+ }
+
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
+ &mDispatch.getDisplayIdentificationData);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
+ &mDispatch.setLayerColorTransform);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
+ &mDispatch.getDisplayedContentSamplingAttributes);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED,
+ &mDispatch.setDisplayedContentSamplingEnabled);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE,
+ &mDispatch.getDisplayedContentSample);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES,
+ &mDispatch.getDisplayCapabilities);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS,
+ &mDispatch.setLayerPerFrameMetadataBlobs);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT,
+ &mDispatch.getDisplayBrightnessSupport);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
+ &mDispatch.setDisplayBrightness);
+ return true;
+ }
+
+ int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) override {
+ if (outChangedLayers == nullptr && outCompositionTypes == nullptr) {
+ uint32_t typesCount = 0;
+ int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount,
+ nullptr, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return error;
+ }
+ mChangedLayersCache[display].resize(typesCount);
+ mCompositionTypesCache[display].resize(typesCount);
+ error = BaseType2_1::getChangedCompositionTypesInternal(
+ display, &typesCount, mChangedLayersCache[display].data(),
+ mCompositionTypesCache[display].data());
+ if (error != HWC2_ERROR_NONE) {
+ return error;
+ }
+ for (Layer layer : mClientCompositionLayers[display]) {
+ bool exist = false;
+ for (uint32_t i = 0; i < typesCount; ++i) {
+ if (mChangedLayersCache[display][i] == layer) {
+ exist = true;
+ break;
+ }
+ }
+ if (!exist) {
+ mChangedLayersCache[display].push_back(layer);
+ mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT);
+ }
+ }
+ *outTypesCount = mChangedLayersCache[display].size();
+ return error;
+ }
+ for (uint32_t i = 0; i < *outTypesCount; ++i) {
+ if (outChangedLayers != nullptr) {
+ outChangedLayers[i] = mChangedLayersCache[display][i];
+ }
+ if (outCompositionTypes != nullptr) {
+ outCompositionTypes[i] = mCompositionTypesCache[display][i];
+ }
+ }
+ return HWC2_ERROR_NONE;
+ }
+
+ void onLayerDestroyed(Display display, Layer layer) override {
+ if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+ return;
+ }
+ mClientCompositionLayers[display].erase(layer);
+ }
+
+ void onBeforeValidateDisplay(Display display) override {
+ if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+ return;
+ }
+
+ // clear the cache proactively so that we don't hold too much memory over time.
+ mChangedLayersCache[display].clear();
+ mCompositionTypesCache[display].clear();
+
+ // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to
+ // follow the spec to make sure those layers marked as client composition before validate
+ // the display.
+ if (!mDispatch.setLayerColorTransform) {
+ for (Layer layer : mClientCompositionLayers[display]) {
+ BaseType2_1::setLayerCompositionType(
+ display, layer, static_cast<int32_t>(IComposerClient::Composition::CLIENT));
+ }
+ }
+ }
+
+ private:
+ struct {
+ HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
+ HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
+ HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES getDisplayedContentSamplingAttributes;
+ HWC2_PFN_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED setDisplayedContentSamplingEnabled;
+ HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE getDisplayedContentSample;
+ HWC2_PFN_GET_DISPLAY_CAPABILITIES getDisplayCapabilities;
+ HWC2_PFN_SET_LAYER_PER_FRAME_METADATA_BLOBS setLayerPerFrameMetadataBlobs;
+ HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT getDisplayBrightnessSupport;
+ HWC2_PFN_SET_DISPLAY_BRIGHTNESS setDisplayBrightness;
+ } mDispatch = {};
+
+ using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::getHdrCapabilities;
+ using BaseType2_1::mDevice;
+ using BaseType2_2::getClientTargetSupport_2_2;
+ using BaseType2_2::getColorModes_2_2;
+ using BaseType2_2::getPerFrameMetadataKeys;
+ using BaseType2_2::getReadbackBufferAttributes;
+ using BaseType2_2::getRenderIntents;
+ using BaseType2_2::setColorMode_2_2;
+ using BaseType2_2::setLayerPerFrameMetadata;
+ std::map<Display, std::set<Layer>> mClientCompositionLayers;
+ std::map<Display, std::vector<Layer>> mChangedLayersCache;
+ std::map<Display, std::vector<IComposerClient::Composition>> mCompositionTypesCache;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
new file mode 100644
index 0000000..afef475
--- a/dev/null
+++ b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * 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 "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.3/Composer.h>
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <composer-passthrough/2.3/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+class HwcLoader : public V2_2::passthrough::HwcLoader {
+ public:
+ static IComposer* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+
+ auto hal = createHalWithAdapter(module);
+ if (!hal) {
+ return nullptr;
+ }
+
+ return createComposer(std::move(hal)).release();
+ }
+
+ // create a ComposerHal instance
+ static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+
+ // create a ComposerHal instance, insert an adapter if necessary
+ static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+ bool adapted;
+ hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+ if (!device) {
+ return nullptr;
+ }
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+ }
+
+ // create an IComposer instance
+ static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+ return hal::Composer::create(std::move(hal));
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android