Merge changes from topic "bh_eventfd"
* changes:
Add BufferHubEventFd to bufferhub system
Allow create BufferHubEventFd from existing fd
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 6310f29..9669135 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -167,19 +167,26 @@
return -EINVAL;
}
- int bufferId = bufferTraits.bufferInfo->data[1];
+ int bufferId = bufferTraits.bufferInfo->data[2];
if (bufferId < 0) {
ALOGE("%s: Received an invalid (negative) id!", __FUNCTION__);
return -EINVAL;
}
uint32_t clientBitMask;
- memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[2], sizeof(clientBitMask));
+ memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[3], sizeof(clientBitMask));
if (clientBitMask == 0U) {
ALOGE("%s: Received a invalid client state mask!", __FUNCTION__);
return -EINVAL;
}
+ const int eventFd = bufferTraits.bufferInfo->data[1];
+ if (eventFd < 0) {
+ ALOGE("%s: Received a invalid event fd!", __FUNCTION__);
+ return -EINVAL;
+ }
+ mEventFd = BufferHubEventFd(eventFd);
+
// Import the metadata. Dup since hidl_handle owns the fd
unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0));
mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
@@ -190,7 +197,7 @@
}
uint32_t userMetadataSize;
- memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[3], sizeof(userMetadataSize));
+ memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[4], 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());
@@ -314,9 +321,8 @@
}
bool BufferHubBuffer::IsValid() const {
- // TODO(b/68770788): check eventFd once implemented
return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
- mMetadata.IsValid() && mBufferClient != nullptr;
+ mEventFd.get() >= 0 && mMetadata.IsValid() && mBufferClient != nullptr;
}
native_handle_t* BufferHubBuffer::Duplicate() {
diff --git a/libs/ui/BufferHubEventFd.cpp b/libs/ui/BufferHubEventFd.cpp
index 978b352..bffc2ca 100644
--- a/libs/ui/BufferHubEventFd.cpp
+++ b/libs/ui/BufferHubEventFd.cpp
@@ -23,6 +23,8 @@
BufferHubEventFd::BufferHubEventFd() : mFd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) {}
+BufferHubEventFd::BufferHubEventFd(int fd) : mFd(fd) {}
+
status_t BufferHubEventFd::signal() const {
if (!isValid()) {
ALOGE("%s: cannot signal an invalid eventfd.", __FUNCTION__);
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index c6a4a23..42d9320 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -21,6 +21,7 @@
#include <android/hardware_buffer.h>
#include <cutils/native_handle.h>
#include <ui/BufferHubDefs.h>
+#include <ui/BufferHubEventFd.h>
#include <ui/BufferHubMetadata.h>
namespace android {
@@ -55,6 +56,8 @@
return native_handle_clone(mBufferHandle.getNativeHandle());
}
+ const BufferHubEventFd& eventFd() const { return mEventFd; }
+
// Returns the current value of MetadataHeader::buffer_state.
uint32_t buffer_state() {
return mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire);
@@ -123,6 +126,9 @@
// Wraps the gralloc buffer handle of this buffer.
hardware::hidl_handle mBufferHandle;
+ // Event fd used for signalling buffer state changes. Shared by all clients of the same buffer.
+ BufferHubEventFd mEventFd;
+
// An ashmem-based metadata object. The same shared memory are mapped to the
// bufferhubd daemon and all buffer clients.
BufferHubMetadata mMetadata;
diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h
index 069f0dc..43d900c 100644
--- a/libs/ui/include/ui/BufferHubDefs.h
+++ b/libs/ui/include/ui/BufferHubDefs.h
@@ -170,15 +170,16 @@
*
* It's definition should follow the following format:
* {
- * NumFds = 1,
+ * NumFds = 2,
* NumInts = 3,
* data[0] = Ashmem fd for BufferHubMetadata,
- * data[1] = buffer id,
- * data[2] = client state bit mask,
- * data[3] = user metadata size,
+ * data[1] = event fd,
+ * data[2] = buffer id,
+ * data[3] = client state bit mask,
+ * data[4] = user metadata size,
* }
*/
-static constexpr int kBufferInfoNumFds = 1;
+static constexpr int kBufferInfoNumFds = 2;
static constexpr int kBufferInfoNumInts = 3;
} // namespace BufferHubDefs
diff --git a/libs/ui/include/ui/BufferHubEventFd.h b/libs/ui/include/ui/BufferHubEventFd.h
index 0e856bd..8772304 100644
--- a/libs/ui/include/ui/BufferHubEventFd.h
+++ b/libs/ui/include/ui/BufferHubEventFd.h
@@ -30,6 +30,12 @@
BufferHubEventFd();
/**
+ * Constructs from a valid event fd. Caller is responsible for the validity of the fd. Takes
+ * ownership.
+ */
+ BufferHubEventFd(int fd);
+
+ /**
* Returns whether this BufferHubEventFd holds a valid event_fd.
*/
bool isValid() const { return get() >= 0; }
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index cd744cd..77ea19c 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "BufferHubBufferTest"
+#include <sys/epoll.h>
+
#include <android/hardware_buffer.h>
#include <cutils/native_handle.h>
#include <gmock/gmock.h>
@@ -23,6 +25,7 @@
#include <hidl/ServiceManagement.h>
#include <hwbinder/IPCThreadState.h>
#include <ui/BufferHubBuffer.h>
+#include <ui/BufferHubEventFd.h>
namespace android {
@@ -160,6 +163,30 @@
// Both buffer instances should be in released state currently.
EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
+
+ // The event fd should behave like duped event fds.
+ const BufferHubEventFd& eventFd1 = b1->eventFd();
+ const BufferHubEventFd& eventFd2 = b2->eventFd();
+
+ base::unique_fd epollFd(epoll_create(64));
+ ASSERT_GE(epollFd.get(), 0);
+
+ // Add eventFd1 to epoll set, and signal eventFd2.
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e), 0);
+
+ std::array<epoll_event, 1> events;
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventFd2.signal();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+
+ // The epoll fd is edge triggered, so it only responds to the eventFd once.
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventFd2.signal();
+ eventFd2.clear();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
}
TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
diff --git a/libs/ui/tests/BufferHubEventFd_test.cpp b/libs/ui/tests/BufferHubEventFd_test.cpp
index 92fb33f..2c9aa57 100644
--- a/libs/ui/tests/BufferHubEventFd_test.cpp
+++ b/libs/ui/tests/BufferHubEventFd_test.cpp
@@ -91,22 +91,21 @@
// Technically, the dupliated eventFd and the original eventFd are pointing
// to the same kernel object. This test signals the duplicated eventFd but epolls the origianl
// eventFd.
- base::unique_fd dupedEventFd(dup(eventFd.get()));
+ BufferHubEventFd dupedEventFd(dup(eventFd.get()));
ASSERT_GE(dupedEventFd.get(), 0);
std::array<epoll_event, 1> events;
EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
- eventfd_write(dupedEventFd.get(), 1);
+ dupedEventFd.signal();
EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
// The epoll fd is edge triggered, so it only responds to the eventFd once.
EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
- eventfd_write(dupedEventFd.get(), 1);
+ dupedEventFd.signal();
- eventfd_t value;
- eventfd_read(dupedEventFd.get(), &value);
+ dupedEventFd.clear();
EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
}
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index ccefe2f..ae357cd 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -65,9 +65,9 @@
std::lock_guard<std::mutex> lock(mClientSetMutex);
mClientSet.emplace(client);
- hidl_handle bufferInfo =
- buildBufferInfo(node->id(), node->AddNewActiveClientsBitToMask(),
- node->user_metadata_size(), node->metadata().ashmem_fd());
+ hidl_handle bufferInfo = buildBufferInfo(node->id(), node->AddNewActiveClientsBitToMask(),
+ node->user_metadata_size(), node->eventFd().get(),
+ node->metadata().ashmem_fd());
BufferTraits bufferTraits = {/*bufferDesc=*/description,
/*bufferHandle=*/hidl_handle(node->buffer_handle()),
/*bufferInfo=*/bufferInfo};
@@ -156,7 +156,7 @@
hidl_handle bufferInfo =
buildBufferInfo(node->id(), clientStateMask, node->user_metadata_size(),
- node->metadata().ashmem_fd());
+ node->eventFd().get(), node->metadata().ashmem_fd());
BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
/*bufferHandle=*/hidl_handle(node->buffer_handle()),
/*bufferInfo=*/bufferInfo};
@@ -345,16 +345,18 @@
// Implementation of this function should be consistent with the definition of bufferInfo handle in
// ui/BufferHubDefs.h.
hidl_handle BufferHubService::buildBufferInfo(int bufferId, uint32_t clientBitMask,
- uint32_t userMetadataSize, const int metadataFd) {
+ uint32_t userMetadataSize, const int eventFd,
+ const int metadataFd) {
native_handle_t* infoHandle = native_handle_create(BufferHubDefs::kBufferInfoNumFds,
BufferHubDefs::kBufferInfoNumInts);
infoHandle->data[0] = dup(metadataFd);
- infoHandle->data[1] = bufferId;
+ infoHandle->data[1] = dup(eventFd);
+ infoHandle->data[2] = bufferId;
// Use memcpy to convert to int without missing digit.
// TOOD(b/121345852): use bit_cast to unpack bufferInfo when C++20 becomes available.
- memcpy(&infoHandle->data[2], &clientBitMask, sizeof(clientBitMask));
- memcpy(&infoHandle->data[3], &userMetadataSize, sizeof(userMetadataSize));
+ memcpy(&infoHandle->data[3], &clientBitMask, sizeof(clientBitMask));
+ memcpy(&infoHandle->data[4], &userMetadataSize, sizeof(userMetadataSize));
hidl_handle bufferInfo;
bufferInfo.setTo(infoHandle, /*shouldOwn=*/true);
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index 23e664e..9015e05 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -59,7 +59,7 @@
private:
// Helper function to build BufferTraits.bufferInfo handle
hidl_handle buildBufferInfo(int bufferId, uint32_t clientBitMask, uint32_t userMetadataSize,
- const int metadataFd);
+ const int eventFd, const int metadataFd);
// Helper function to remove all the token belongs to a specific client.
void removeTokenByClient(const BufferClient* client);
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index b7a195b..4729e1c 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -4,6 +4,7 @@
#include <android/hardware_buffer.h>
#include <bufferhub/BufferHubIdGenerator.h>
#include <cutils/native_handle.h>
+#include <ui/BufferHubEventFd.h>
#include <ui/BufferHubMetadata.h>
namespace android {
@@ -31,6 +32,9 @@
const native_handle_t* buffer_handle() const { return buffer_handle_; }
const AHardwareBuffer_Desc& buffer_desc() const { return buffer_desc_; }
+ // Accessor of event fd.
+ const BufferHubEventFd& eventFd() const { return mEventFd; }
+
// Accessors of metadata.
const BufferHubMetadata& metadata() const { return metadata_; }
@@ -60,6 +64,9 @@
native_handle_t* buffer_handle_;
AHardwareBuffer_Desc buffer_desc_;
+ // Eventfd used for signalling buffer events among the clients of the buffer.
+ BufferHubEventFd mEventFd;
+
// Metadata in shared memory.
BufferHubMetadata metadata_;