summaryrefslogtreecommitdiff
path: root/libs/ui/BufferHubBuffer.cpp
diff options
context:
space:
mode:
author Fan Xu <fanxu@google.com> 2018-12-05 13:34:48 -0800
committer Tianyu Jiang <tianyuj@google.com> 2019-01-11 18:28:53 +0000
commit021776e289849daf3b3c327d5b0a57ee55873225 (patch)
treea8c639255ff3eb554e55354f7cda6094164aafbd /libs/ui/BufferHubBuffer.cpp
parent6b4b1e5b1f7ad32dcadc49a2455370003b20897a (diff)
Refactor BufferHubBuffer to use hwbinder
Entirely move BufferHubBuffer off pdx dependency and using hwbinder backend and rewrite test cases to fit in current behavior. Remove duplicated test cases in buffer_hub-test. Commented out BufferHubBuffer related parts and remove related include and using statement. Add hidl interface dependency to libs/gui build file to avoid compile errors. Test: BufferHub_test, GraphicBuffer_test, buffer_hub-test Bug: 116681016 Change-Id: I9d8f734f681e04d3d50b7a02c27b17df8c66cbad
Diffstat (limited to 'libs/ui/BufferHubBuffer.cpp')
-rw-r--r--libs/ui/BufferHubBuffer.cpp316
1 files changed, 182 insertions, 134 deletions
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 11849608ba..c70f18823c 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,150 +14,190 @@
* limitations under the License.
*/
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
-#pragma clang diagnostic pop
-
#include <poll.h>
#include <android-base/unique_fd.h>
+#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <log/log.h>
#include <ui/BufferHubBuffer.h>
#include <ui/BufferHubDefs.h>
-
-using android::base::unique_fd;
-using android::dvr::BufferTraits;
-using android::dvr::DetachedBufferRPC;
-using android::dvr::NativeHandleWrapper;
-
-// TODO(b/112338294): Remove PDX dependencies from libui.
-using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
+#include <utils/Trace.h>
+
+using ::android::base::unique_fd;
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
+using ::android::frameworks::bufferhub::V1_0::BufferTraits;
+using ::android::frameworks::bufferhub::V1_0::IBufferClient;
+using ::android::frameworks::bufferhub::V1_0::IBufferHub;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
namespace android {
-namespace {
-
-// TODO(b/112338294): Remove this string literal after refactoring BufferHub
-// to use Binder.
-static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kHighBitsMask;
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Create(uint32_t width, uint32_t height,
+ uint32_t layerCount, uint32_t format,
+ uint64_t usage, size_t userMetadataSize) {
+ auto buffer = std::unique_ptr<BufferHubBuffer>(
+ new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
+ return buffer->IsValid() ? std::move(buffer) : nullptr;
+}
-} // namespace
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Import(const native_handle_t* token) {
+ if (token == nullptr) {
+ ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
+ return nullptr;
+ }
-BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
+ auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
+ return buffer->IsValid() ? std::move(buffer) : nullptr;
+}
-BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
- : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
+BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
+ uint32_t format, uint64_t usage, size_t userMetadataSize) {
+ ATRACE_CALL();
+ ALOGD("%s: width=%u height=%u layerCount=%u, format=%u "
+ "usage=%" PRIx64 " mUserMetadataSize=%zu",
+ __FUNCTION__, width, height, layerCount, format, usage, userMetadataSize);
+
+ sp<IBufferHub> bufferhub = IBufferHub::getService();
+ if (bufferhub.get() == nullptr) {
+ ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+ return;
+ }
-BufferHubClient::~BufferHubClient() {}
+ AHardwareBuffer_Desc aDesc = {width, height, layerCount, format,
+ usage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ BufferHubStatus ret;
+ sp<IBufferClient> client;
+ BufferTraits bufferTraits;
+ IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& status, const auto& outClient,
+ const auto& traits) {
+ ret = status;
+ client = std::move(outClient);
+ bufferTraits = std::move(traits);
+ };
+
+ if (!bufferhub->allocateBuffer(desc, static_cast<uint32_t>(userMetadataSize), alloc_cb)
+ .isOk()) {
+ ALOGE("%s: allocateBuffer transaction failed!", __FUNCTION__);
+ return;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: allocateBuffer failed with error %u.", __FUNCTION__, ret);
+ return;
+ } else if (client == nullptr) {
+ ALOGE("%s: allocateBuffer got null BufferClient.", __FUNCTION__);
+ return;
+ }
-bool BufferHubClient::IsValid() const {
- return IsConnected() && GetChannelHandle().valid();
+ const int importRet = initWithBufferTraits(bufferTraits);
+ if (importRet < 0) {
+ ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+ client->close();
+ }
+ mBufferClient = std::move(client);
}
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
- if (IsConnected()) {
- return std::move(GetChannelHandle());
- } else {
- return {};
+BufferHubBuffer::BufferHubBuffer(const native_handle_t* token) {
+ sp<IBufferHub> bufferhub = IBufferHub::getService();
+ if (bufferhub.get() == nullptr) {
+ ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+ return;
}
-}
-BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
- uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
- ATRACE_CALL();
- ALOGD("%s: width=%u height=%u layerCount=%u, format=%u usage=%" PRIx64 " mUserMetadataSize=%zu",
- __FUNCTION__, width, height, layerCount, format, usage, mUserMetadataSize);
-
- auto status =
- mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
- usage, mUserMetadataSize);
- if (!status) {
- ALOGE("%s: Failed to create detached buffer: %s", __FUNCTION__,
- status.GetErrorMessage().c_str());
- mClient.Close(-status.error());
+ BufferHubStatus ret;
+ sp<IBufferClient> client;
+ BufferTraits bufferTraits;
+ IBufferHub::importBuffer_cb import_cb = [&](const auto& status, const auto& outClient,
+ const auto& traits) {
+ ret = status;
+ client = std::move(outClient);
+ bufferTraits = std::move(traits);
+ };
+
+ // hidl_handle(native_handle_t*) simply creates a raw pointer reference withouth ownership
+ // transfer.
+ if (!bufferhub->importBuffer(hidl_handle(token), import_cb).isOk()) {
+ ALOGE("%s: importBuffer transaction failed!", __FUNCTION__);
+ return;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: importBuffer failed with error %u.", __FUNCTION__, ret);
+ return;
+ } else if (client == nullptr) {
+ ALOGE("%s: importBuffer got null BufferClient.", __FUNCTION__);
+ return;
}
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
- mClient.Close(ret);
+ const int importRet = initWithBufferTraits(bufferTraits);
+ if (importRet < 0) {
+ ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+ client->close();
}
+ mBufferClient = std::move(client);
}
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
- : mClient(std::move(mChannelHandle)) {
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
- mClient.Close(ret);
+BufferHubBuffer::~BufferHubBuffer() {
+ // Close buffer client to avoid possible race condition: user could first duplicate and hold
+ // token with the original buffer gone, and then try to import the token. The close function
+ // will explicitly invalidate the token to avoid this.
+ if (mBufferClient != nullptr) {
+ if (!mBufferClient->close().isOk()) {
+ ALOGE("%s: close BufferClient transaction failed!", __FUNCTION__);
+ }
}
}
-int BufferHubBuffer::ImportGraphicBuffer() {
+int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) {
ATRACE_CALL();
- auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
- if (!status) {
- ALOGE("%s: Failed to import GraphicBuffer: %s", __FUNCTION__,
- status.GetErrorMessage().c_str());
- return -status.error();
+ if (bufferTraits.bufferInfo.getNativeHandle() == nullptr) {
+ ALOGE("%s: missing buffer info handle.", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if (bufferTraits.bufferHandle.getNativeHandle() == nullptr) {
+ ALOGE("%s: missing gralloc handle.", __FUNCTION__);
+ return -EINVAL;
}
- BufferTraits<LocalHandle> bufferTraits = status.take();
- if (bufferTraits.id() < 0) {
- ALOGE("%s: Received an invalid id!", __FUNCTION__);
- return -EIO;
+ int bufferId = bufferTraits.bufferInfo->data[1];
+ if (bufferId < 0) {
+ ALOGE("%s: Received an invalid (negative) id!", __FUNCTION__);
+ return -EINVAL;
}
- // Stash the buffer id to replace the value in mId.
- const int bufferId = bufferTraits.id();
+ uint32_t clientBitMask;
+ memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[2], sizeof(clientBitMask));
+ if (clientBitMask == 0U) {
+ ALOGE("%s: Received a invalid client state mask!", __FUNCTION__);
+ return -EINVAL;
+ }
- // Import the metadata.
- LocalHandle metadataHandle = bufferTraits.take_metadata_handle();
- unique_fd metadataFd(metadataHandle.Release());
- mMetadata = BufferHubMetadata::Import(std::move(metadataFd));
+ // Import the metadata. Dup since hidl_handle owns the fd
+ unique_fd ashmemFd(dup(bufferTraits.bufferInfo->data[0]));
+ mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
if (!mMetadata.IsValid()) {
ALOGE("%s: invalid metadata.", __FUNCTION__);
- return -ENOMEM;
+ return -EINVAL;
}
- if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
- ALOGE("%s: metadata buffer too small: %zu, expected: %" PRIu64 ".", __FUNCTION__,
- mMetadata.metadata_size(), bufferTraits.metadata_size());
- return -ENOMEM;
+ uint32_t userMetadataSize;
+ memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[3], sizeof(userMetadataSize));
+ if (mMetadata.user_metadata_size() != userMetadataSize) {
+ ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
+ userMetadataSize, mMetadata.user_metadata_size());
+ return -EINVAL;
}
- size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
+ size_t metadataSize = static_cast<size_t>(mMetadata.metadata_size());
if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
return -EINVAL;
@@ -178,24 +218,14 @@ int BufferHubBuffer::ImportGraphicBuffer() {
// Import the buffer: We only need to hold on the native_handle_t here so that
// GraphicBuffer instance can be created in future.
- mBufferHandle = bufferTraits.take_buffer_handle();
-
- // Populate buffer desc based on buffer traits.
- mBufferDesc.width = bufferTraits.width();
- mBufferDesc.height = bufferTraits.height();
- mBufferDesc.layers = bufferTraits.layer_count();
- mBufferDesc.format = bufferTraits.format();
- mBufferDesc.usage = bufferTraits.usage();
- mBufferDesc.stride = bufferTraits.stride();
- mBufferDesc.rfu0 = 0U;
- mBufferDesc.rfu1 = 0U;
-
- // If all imports succeed, replace the previous buffer and id.
+ mBufferHandle = std::move(bufferTraits.bufferHandle);
+ memcpy(&mBufferDesc, &bufferTraits.bufferDesc, sizeof(AHardwareBuffer_Desc));
+
mId = bufferId;
- mClientStateMask = bufferTraits.client_state_mask();
+ mClientStateMask = clientBitMask;
// TODO(b/112012161) Set up shared fences.
- ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, id(),
+ ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, mId,
buffer_state_->load(std::memory_order_acquire));
return 0;
}
@@ -225,7 +255,7 @@ int BufferHubBuffer::Gain() {
int BufferHubBuffer::Post() {
uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- uint32_t updated_buffer_state = (~mClientStateMask) & kHighBitsMask;
+ uint32_t updated_buffer_state = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
do {
if (!IsClientGained(current_buffer_state, mClientStateMask)) {
ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
@@ -283,24 +313,42 @@ int BufferHubBuffer::Release() {
return 0;
}
-int BufferHubBuffer::Poll(int timeoutMs) {
- ATRACE_CALL();
-
- pollfd p = {mClient.event_fd(), POLLIN, 0};
- return poll(&p, 1, timeoutMs);
+bool BufferHubBuffer::IsValid() const {
+ // TODO(b/68770788): check eventFd once implemented
+ return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
+ mMetadata.IsValid() && mBufferClient != nullptr;
}
-Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
- ATRACE_CALL();
- ALOGD("%s: id=%d.", __FUNCTION__, mId);
+// TODO(b/68770788): implement Poll() once we have event fd
+int BufferHubBuffer::Poll(int /* timeoutMs */) {
+ return -ENOSYS;
+}
- auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
+native_handle_t* BufferHubBuffer::Duplicate() {
+ if (mBufferClient == nullptr) {
+ ALOGE("%s: missing BufferClient!", __FUNCTION__);
+ return nullptr;
+ }
- if (!statusOrHandle.ok()) {
- ALOGE("%s: Failed to duplicate buffer (id=%d): %s.", __FUNCTION__, mId,
- statusOrHandle.GetErrorMessage().c_str());
+ hidl_handle token;
+ BufferHubStatus ret;
+ IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+ token = std::move(outToken);
+ ret = status;
+ };
+
+ if (!mBufferClient->duplicate(dup_cb).isOk()) {
+ ALOGE("%s: duplicate transaction failed!", __FUNCTION__);
+ return nullptr;
+ } else if (ret != BufferHubStatus::NO_ERROR) {
+ ALOGE("%s: duplicate failed with error %u.", __FUNCTION__, ret);
+ return nullptr;
+ } else if (token.getNativeHandle() == nullptr) {
+ ALOGE("%s: duplicate got null token.", __FUNCTION__);
+ return nullptr;
}
- return statusOrHandle;
+
+ return native_handle_clone(token.getNativeHandle());
}
} // namespace android