graphics: add composer 2.2 default impl
This adds
android.hardware.graphics.composer@2.2-hal
android.hardware.graphics.composer@2.2-passthrough
android.hardware.graphics.composer@2.2-service
The -hal module makes it easier to write composer 2.2 HAL and is
reusable by vendors. The -passthrough module provides a HwcHal
class that implements ComposerHal 2.2 on top of hwcomposer2, and is
also resuable by vendors. Finally, the -service module provides a
(stub) default implementation.
Test: boots and VTS
Change-Id: I4f940a9dea656abc7d9d485bf48d852c13d2ed56
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..906479e
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,31 @@
+cc_binary {
+ name: "android.hardware.graphics.composer@2.2-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.mapper@2.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"ComposerHal\""
+ ],
+}
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS
new file mode 100644
index 0000000..4714be2
--- /dev/null
+++ b/graphics/composer/2.2/default/OWNERS
@@ -0,0 +1,5 @@
+# Graphics team
+courtneygo@google.com
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
new file mode 100644
index 0000000..a41d902
--- /dev/null
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/graphics/composer/2.2/default/service.cpp b/graphics/composer/2.2/default/service.cpp
new file mode 100644
index 0000000..8c5ef18
--- /dev/null
+++ b/graphics/composer/2.2/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.2/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_2::IComposer;
+using android::hardware::graphics::composer::V2_2::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, ¶m) != 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/graphics/composer/2.2/utils/hal/Android.bp b/graphics/composer/2.2/utils/hal/Android.bp
new file mode 100644
index 0000000..10dcae4
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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.2-hal",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.2",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.2",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ "android.hardware.graphics.composer@2.1-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
new file mode 100644
index 0000000..58bbaa5
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h
@@ -0,0 +1,74 @@
+/*
+ * 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 "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <composer-hal/2.1/Composer.h>
+#include <composer-hal/2.2/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_1::hal::detail::ComposerImpl<Interface, Hal> {
+ 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) : BaseType2_1(std::move(hal)) {}
+
+ protected:
+ V2_1::IComposerClient* createClient() override {
+ auto client = ComposerClient::create(mHal.get());
+ if (!client) {
+ return nullptr;
+ }
+
+ auto clientDestroyed = [this]() { onClientDestroyed(); };
+ client->setOnClientDestroyed(clientDestroyed);
+
+ return client.release();
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+ using BaseType2_1::mHal;
+ using BaseType2_1::onClientDestroyed;
+};
+
+} // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
new file mode 100644
index 0000000..d550f83
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h
@@ -0,0 +1,162 @@
+/*
+ * 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 <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerClient.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl<Interface, Hal> {
+ 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) : BaseType2_1(hal) {}
+
+ // IComposerClient 2.2 interface
+
+ Return<void> getPerFrameMetadataKeys(
+ Display display, IComposerClient::getPerFrameMetadataKeys_cb hidl_cb) override {
+ std::vector<IComposerClient::PerFrameMetadataKey> keys;
+ Error error = mHal->getPerFrameMetadataKeys(display, &keys);
+ hidl_cb(error, keys);
+ return Void();
+ }
+
+ Return<void> getReadbackBufferAttributes(
+ Display display, IComposerClient::getReadbackBufferAttributes_cb hidl_cb) override {
+ PixelFormat format = static_cast<PixelFormat>(0);
+ Dataspace dataspace = Dataspace::UNKNOWN;
+ Error error = mHal->getReadbackBufferAttributes(display, &format, &dataspace);
+ hidl_cb(error, format, dataspace);
+ return Void();
+ }
+
+ Return<void> getReadbackBufferFence(
+ Display display, IComposerClient::getReadbackBufferFence_cb hidl_cb) override {
+ base::unique_fd fenceFd;
+ Error error = mHal->getReadbackBufferFence(display, &fenceFd);
+ if (error != Error::NONE) {
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+ return Void();
+ }
+
+ Return<Error> setReadbackBuffer(Display display, const hidl_handle& buffer,
+ const hidl_handle& releaseFence) override {
+ base::unique_fd fenceFd;
+ Error error = getFenceFd(releaseFence, &fenceFd);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ auto resources = static_cast<ComposerResources*>(mResources.get());
+ const native_handle_t* readbackBuffer;
+ ComposerResources::ReplacedBufferHandle replacedReadbackBuffer;
+ error = resources->getDisplayReadbackBuffer(display, buffer.getNativeHandle(),
+ &readbackBuffer, &replacedReadbackBuffer);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd));
+ }
+
+ Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override {
+ return mHal->setPowerMode_2_2(display, mode);
+ }
+
+ protected:
+ std::unique_ptr<V2_1::hal::ComposerResources> createResources() override {
+ return ComposerResources::create();
+ }
+
+ std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override {
+ return std::make_unique<ComposerCommandEngine>(
+ mHal, static_cast<ComposerResources*>(mResources.get()));
+ }
+
+ // convert fenceFd to or from hidl_handle
+ static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+ auto handle = fenceHandle.getNativeHandle();
+ if (handle && handle->numFds > 1) {
+ ALOGE("invalid fence handle with %d fds", handle->numFds);
+ return Error::BAD_PARAMETER;
+ }
+
+ int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ outFenceFd->reset(fenceFd);
+
+ return Error::NONE;
+ }
+
+ static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+ native_handle_t* handle = nullptr;
+ if (fenceFd >= 0) {
+ handle = native_handle_init(handleStorage, 1, 0);
+ handle->data[0] = fenceFd;
+ }
+
+ return hidl_handle(handle);
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+ using BaseType2_1::mHal;
+ using BaseType2_1::mResources;
+};
+
+} // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
new file mode 100644
index 0000000..adcac46
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h
@@ -0,0 +1,103 @@
+/*
+ * 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 <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerHal.h>
+#include <composer-hal/2.2/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine {
+ public:
+ ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+ : BaseType2_1(hal, resources), mHal(hal) {}
+
+ protected:
+ bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+ switch (static_cast<IComposerClient::Command>(command)) {
+ case IComposerClient::Command::SET_PER_FRAME_METADATA:
+ return executeSetPerFrameMetadata(length);
+ case IComposerClient::Command::SET_LAYER_FLOAT_COLOR:
+ return executeSetLayerFloatColor(length);
+ default:
+ return BaseType2_1::executeCommand(command, length);
+ }
+ }
+
+ bool executeSetPerFrameMetadata(uint16_t length) {
+ // (key, value) pairs
+ if (length % 2 != 0) {
+ return false;
+ }
+
+ std::vector<IComposerClient::PerFrameMetadata> metadata;
+ metadata.reserve(length / 2);
+ while (length > 0) {
+ metadata.emplace_back(IComposerClient::PerFrameMetadata{
+ static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()), readFloat()});
+ length -= 2;
+ }
+
+ auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerFloatColor(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerFloatColorLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerFloatColor(mCurrentDisplay, mCurrentLayer, readFloatColor());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ IComposerClient::FloatColor readFloatColor() {
+ return IComposerClient::FloatColor{readFloat(), readFloat(), readFloat(), readFloat()};
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+ using BaseType2_1::mWriter;
+
+ ComposerHal* mHal;
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
new file mode 100644
index 0000000..30b3643
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h
@@ -0,0 +1,66 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-hal/2.1/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using common::V1_0::Dataspace;
+using common::V1_0::PixelFormat;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+
+class ComposerHal : public V2_1::hal::ComposerHal {
+ public:
+ // superceded by setPowerMode_2_2
+ Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override {
+ return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode));
+ }
+
+ virtual Error getPerFrameMetadataKeys(
+ Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0;
+ virtual Error setPerFrameMetadata(
+ Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0;
+
+ virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat,
+ Dataspace* outDataspace) = 0;
+ virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle,
+ base::unique_fd fenceFd) = 0;
+ virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0;
+
+ virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0;
+
+ virtual Error setLayerFloatColor(Display display, Layer layer,
+ IComposerClient::FloatColor color) = 0;
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
new file mode 100644
index 0000000..85b6651
--- /dev/null
+++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h
@@ -0,0 +1,105 @@
+/*
+ * 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 <composer-hal/2.1/ComposerResources.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using V2_1::hal::ComposerHandleCache;
+using V2_1::hal::ComposerHandleImporter;
+
+class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource {
+ public:
+ ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize),
+ mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {}
+
+ Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ const uint32_t slot = 0;
+ const bool fromCache = false;
+ return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
+ outReplacedHandle);
+ }
+
+ protected:
+ ComposerHandleCache mReadbackBufferCache;
+};
+
+class ComposerResources : public V2_1::hal::ComposerResources {
+ public:
+ static std::unique_ptr<ComposerResources> create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+ }
+
+ Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+ const native_handle_t** outHandle,
+ ReplacedBufferHandle* outReplacedHandle) {
+ // import buffer
+ const native_handle_t* importedHandle;
+ Error error = mImporter.importBuffer(rawHandle, &importedHandle);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+
+ auto iter = mDisplayResources.find(display);
+ if (iter == mDisplayResources.end()) {
+ mImporter.freeBuffer(importedHandle);
+ return Error::BAD_DISPLAY;
+ }
+ ComposerDisplayResource& displayResource =
+ *static_cast<ComposerDisplayResource*>(iter->second.get());
+
+ // update cache
+ const native_handle_t* replacedHandle;
+ error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle);
+ if (error != Error::NONE) {
+ mImporter.freeBuffer(importedHandle);
+ return error;
+ }
+
+ outReplacedHandle->reset(&mImporter, replacedHandle);
+ return Error::NONE;
+ }
+
+ protected:
+ std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override {
+ return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+ }
+};
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/utils/passthrough/Android.bp b/graphics/composer/2.2/utils/passthrough/Android.bp
new file mode 100644
index 0000000..318ce91
--- /dev/null
+++ b/graphics/composer/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/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
new file mode 100644
index 0000000..b251351
--- /dev/null
+++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h
@@ -0,0 +1,208 @@
+/*
+ * 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_0::Dataspace;
+using common::V1_0::PixelFormat;
+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 setPerFrameMetadata(
+ Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override {
+ if (!mDispatch.setPerFrameMetadata) {
+ 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.setPerFrameMetadata(mDevice, display, 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 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);
+ }
+
+ 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_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata);
+ 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);
+
+ return true;
+ }
+
+ struct {
+ HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor;
+ HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata;
+ 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;
+ } mDispatch = {};
+
+ private:
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::mDevice;
+ 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/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h
new file mode 100644
index 0000000..cb4a238
--- /dev/null
+++ b/graphics/composer/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