diff options
Diffstat (limited to 'libs/ui/BufferHubBuffer.cpp')
| -rw-r--r-- | libs/ui/BufferHubBuffer.cpp | 316 |
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 |