summaryrefslogtreecommitdiff
authorbaocheng sun <baocheng.sun@amlogic.com>2020-05-26 11:48:44 (GMT)
committer baocheng sun <baocheng.sun@amlogic.com>2020-05-28 02:15:01 (GMT)
commitf34c749ec03c46df0271a0b30278e27906a13ef6 (patch)
treea368ad94990dbc1573010c2dcdc8ee7579cbc4b4
parentadc88c28ecfdcd18df302ff9dc260d04965bd792 (diff)
downloadhwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.zip
hwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.tar.gz
hwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.tar.bz2
hwc: add vendor composer service [1/1]
PD#SWPL-26849 Problem: enable vendor composer service for R Solution: add vendor composer service Verify: newton Change-Id: I83cdbb61da0af5d4ae49fba63af9d308f941d452 Signed-off-by: baocheng sun <baocheng.sun@amlogic.com>
Diffstat
-rwxr-xr-x[-rw-r--r--]service/2.1/utils/hal/Android.bp6
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/Composer.h11
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h2
-rw-r--r--service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h141
-rwxr-xr-xservice/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h717
-rw-r--r--service/2.1/utils/resources/Android.bp53
-rw-r--r--service/2.1/utils/resources/ComposerResources.cpp607
-rw-r--r--service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h288
-rw-r--r--service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h12
-rw-r--r--service/2.2/utils/resources/Android.bp29
-rw-r--r--service/2.2/utils/resources/ComposerResources.cpp84
-rw-r--r--service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h105
-rw-r--r--service/2.3/default/Android.bp5
-rw-r--r--service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h14
-rw-r--r--service/2.4/default/Android.bp48
-rw-r--r--service/2.4/default/OWNERS4
-rw-r--r--service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc7
-rw-r--r--service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml11
-rw-r--r--service/2.4/default/service.cpp55
-rw-r--r--service/2.4/utils/passthrough/Android.bp30
-rw-r--r--service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h402
-rw-r--r--service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h79
22 files changed, 1905 insertions, 805 deletions
diff --git a/service/2.1/utils/hal/Android.bp b/service/2.1/utils/hal/Android.bp
index 45831a1..40f3dd0 100644..100755
--- a/service/2.1/utils/hal/Android.bp
+++ b/service/2.1/utils/hal/Android.bp
@@ -19,15 +19,13 @@ cc_library_headers {
vendor: true,
shared_libs: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.composer@2.1-resources-vendor",
"libhardware", // TODO remove hwcomposer2.h dependency
"libamgralloc_ext_vendor@2",
],
export_shared_lib_headers: [
"android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.composer@2.1-resources-vendor",
"libhardware",
"libamgralloc_ext_vendor@2",
],
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
index 90d9b98..4b8c6bb 100644
--- 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
@@ -67,6 +67,14 @@ class ComposerImpl : public Interface {
}
}
+ // we do not have HWC2_CAPABILITY_SKIP_VALIDATE defined in
+ // IComposer::Capability. However, this is defined in hwcomposer2.h,
+ // so if the device returns it, add it manually to be returned to the
+ // client
+ if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+ caps.push_back(static_cast<IComposer::Capability>(HWC2_CAPABILITY_SKIP_VALIDATE));
+ }
+
hidl_vec<IComposer::Capability> caps_reply;
caps_reply.setToExternal(caps.data(), caps.size());
hidl_cb(caps_reply);
@@ -80,8 +88,7 @@ class ComposerImpl : public Interface {
Return<void> createClient(IComposer::createClient_cb hidl_cb) override {
std::unique_lock<std::mutex> lock(mClientMutex);
- bool destroyed = waitForClientDestroyedLocked(lock);
- if (!destroyed) {
+ if (!waitForClientDestroyedLocked(lock)) {
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
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
index 095189f..47ead41 100644
--- 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
@@ -27,7 +27,7 @@
#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 <composer-resources/2.1/ComposerResources.h>
#include <log/log.h>
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
index d87110a..ab67eb1 100644
--- 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
@@ -24,7 +24,7 @@
#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
#include <composer-hal/2.1/ComposerHal.h>
-#include <composer-hal/2.1/ComposerResources.h>
+#include <composer-resources/2.1/ComposerResources.h>
// TODO remove hwcomposer_defs.h dependency
#include <hardware/hwcomposer_defs.h>
#include <log/log.h>
@@ -39,8 +39,10 @@ namespace hal {
// TODO own a CommandReaderBase rather than subclassing
class ComposerCommandEngine : protected CommandReaderBase {
public:
- ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
- : mHal(hal), mResources(resources) {}
+ ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+ : mHal(hal), mResources(resources) {
+ mWriter = createCommandWriter(kWriterInitialSize);
+ }
virtual ~ComposerCommandEngine() = default;
@@ -74,16 +76,16 @@ class ComposerCommandEngine : protected CommandReaderBase {
return Error::BAD_PARAMETER;
}
- return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
- ? Error::NONE
- : Error::NO_RESOURCES;
+ return mWriter->writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+ ? Error::NONE
+ : Error::NO_RESOURCES;
}
- const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+ const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter->getMQDescriptor(); }
void reset() {
CommandReaderBase::reset();
- mWriter.reset();
+ mWriter->reset();
}
protected:
@@ -140,13 +142,36 @@ class ComposerCommandEngine : protected CommandReaderBase {
}
}
+ virtual std::unique_ptr<CommandWriterBase> createCommandWriter(size_t writerInitialSize) {
+ return std::make_unique<CommandWriterBase>(writerInitialSize);
+ }
+
+ virtual Error executeValidateDisplayInternal() {
+ 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 err;
+ }
+
bool executeSelectDisplay(uint16_t length) {
if (length != CommandWriterBase::kSelectDisplayLength) {
return false;
}
mCurrentDisplay = read64();
- mWriter.selectDisplay(mCurrentDisplay);
+ mWriter->selectDisplay(mCurrentDisplay);
return true;
}
@@ -174,7 +199,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -195,7 +220,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
bool closeFence = true;
const native_handle_t* clientTarget;
- ComposerResources::ReplacedBufferHandle replacedClientTarget;
+ ComposerResources::ReplacedHandle replacedClientTarget(true);
auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
&clientTarget, &replacedClientTarget);
if (err == Error::NONE) {
@@ -208,7 +233,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
close(fence);
}
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -226,7 +251,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
bool closeFence = true;
const native_handle_t* outputBuffer;
- ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+ ComposerResources::ReplacedHandle replacedOutputBuffer(true);
auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
&outputBuffer, &replacedOutputBuffer);
if (err == Error::NONE) {
@@ -239,7 +264,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
close(fence);
}
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -249,23 +274,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
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);
- }
-
+ executeValidateDisplayInternal();
return true;
}
@@ -283,29 +292,17 @@ class ComposerCommandEngine : protected CommandReaderBase {
? Error::NOT_VALIDATED
: mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
if (err == Error::NONE) {
- mWriter.setPresentOrValidateResult(1);
- mWriter.setPresentFence(presentFence);
- mWriter.setReleaseFences(layers, fences);
+ 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);
+ auto err = executeValidateDisplayInternal();
if (err == Error::NONE) {
- mWriter.setPresentOrValidateResult(0);
- mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
- mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
- } else {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setPresentOrValidateResult(0);
}
return true;
@@ -318,7 +315,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -334,10 +331,10 @@ class ComposerCommandEngine : protected CommandReaderBase {
std::vector<int> fences;
auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
if (err == Error::NONE) {
- mWriter.setPresentFence(presentFence);
- mWriter.setReleaseFences(layers, fences);
+ mWriter->setPresentFence(presentFence);
+ mWriter->setReleaseFences(layers, fences);
} else {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -351,7 +348,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
readSigned());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -369,7 +366,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
bool closeFence = true;
const native_handle_t* buffer;
- ComposerResources::ReplacedBufferHandle replacedBuffer;
+ ComposerResources::ReplacedHandle replacedBuffer(true);
auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
rawHandle, &buffer, &replacedBuffer);
if (err == Error::NONE) {
@@ -382,7 +379,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
close(fence);
}
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -397,7 +394,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto damage = readRegion(length / 4);
auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -410,7 +407,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -423,7 +420,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -436,7 +433,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -449,7 +446,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -462,7 +459,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -475,7 +472,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -489,14 +486,14 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto rawHandle = readHandle();
const native_handle_t* stream;
- ComposerResources::ReplacedStreamHandle replacedStream;
+ ComposerResources::ReplacedHandle replacedStream(false);
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);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -509,7 +506,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -522,7 +519,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -537,7 +534,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto region = readRegion(length / 4);
auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -550,7 +547,7 @@ class ComposerCommandEngine : protected CommandReaderBase {
auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
if (err != Error::NONE) {
- mWriter.setError(getCommandLoc(), err);
+ mWriter->setError(getCommandLoc(), err);
}
return true;
@@ -579,12 +576,12 @@ class ComposerCommandEngine : protected CommandReaderBase {
};
}
- 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};
+
+ ComposerHal* mHal;
+ ComposerResources* mResources;
+ std::unique_ptr<CommandWriterBase> mWriter;
Display mCurrentDisplay = 0;
Layer mCurrentLayer = 0;
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
deleted file mode 100755
index 8c22ebc..0000000
--- a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
+++ b/dev/null
@@ -1,717 +0,0 @@
-/*
- * 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>
-
-#include <hwbinder/IPCThreadState.h>
-#include "am_gralloc_ext.h"
-
-#define UVM_DEV_PATH "/dev/uvm"
-#define UVM_IOC_MAGIC 'U'
-#define UVM_IOC_SET_PID _IOWR(UVM_IOC_MAGIC, 2, struct uvm_pid_data)
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace composer {
-namespace V2_1 {
-namespace hal {
-
-class ComposerUVMHandle {
-public:
- ComposerUVMHandle() : mFd(-1) {}
-
- ~ComposerUVMHandle() {
- if (mFd >=0)
- close(mFd);
- }
-
- int setUVM() {
- ::android::hardware::IPCThreadState *ipc = ::android::hardware::IPCThreadState::self();
- const pid_t pid = ipc->getCallingPid();
-
- struct uvm_pid_data {
- int pid;
- } pid_data;
-
- pid_data.pid = pid;
-
- ALOGD("setUVM with pid %d", pid);
- if (ioctl(mFd, UVM_IOC_SET_PID, &pid_data) != 0) {
- ALOGE("setUVM pid %d ioctl error %s", pid, strerror(errno));
- return -1;
- }
- return 0;
- }
-
- bool init() {
- mFd = open(UVM_DEV_PATH, O_RDWR);
- if (mFd <= 0) {
- ALOGE("open uvm device error");
- return false;
- }
- setUVM();
- return true;
- }
-
-private:
- int mFd;
-};
-
-// 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,
- };
-
- enum class DrmFbType {
- DRM_FB_UNDEFINED = 0,
- // scattered buffer, can be used for rendering.
- DRM_FB_RENDER = 1,
- // contiguous buffer, can be used for scanout.
- DRM_FB_SCANOUT,
- // video type, used for video.
- DRM_FB_VIDEO,
- DRM_FB_VIDEO_OVERLAY,
- };
-
- 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;
- }
- }
-
- // release cache
- Error releaseCache(uint32_t slot) {
- if (slot >= 0 && slot < mHandles.size()) {
- switch (mHandleType) {
- case HandleType::BUFFER:
- for (; slot < mHandles.size(); slot++) {
- if (mHandles[slot])
- mImporter.freeBuffer(mHandles[slot]);
- mHandles[slot] = nullptr;
- }
- break;
- case HandleType::STREAM:
- for (; slot < mHandles.size(); slot++) {
- if (mHandles[slot])
- mImporter.freeStream(mHandles[slot]);
- mHandles[slot] = nullptr;
- }
- break;
- default:
- break;
- }
- return Error::NONE;
- } else {
- return Error::BAD_PARAMETER;
- }
- }
-
- bool isChangedFromeVideoToUi(const native_handle_t* handle) {
- bool changed = false;
- if (am_gralloc_is_omx_v4l_buffer(handle) || am_gralloc_is_omx2_v4l2_buffer(handle) ||
- am_gralloc_is_omx_metadata_buffer(handle)) {
- mFbType = DrmFbType::DRM_FB_VIDEO;
- } else if (am_gralloc_is_overlay_buffer(handle)) {
- mFbType = DrmFbType::DRM_FB_VIDEO_OVERLAY;
- } else if (am_gralloc_is_coherent_buffer(handle)) {
- if (mFbType == DrmFbType::DRM_FB_VIDEO ||
- mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) {
- changed = true;
- }
- mFbType = DrmFbType::DRM_FB_SCANOUT;
- } else {
- if (mFbType == DrmFbType::DRM_FB_VIDEO ||
- mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) {
- changed = true;
- }
- mFbType = DrmFbType::DRM_FB_RENDER;
- }
- return changed;
- }
-
- // 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) {
- Error error = Error::NONE;
-
- if (fromCache) {
- *outReplacedHandle = nullptr;
- error = lookupCache(slot, outHandle);
- } else {
- if (mHandleType == HandleType::BUFFER && isChangedFromeVideoToUi(inHandle)) {
- ALOGD("FB type changed from video to UI, fromcache(%d):slot(%d)", fromCache, slot);
- releaseCache(0);
- }
-
- *outHandle = inHandle;
- error = updateCache(slot, inHandle, outReplacedHandle);
- }
-
- return error;
- }
-
- private:
- ComposerHandleImporter& mImporter;
- HandleType mHandleType = HandleType::INVALID;
- DrmFbType mFbType = DrmFbType::DRM_FB_UNDEFINED;
- 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() {
- bool result = mImporter.init();
- mUVMHandle.init();
-
- return result;
- }
-
- 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;
- ComposerUVMHandle mUVMHandle;
-
- 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/resources/Android.bp b/service/2.1/utils/resources/Android.bp
new file mode 100644
index 0000000..9098603
--- a/dev/null
+++ b/service/2.1/utils/resources/Android.bp
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2019 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_shared {
+ name: "android.hardware.graphics.composer@2.1-resources-vendor",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ "libcutils",
+ "libhardware", // TODO remove hwcomposer2.h dependency
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ "libamgralloc_ext_vendor@2",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ "libhardware",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ "libamgralloc_ext_vendor@2",
+ ],
+ 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"],
+ srcs: [
+ "ComposerResources.cpp",
+ ],
+}
diff --git a/service/2.1/utils/resources/ComposerResources.cpp b/service/2.1/utils/resources/ComposerResources.cpp
new file mode 100644
index 0000000..46d552d
--- a/dev/null
+++ b/service/2.1/utils/resources/ComposerResources.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ComposerResources"
+
+#include <hwbinder/IPCThreadState.h>
+#include "composer-resources/2.1/ComposerResources.h"
+#include "am_gralloc_ext.h"
+#include <sys/ioctl.h>
+
+#define UVM_DEV_PATH "/dev/uvm"
+#define UVM_IOC_MAGIC 'U'
+#define UVM_IOC_SET_PID _IOWR(UVM_IOC_MAGIC, 2, struct uvm_pid_data)
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+ComposerUVMHandle::ComposerUVMHandle() : mFd(-1) {
+}
+
+ComposerUVMHandle::~ComposerUVMHandle() {
+ if (mFd >=0)
+ close(mFd);
+}
+
+bool ComposerUVMHandle::init() {
+ mFd = open(UVM_DEV_PATH, O_RDWR);
+ if (mFd <= 0) {
+ ALOGE("open uvm device error");
+ return false;
+ }
+ setUVM();
+ return true;
+}
+
+int ComposerUVMHandle::setUVM() {
+ ::android::hardware::IPCThreadState *ipc = ::android::hardware::IPCThreadState::self();
+ const pid_t pid = ipc->getCallingPid();
+
+ struct uvm_pid_data {
+ int pid;
+ } pid_data;
+
+ pid_data.pid = pid;
+
+ ALOGD("setUVM with pid %d", pid);
+ if (ioctl(mFd, UVM_IOC_SET_PID, &pid_data) != 0) {
+ ALOGE("setUVM pid %d ioctl error %s", pid, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+bool ComposerHandleImporter::init() {
+ mMapper4 = mapper::V4_0::IMapper::getService();
+ if (mMapper4) {
+ return true;
+ }
+ ALOGI_IF(!mMapper4, "failed to get mapper 4.0 service, falling back to mapper 3.0");
+
+ mMapper3 = mapper::V3_0::IMapper::getService();
+ if (mMapper3) {
+ return true;
+ }
+ ALOGI_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 ComposerHandleImporter::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;
+ }
+ }
+ if (mMapper4) {
+ mapper::V4_0::Error error;
+ mMapper4->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
+ error = tmpError;
+ bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
+ });
+ if (error != mapper::V4_0::Error::NONE) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outBufferHandle = bufferHandle;
+ return Error::NONE;
+}
+
+void ComposerHandleImporter::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)));
+ } else if (mMapper4) {
+ mMapper4->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
+ }
+ }
+}
+
+Error ComposerHandleImporter::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 ComposerHandleImporter::freeStream(const native_handle_t* streamHandle) {
+ if (streamHandle) {
+ native_handle_close(streamHandle);
+ native_handle_delete(const_cast<native_handle_t*>(streamHandle));
+ }
+}
+
+ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer, HandleType type,
+ uint32_t cacheSize)
+ : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
+
+// must be initialized later with initCache
+ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
+
+ComposerHandleCache::~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;
+ }
+}
+
+bool ComposerHandleCache::initCache(HandleType type, uint32_t cacheSize) {
+ // already initialized
+ if (mHandleType != HandleType::INVALID) {
+ return false;
+ }
+
+ mHandleType = type;
+ mHandles.resize(cacheSize, nullptr);
+
+ return true;
+}
+
+Error ComposerHandleCache::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 ComposerHandleCache::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;
+ }
+}
+
+// release cache
+Error ComposerHandleCache::releaseCache(uint32_t slot) {
+ if (slot >= 0 && slot < mHandles.size()) {
+ switch (mHandleType) {
+ case HandleType::BUFFER:
+ for (; slot < mHandles.size(); slot++) {
+ if (mHandles[slot])
+ mImporter.freeBuffer(mHandles[slot]);
+ mHandles[slot] = nullptr;
+ }
+ break;
+ case HandleType::STREAM:
+ for (; slot < mHandles.size(); slot++) {
+ if (mHandles[slot])
+ mImporter.freeStream(mHandles[slot]);
+ mHandles[slot] = nullptr;
+ }
+ break;
+ default:
+ break;
+ }
+ return Error::NONE;
+ } else {
+ return Error::BAD_PARAMETER;
+ }
+}
+
+bool ComposerHandleCache::isChangedFromeVideoToUi(const native_handle_t* handle) {
+ bool changed = false;
+ if (am_gralloc_is_omx_v4l_buffer(handle) || am_gralloc_is_omx2_v4l2_buffer(handle) ||
+ am_gralloc_is_omx_metadata_buffer(handle)) {
+ mFbType = DrmFbType::DRM_FB_VIDEO;
+ } else if (am_gralloc_is_overlay_buffer(handle)) {
+ mFbType = DrmFbType::DRM_FB_VIDEO_OVERLAY;
+ } else if (am_gralloc_is_coherent_buffer(handle)) {
+ if (mFbType == DrmFbType::DRM_FB_VIDEO ||
+ mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) {
+ changed = true;
+ }
+ mFbType = DrmFbType::DRM_FB_SCANOUT;
+ } else {
+ if (mFbType == DrmFbType::DRM_FB_VIDEO ||
+ mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) {
+ changed = true;
+ }
+ mFbType = DrmFbType::DRM_FB_RENDER;
+ }
+ return changed;
+}
+
+// when fromCache is true, look up in the cache; otherwise, update the cache
+Error ComposerHandleCache::getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle) {
+ Error error = Error::NONE;
+
+ if (fromCache) {
+ *outReplacedHandle = nullptr;
+ error = lookupCache(slot, outHandle);
+ } else {
+ if (mHandleType == HandleType::BUFFER && isChangedFromeVideoToUi(inHandle)) {
+ ALOGD("FB type changed from video to UI, fromcache(%d):slot(%d)", fromCache, slot);
+ releaseCache(0);
+ }
+
+ *outHandle = inHandle;
+ error = updateCache(slot, inHandle, outReplacedHandle);
+ }
+
+ return error;
+}
+
+ComposerLayerResource::ComposerLayerResource(ComposerHandleImporter& importer,
+ uint32_t bufferCacheSize)
+ : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
+ mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
+
+Error ComposerLayerResource::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 ComposerLayerResource::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);
+}
+
+ComposerDisplayResource::ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
+ uint32_t outputBufferCacheSize)
+ : mType(type),
+ mClientTargetCache(importer),
+ mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, outputBufferCacheSize),
+ mMustValidate(true) {}
+
+bool ComposerDisplayResource::initClientTargetCache(uint32_t cacheSize) {
+ return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
+}
+
+bool ComposerDisplayResource::isVirtual() const {
+ return mType == DisplayType::VIRTUAL;
+}
+
+Error ComposerDisplayResource::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 ComposerDisplayResource::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 ComposerDisplayResource::addLayer(Layer layer,
+ std::unique_ptr<ComposerLayerResource> layerResource) {
+ auto result = mLayerResources.emplace(layer, std::move(layerResource));
+ return result.second;
+}
+
+bool ComposerDisplayResource::removeLayer(Layer layer) {
+ return mLayerResources.erase(layer) > 0;
+}
+
+ComposerLayerResource* ComposerDisplayResource::findLayerResource(Layer layer) {
+ auto layerIter = mLayerResources.find(layer);
+ if (layerIter == mLayerResources.end()) {
+ return nullptr;
+ }
+
+ return layerIter->second.get();
+}
+
+std::vector<Layer> ComposerDisplayResource::getLayers() const {
+ std::vector<Layer> layers;
+ layers.reserve(mLayerResources.size());
+ for (const auto& layerKey : mLayerResources) {
+ layers.push_back(layerKey.first);
+ }
+ return layers;
+}
+
+void ComposerDisplayResource::setMustValidateState(bool mustValidate) {
+ mMustValidate = mustValidate;
+}
+
+bool ComposerDisplayResource::mustValidate() const {
+ return mMustValidate;
+}
+
+std::unique_ptr<ComposerResources> ComposerResources::create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+}
+
+bool ComposerResources::init() {
+ bool result = mImporter.init();
+ mUVMHandle.init();
+ return result;
+}
+
+void ComposerResources::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 ComposerResources::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 ComposerResources::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 ComposerResources::removeDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
+}
+
+Error ComposerResources::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 ComposerResources::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 ComposerResources::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;
+}
+
+Error ComposerResources::getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, 0, slot, Cache::CLIENT_TARGET, fromCache, rawHandle, outBufferHandle,
+ outReplacedBuffer);
+}
+
+Error ComposerResources::getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, 0, slot, Cache::OUTPUT_BUFFER, fromCache, rawHandle, outBufferHandle,
+ outReplacedBuffer);
+}
+
+Error ComposerResources::getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer) {
+ return getHandle(display, layer, slot, Cache::LAYER_BUFFER, fromCache, rawHandle,
+ outBufferHandle, outReplacedBuffer);
+}
+
+Error ComposerResources::getLayerSidebandStream(Display display, Layer layer,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle,
+ ReplacedHandle* outReplacedStream) {
+ return getHandle(display, layer, 0, Cache::LAYER_SIDEBAND_STREAM, false, rawHandle,
+ outStreamHandle, outReplacedStream);
+}
+
+void ComposerResources::setDisplayMustValidateState(Display display, bool mustValidate) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ displayResource->setMustValidateState(mustValidate);
+ }
+}
+
+bool ComposerResources::mustValidateDisplay(Display display) {
+ std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+ auto* displayResource = findDisplayResourceLocked(display);
+ if (displayResource) {
+ return displayResource->mustValidate();
+ }
+ return false;
+}
+
+std::unique_ptr<ComposerDisplayResource> ComposerResources::createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
+ return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
+}
+
+std::unique_ptr<ComposerLayerResource> ComposerResources::createLayerResource(
+ uint32_t bufferCacheSize) {
+ return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
+}
+
+ComposerDisplayResource* ComposerResources::findDisplayResourceLocked(Display display) {
+ auto iter = mDisplayResources.find(display);
+ if (iter == mDisplayResources.end()) {
+ return nullptr;
+ }
+ return iter->second.get();
+}
+
+Error ComposerResources::getHandle(Display display, Layer layer, uint32_t slot, Cache cache,
+ bool fromCache, const native_handle_t* rawHandle,
+ const native_handle_t** outHandle,
+ ReplacedHandle* outReplacedHandle) {
+ Error error;
+
+ // import the raw handle (or ignore raw handle when fromCache is true)
+ const native_handle_t* importedHandle = nullptr;
+ if (!fromCache) {
+ error = (outReplacedHandle->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 == ComposerResources::Cache::LAYER_BUFFER ||
+ cache == ComposerResources::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 ComposerResources::Cache::CLIENT_TARGET:
+ error = displayResource->getClientTarget(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::Cache::OUTPUT_BUFFER:
+ error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::Cache::LAYER_BUFFER:
+ error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
+ &replacedHandle);
+ break;
+ case ComposerResources::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 (outReplacedHandle->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/resources/include/composer-resources/2.1/ComposerResources.h b/service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
new file mode 100644
index 0000000..95c2f34
--- a/dev/null
+++ b/service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h
@@ -0,0 +1,288 @@
+/*
+ * 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/composer/2.1/types.h>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+class ComposerUVMHandle {
+public:
+ ComposerUVMHandle();
+ ~ComposerUVMHandle();
+
+ bool init();
+ int setUVM();
+
+private:
+ int mFd;
+};
+
+// wrapper for IMapper to import buffers and sideband streams
+class ComposerHandleImporter {
+ public:
+ bool init();
+
+ Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle);
+ void freeBuffer(const native_handle_t* bufferHandle);
+ Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle);
+ void freeStream(const native_handle_t* streamHandle);
+
+ private:
+ sp<mapper::V2_0::IMapper> mMapper2;
+ sp<mapper::V3_0::IMapper> mMapper3;
+ sp<mapper::V4_0::IMapper> mMapper4;
+};
+
+class ComposerHandleCache {
+ public:
+ enum class HandleType {
+ INVALID,
+ BUFFER,
+ STREAM,
+ };
+
+ enum class DrmFbType {
+ DRM_FB_UNDEFINED = 0,
+ // scattered buffer, can be used for rendering.
+ DRM_FB_RENDER = 1,
+ // contiguous buffer, can be used for scanout.
+ DRM_FB_SCANOUT,
+ // video type, used for video.
+ DRM_FB_VIDEO,
+ DRM_FB_VIDEO_OVERLAY,
+ };
+
+ ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize);
+
+ // must be initialized later with initCache
+ ComposerHandleCache(ComposerHandleImporter& importer);
+
+ ~ComposerHandleCache();
+
+ ComposerHandleCache(const ComposerHandleCache&) = delete;
+ ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
+
+ bool initCache(HandleType type, uint32_t cacheSize);
+ Error lookupCache(uint32_t slot, const native_handle_t** outHandle);
+ Error updateCache(uint32_t slot, const native_handle_t* handle,
+ const native_handle** outReplacedHandle);
+
+ Error releaseCache(uint32_t slot);
+ bool isChangedFromeVideoToUi(const native_handle_t* handle);
+
+ // 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);
+
+ private:
+ ComposerHandleImporter& mImporter;
+ HandleType mHandleType = HandleType::INVALID;
+ DrmFbType mFbType = DrmFbType::DRM_FB_UNDEFINED;
+ std::vector<const native_handle_t*> mHandles;
+};
+
+// layer resource
+class ComposerLayerResource {
+ public:
+ ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize);
+
+ virtual ~ComposerLayerResource() = default;
+
+ Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle, const native_handle** outReplacedHandle);
+ Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** 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);
+
+ bool initClientTargetCache(uint32_t cacheSize);
+
+ bool isVirtual() const;
+
+ Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle);
+
+ Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
+ const native_handle_t** outHandle,
+ const native_handle** outReplacedHandle);
+
+ bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource);
+ bool removeLayer(Layer layer);
+ ComposerLayerResource* findLayerResource(Layer layer);
+ std::vector<Layer> getLayers() const;
+
+ void setMustValidateState(bool mustValidate);
+
+ bool mustValidate() const;
+
+ protected:
+ const DisplayType mType;
+ ComposerHandleCache mClientTargetCache;
+ ComposerHandleCache mOutputBufferCache;
+ bool mMustValidate;
+
+ std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
+};
+
+class ComposerResources {
+ public:
+ static std::unique_ptr<ComposerResources> create();
+
+ ComposerResources() = default;
+ virtual ~ComposerResources() = default;
+
+ bool init();
+
+ using RemoveDisplay =
+ std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
+ void clear(RemoveDisplay removeDisplay);
+
+ Error addPhysicalDisplay(Display display);
+ Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize);
+
+ Error removeDisplay(Display display);
+
+ Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize);
+
+ Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize);
+ Error removeLayer(Display display, Layer layer);
+
+ void setDisplayMustValidateState(Display display, bool mustValidate);
+
+ bool mustValidateDisplay(Display display);
+
+ // When a buffer in the cache is replaced by a new one, we must keep it
+ // alive until it has been replaced in ComposerHal.
+ class ReplacedHandle {
+ public:
+ explicit ReplacedHandle(bool isBuffer) : mIsBuffer(isBuffer) {}
+ ReplacedHandle(const ReplacedHandle&) = delete;
+ ReplacedHandle& operator=(const ReplacedHandle&) = delete;
+
+ ~ReplacedHandle() { reset(); }
+
+ bool isBuffer() { return mIsBuffer; }
+
+ void reset(ComposerHandleImporter* importer = nullptr,
+ const native_handle_t* handle = nullptr) {
+ if (mHandle) {
+ if (mIsBuffer) {
+ mImporter->freeBuffer(mHandle);
+ } else {
+ mImporter->freeStream(mHandle);
+ }
+ }
+
+ mImporter = importer;
+ mHandle = handle;
+ }
+
+ private:
+ bool mIsBuffer;
+ ComposerHandleImporter* mImporter = nullptr;
+ const native_handle_t* mHandle = nullptr;
+ };
+
+ Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle,
+ const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
+ ReplacedHandle* outReplacedBuffer);
+
+ Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
+ const native_handle_t** outStreamHandle,
+ ReplacedHandle* outReplacedStream);
+
+ protected:
+ virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
+ ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize);
+
+ virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize);
+
+ ComposerDisplayResource* findDisplayResourceLocked(Display display);
+
+ ComposerHandleImporter mImporter;
+ ComposerUVMHandle mUVMHandle;
+
+ 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,
+ };
+
+ Error getHandle(Display display, Layer layer, uint32_t slot, Cache cache, bool fromCache,
+ const native_handle_t* rawHandle, const native_handle_t** outHandle,
+ ReplacedHandle* outReplacedHandle);
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
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
index 93da0a5..9b3aa90 100644
--- 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
@@ -173,6 +173,14 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
Error getRenderIntents(Display display, ColorMode mode,
std::vector<RenderIntent>* outIntents) override {
if (!mDispatch.getRenderIntents) {
+ IComposerClient::DisplayType type;
+ if (getDisplayType(display, &type) == Error::BAD_DISPLAY) {
+ return Error::BAD_DISPLAY;
+ }
+ if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3) {
+ return Error::BAD_PARAMETER;
+ }
+
*outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC});
return Error::NONE;
}
@@ -199,6 +207,9 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override {
if (!mDispatch.setColorModeWithRenderIntent) {
+ if (intent < RenderIntent::COLORIMETRIC || intent > RenderIntent::TONE_MAP_ENHANCE) {
+ return Error::BAD_PARAMETER;
+ }
if (intent != RenderIntent::COLORIMETRIC) {
return Error::UNSUPPORTED;
}
@@ -282,6 +293,7 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> {
private:
using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
using BaseType2_1::getColorModes;
+ using BaseType2_1::getDisplayType;
using BaseType2_1::mDevice;
using BaseType2_1::setColorMode;
using BaseType2_1::createVirtualDisplay;
diff --git a/service/2.2/utils/resources/Android.bp b/service/2.2/utils/resources/Android.bp
new file mode 100644
index 0000000..d040143
--- a/dev/null
+++ b/service/2.2/utils/resources/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2019 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_shared {
+ name: "android.hardware.graphics.composer@2.2-resources-vendor",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1-resources-vendor",
+ "android.hardware.graphics.composer@2.2",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.1-resources-vendor",
+ "android.hardware.graphics.composer@2.2",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.2/utils/resources/ComposerResources.cpp b/service/2.2/utils/resources/ComposerResources.cpp
new file mode 100644
index 0000000..a0610a3
--- a/dev/null
+++ b/service/2.2/utils/resources/ComposerResources.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ComposerResources 2.2"
+
+#include "composer-resources/2.2/ComposerResources.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace hal {
+
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+using V2_1::hal::ComposerHandleCache;
+using V2_1::hal::ComposerHandleImporter;
+
+Error ComposerDisplayResource::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);
+}
+
+std::unique_ptr<ComposerResources> ComposerResources::create() {
+ auto resources = std::make_unique<ComposerResources>();
+ return resources->init() ? std::move(resources) : nullptr;
+}
+
+Error ComposerResources::getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle,
+ const native_handle_t** outHandle,
+ ReplacedHandle* 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;
+}
+
+} // namespace hal
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h b/service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h
new file mode 100644
index 0000000..33012e9
--- a/dev/null
+++ b/service/2.2/utils/resources/include/composer-resources/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-resources/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,
+ ReplacedHandle* 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/service/2.3/default/Android.bp b/service/2.3/default/Android.bp
index 4cde6e1..4702122 100644
--- a/service/2.3/default/Android.bp
+++ b/service/2.3/default/Android.bp
@@ -25,12 +25,13 @@ cc_binary {
header_libs: [
"android.hardware.graphics.composer@2.3-passthrough-vendor",
],
+
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",
+ "android.hardware.graphics.composer@2.1-resources-vendor",
+ "android.hardware.graphics.composer@2.2-resources-vendor",
"libbase",
"libbinder",
"libcutils",
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
index d3b29bb..e0e1394 100644
--- 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
@@ -294,9 +294,6 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
(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);
}
@@ -307,6 +304,13 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
return false;
}
+ if (!BaseType2_1::initDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES,
+ &mDispatch.getDisplayCapabilities) ||
+ !BaseType2_1::initDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS,
+ &mDispatch.setDisplayBrightness)) {
+ return false;
+ }
+
this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
&mDispatch.getDisplayIdentificationData);
this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
@@ -317,14 +321,10 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
&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;
}
diff --git a/service/2.4/default/Android.bp b/service/2.4/default/Android.bp
new file mode 100644
index 0000000..5b48e19
--- a/dev/null
+++ b/service/2.4/default/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright 2019 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.4-service.droidlogic",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ vintf_fragments: ["android.hardware.graphics.composer@2.4-service.droidlogic.xml"],
+ init_rc: ["android.hardware.graphics.composer@2.4-service.droidlogic.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.4-passthrough-vendor",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.graphics.composer@2.4",
+ "android.hardware.graphics.composer@2.1-resources-vendor",
+ "android.hardware.graphics.composer@2.2-resources-vendor",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ "libamgralloc_ext_vendor@2",
+ ],
+}
diff --git a/service/2.4/default/OWNERS b/service/2.4/default/OWNERS
new file mode 100644
index 0000000..cc6d937
--- a/dev/null
+++ b/service/2.4/default/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+lpy@google.com
+stoza@google.com
+vhau@google.com
diff --git a/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc
new file mode 100644
index 0000000..ef0573f
--- a/dev/null
+++ b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc
@@ -0,0 +1,7 @@
+service vendor.hwcomposer-2-4 /vendor/bin/hw/android.hardware.graphics.composer@2.4-service.droidlogic
+ 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.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml
new file mode 100644
index 0000000..7f37bbd
--- a/dev/null
+++ b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.graphics.composer</name>
+ <transport>hwbinder</transport>
+ <version>2.4</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/service/2.4/default/service.cpp b/service/2.4/default/service.cpp
new file mode 100644
index 0000000..98dac3e
--- a/dev/null
+++ b/service/2.4/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 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.4/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.4/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_4::IComposer;
+using android::hardware::graphics::composer::V2_4::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.4/utils/passthrough/Android.bp b/service/2.4/utils/passthrough/Android.bp
new file mode 100644
index 0000000..9bd0cf9
--- a/dev/null
+++ b/service/2.4/utils/passthrough/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright 2019 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.4-passthrough-vendor",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ header_libs: [
+ "android.hardware.graphics.composer@2.3-passthrough-vendor",
+ "android.hardware.graphics.composer@2.4-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.3-passthrough-vendor",
+ "android.hardware.graphics.composer@2.4-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
new file mode 100644
index 0000000..d28e006
--- a/dev/null
+++ b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2019 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 <android/hardware/graphics/composer/2.4/IComposerClient.h>
+#include <composer-hal/2.4/ComposerHal.h>
+#include <composer-passthrough/2.3/HwcHal.h>
+#include <hardware/hwcomposer_defs.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_4 {
+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::Config;
+using V2_1::Display;
+using V2_1::Layer;
+using V2_4::Error;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> {
+ public:
+ void registerEventCallback_2_4(hal::ComposerHal::EventCallback_2_4* callback) override {
+ mEventCallback_2_4 = callback;
+
+ BaseType2_1::mDispatch.registerCallback(
+ mDevice, HWC2_CALLBACK_HOTPLUG, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+ BaseType2_1::mDispatch.registerCallback(
+ mDevice, HWC2_CALLBACK_REFRESH, this,
+ reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+ BaseType2_1::mDispatch.registerCallback(
+ mDevice, HWC2_CALLBACK_VSYNC_2_4, this,
+ reinterpret_cast<hwc2_function_pointer_t>(vsync_2_4_Hook));
+ BaseType2_1::mDispatch.registerCallback(
+ mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this,
+ reinterpret_cast<hwc2_function_pointer_t>(vsyncPeriodTimingChangedHook));
+ BaseType2_1::mDispatch.registerCallback(
+ mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this,
+ reinterpret_cast<hwc2_function_pointer_t>(seamlessPossibleHook));
+ }
+
+ void unregisterEventCallback_2_4() override {
+ // we assume the callback functions
+ //
+ // - can be unregistered
+ // - can be in-flight
+ // - will never be called afterward
+ //
+ // which is likely incorrect
+ BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr);
+ BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr);
+ BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this, nullptr);
+ BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED,
+ this, nullptr);
+ BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this,
+ nullptr);
+
+ mEventCallback_2_4 = nullptr;
+ }
+
+ Error getDisplayCapabilities_2_4(
+ Display display,
+ std::vector<IComposerClient::DisplayCapability>* outCapabilities) override {
+ std::vector<V2_3::IComposerClient::DisplayCapability> capabilities;
+ V2_3::Error error_2_3 = BaseType2_3::getDisplayCapabilities(display, &capabilities);
+ Error error = static_cast<Error>(error_2_3);
+ if (error != Error::NONE) {
+ return error;
+ }
+ outCapabilities->clear();
+ outCapabilities->reserve(capabilities.size());
+ for (auto capability : capabilities) {
+ outCapabilities->push_back(static_cast<IComposerClient::DisplayCapability>(capability));
+ }
+ return Error::NONE;
+ }
+
+ Error getDisplayConnectionType(Display display,
+ IComposerClient::DisplayConnectionType* outType) override {
+ if (!mDispatch.getDisplayConnectionType) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t type = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL;
+ int32_t error = mDispatch.getDisplayConnectionType(mDevice, display, &type);
+ *outType = static_cast<IComposerClient::DisplayConnectionType>(type);
+ return static_cast<Error>(error);
+ }
+
+ Error getDisplayAttribute_2_4(Display display, Config config,
+ IComposerClient::Attribute attribute,
+ int32_t* outValue) override {
+ int32_t err = BaseType2_1::mDispatch.getDisplayAttribute(
+ mDevice, display, config, static_cast<int32_t>(attribute), outValue);
+ if (err != HWC2_ERROR_NONE && *outValue == -1) {
+ // Convert the error from hwcomposer2 to IComposerClient definition
+ return Error::BAD_PARAMETER;
+ }
+ return static_cast<Error>(err);
+ }
+
+ Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override {
+ if (!mDispatch.getDisplayVsyncPeriod) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error = mDispatch.getDisplayVsyncPeriod(mDevice, display, outVsyncPeriod);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ return Error::NONE;
+ }
+
+ Error setActiveConfigWithConstraints(
+ Display display, Config config,
+ const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints,
+ VsyncPeriodChangeTimeline* timeline) override {
+ if (!mDispatch.setActiveConfigWithConstraints) {
+ return Error::UNSUPPORTED;
+ }
+
+ hwc_vsync_period_change_constraints_t vsync_period_change_constraints;
+ vsync_period_change_constraints.desiredTimeNanos =
+ vsyncPeriodChangeConstraints.desiredTimeNanos;
+ vsync_period_change_constraints.seamlessRequired =
+ vsyncPeriodChangeConstraints.seamlessRequired;
+
+ hwc_vsync_period_change_timeline_t out_timeline;
+ int32_t error = mDispatch.setActiveConfigWithConstraints(
+ mDevice, display, config, &vsync_period_change_constraints, &out_timeline);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ timeline->newVsyncAppliedTimeNanos = out_timeline.newVsyncAppliedTimeNanos;
+ timeline->refreshRequired = out_timeline.refreshRequired;
+ timeline->refreshTimeNanos = out_timeline.refreshTimeNanos;
+ return Error::NONE;
+ }
+
+ Error setAutoLowLatencyMode(Display display, bool on) override {
+ if (!mDispatch.setAutoLowLatencyMode) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error = mDispatch.setAutoLowLatencyMode(mDevice, display, on);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ return Error::NONE;
+ }
+
+ Error getSupportedContentTypes(
+ Display display,
+ std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override {
+ if (!mDispatch.getSupportedContentTypes) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t count = 0;
+ int32_t error = mDispatch.getSupportedContentTypes(mDevice, display, &count, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ outSupportedContentTypes->resize(count);
+
+ error = mDispatch.getSupportedContentTypes(
+ mDevice, display, &count,
+ reinterpret_cast<std::underlying_type<IComposerClient::ContentType>::type*>(
+ outSupportedContentTypes->data()));
+ if (error != HWC2_ERROR_NONE) {
+ *outSupportedContentTypes = std::vector<IComposerClient::ContentType>();
+ return static_cast<Error>(error);
+ }
+ return Error::NONE;
+ }
+
+ Error setContentType(Display display, IComposerClient::ContentType contentType) override {
+ if (!mDispatch.setContentType) {
+ return Error::UNSUPPORTED;
+ }
+
+ int32_t error =
+ mDispatch.setContentType(mDevice, display, static_cast<int32_t>(contentType));
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+ return Error::NONE;
+ }
+
+ Error validateDisplay_2_4(
+ Display display, std::vector<Layer>* outChangedLayers,
+ std::vector<IComposerClient::Composition>* outCompositionTypes,
+ uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
+ std::vector<uint32_t>* outRequestMasks,
+ IComposerClient::ClientTargetProperty* outClientTargetProperty) override {
+ auto err = static_cast<Error>(BaseType2_1::validateDisplay(
+ display, outChangedLayers, outCompositionTypes, outDisplayRequestMask,
+ outRequestedLayers, outRequestMasks));
+ if (err != Error::NONE) {
+ return err;
+ }
+
+ if (mDispatch.getClientTargetProperty) {
+ hwc_client_target_property_t clientTargetProperty;
+ err = static_cast<Error>(
+ mDispatch.getClientTargetProperty(mDevice, display, &clientTargetProperty));
+ outClientTargetProperty->pixelFormat =
+ static_cast<PixelFormat>(clientTargetProperty.pixelFormat);
+ outClientTargetProperty->dataspace =
+ static_cast<Dataspace>(clientTargetProperty.dataspace);
+ }
+
+ return err;
+ }
+
+ Error setLayerGenericMetadata(Display display, Layer layer, const std::string& key,
+ bool mandatory, const std::vector<uint8_t>& value) override {
+ if (!mDispatch.setLayerGenericMetadata) {
+ return Error::UNSUPPORTED;
+ }
+
+ if (key.size() > std::numeric_limits<uint32_t>::max()) {
+ return Error::BAD_PARAMETER;
+ }
+
+ if (value.size() > std::numeric_limits<uint32_t>::max()) {
+ return Error::BAD_PARAMETER;
+ }
+
+ int32_t error = mDispatch.setLayerGenericMetadata(
+ mDevice, display, layer, static_cast<uint32_t>(key.size()), key.c_str(), mandatory,
+ static_cast<uint32_t>(value.size()), value.data());
+ return static_cast<Error>(error);
+ }
+
+ Error getLayerGenericMetadataKeys(
+ std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override {
+ if (!mDispatch.getLayerGenericMetadataKey) {
+ return Error::UNSUPPORTED;
+ }
+
+ std::vector<IComposerClient::LayerGenericMetadataKey> keys;
+
+ uint32_t index = 0;
+ uint32_t keyLength = 0;
+ while (true) {
+ mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, nullptr, nullptr);
+ if (keyLength == 0) {
+ break;
+ }
+
+ IComposerClient::LayerGenericMetadataKey key;
+ std::string keyName;
+ keyName.resize(keyLength);
+ mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, keyName.data(),
+ &key.mandatory);
+ key.name = keyName;
+ keys.emplace_back(std::move(key));
+
+ // Only attempt to load the first 100 keys to avoid an infinite loop
+ // if something goes wrong
+ if (++index > 100) {
+ break;
+ }
+ }
+
+ *outKeys = std::move(keys);
+ return Error::NONE;
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_3::initDispatch()) {
+ return false;
+ }
+
+ if (!BaseType2_1::initDispatch(HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD,
+ &mDispatch.getDisplayVsyncPeriod) ||
+ !BaseType2_1::initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS,
+ &mDispatch.setActiveConfigWithConstraints)) {
+ return false;
+ }
+
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE,
+ &mDispatch.getDisplayConnectionType);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE,
+ &mDispatch.setAutoLowLatencyMode);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES,
+ &mDispatch.getSupportedContentTypes);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY,
+ &mDispatch.getClientTargetProperty);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_GENERIC_METADATA,
+ &mDispatch.setLayerGenericMetadata);
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_LAYER_GENERIC_METADATA_KEY,
+ &mDispatch.getLayerGenericMetadataKey);
+
+ return true;
+ }
+
+ static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+ int32_t connected) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback_2_4->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_2_4->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_2_4->onVsync(display, timestamp);
+ }
+
+ static void vsync_2_4_Hook(hwc2_callback_data_t callbackData, hwc2_display_t display,
+ int64_t timestamp, hwc2_vsync_period_t vsyncPeriodNanos) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback_2_4->onVsync_2_4(display, timestamp, vsyncPeriodNanos);
+ }
+
+ static void vsyncPeriodTimingChangedHook(hwc2_callback_data_t callbackData,
+ hwc2_display_t display,
+ hwc_vsync_period_change_timeline_t* updated_timeline) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ VsyncPeriodChangeTimeline timeline;
+ timeline.newVsyncAppliedTimeNanos = updated_timeline->newVsyncAppliedTimeNanos;
+ timeline.refreshRequired = updated_timeline->refreshRequired;
+ timeline.refreshTimeNanos = updated_timeline->refreshTimeNanos;
+ hal->mEventCallback_2_4->onVsyncPeriodTimingChanged(display, timeline);
+ }
+
+ static void seamlessPossibleHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
+ auto hal = static_cast<HwcHalImpl*>(callbackData);
+ hal->mEventCallback_2_4->onSeamlessPossible(display);
+ }
+
+ private:
+ struct {
+ HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType;
+ HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod;
+ HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints;
+ HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode;
+ HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes;
+ HWC2_PFN_SET_CONTENT_TYPE setContentType;
+ HWC2_PFN_GET_CLIENT_TARGET_PROPERTY getClientTargetProperty;
+ HWC2_PFN_SET_LAYER_GENERIC_METADATA setLayerGenericMetadata;
+ HWC2_PFN_GET_LAYER_GENERIC_METADATA_KEY getLayerGenericMetadataKey;
+ } mDispatch = {};
+
+ hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr;
+
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_3 = V2_3::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::mDevice;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_4
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h
new file mode 100644
index 0000000..a7cc588
--- a/dev/null
+++ b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2019 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.4/Composer.h>
+#include <composer-hal/2.4/ComposerHal.h>
+#include <composer-passthrough/2.3/HwcLoader.h>
+#include <composer-passthrough/2.4/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_4 {
+namespace passthrough {
+
+class HwcLoader : public V2_3::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_4
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android