libgui: Add simpler methods to ConsumerBase and BufferItemConsumer.
Now we can detach a buffer directly.
BYPASS_IGBP_IGBC_API_REASON=warren buffers
Bug: 340933754
Flag: com.android.graphics.libgui.flags.wb_platform_api_improvements
Test: new test in libgui_test
Change-Id: Ib14e645a04b21b3233522d2d20ee5aaa09fe563c
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index e6331e7..eeb8f19 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -21,8 +21,11 @@
#include <inttypes.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
+#include <ui/BufferQueueDefs.h>
+#include <ui/GraphicBuffer.h>
#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
// #define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
@@ -87,17 +90,38 @@
status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
const sp<Fence>& releaseFence) {
- status_t err;
+ Mutex::Autolock _l(mMutex);
+ return releaseBufferSlotLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
+}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+status_t BufferItemConsumer::releaseBuffer(const sp<GraphicBuffer>& buffer,
+ const sp<Fence>& releaseFence) {
Mutex::Autolock _l(mMutex);
- err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+
+ int slotIndex = getSlotForBufferLocked(buffer);
+ if (slotIndex == INVALID_BUFFER_SLOT) {
+ return BAD_VALUE;
+ }
+
+ return releaseBufferSlotLocked(slotIndex, buffer, releaseFence);
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+status_t BufferItemConsumer::releaseBufferSlotLocked(int slotIndex, const sp<GraphicBuffer>& buffer,
+ const sp<Fence>& releaseFence) {
+ status_t err;
+
+ err = addReleaseFenceLocked(slotIndex, buffer, releaseFence);
if (err != OK) {
BI_LOGE("Failed to addReleaseFenceLocked");
}
- err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
- EGL_NO_SYNC_KHR);
+ err = releaseBufferLocked(slotIndex, buffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
if (err != OK && err != IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
BI_LOGE("Failed to release buffer: %s (%d)",
strerror(-err), err);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index b625c3f..19b9c8b 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -30,9 +30,10 @@
#include <cutils/atomic.h>
#include <gui/BufferItem.h>
+#include <gui/ConsumerBase.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <gui/ConsumerBase.h>
+#include <ui/BufferQueueDefs.h>
#include <private/gui/ComposerService.h>
@@ -40,6 +41,8 @@
#include <utils/String8.h>
#include <utils/Trace.h>
+#include <com_android_graphics_libgui_flags.h>
+
// Macros for including the ConsumerBase name in log messages
#define CB_LOGV(x, ...) ALOGV("[%s] " x, mName.c_str(), ##__VA_ARGS__)
// #define CB_LOGD(x, ...) ALOGD("[%s] " x, mName.c_str(), ##__VA_ARGS__)
@@ -96,6 +99,35 @@
abandon();
}
+int ConsumerBase::getSlotForBufferLocked(const sp<GraphicBuffer>& buffer) {
+ if (!buffer) {
+ return BufferQueue::INVALID_BUFFER_SLOT;
+ }
+
+ uint64_t id = buffer->getId();
+ for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
+ auto& slot = mSlots[i];
+ if (slot.mGraphicBuffer && slot.mGraphicBuffer->getId() == id) {
+ return i;
+ }
+ }
+
+ return BufferQueue::INVALID_BUFFER_SLOT;
+}
+
+status_t ConsumerBase::detachBufferLocked(int slotIndex) {
+ status_t result = mConsumer->detachBuffer(slotIndex);
+
+ if (result != NO_ERROR) {
+ CB_LOGE("Failed to detach buffer: %d", result);
+ return result;
+ }
+
+ freeBufferLocked(slotIndex);
+
+ return result;
+}
+
void ConsumerBase::freeBufferLocked(int slotIndex) {
CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
mSlots[slotIndex].mGraphicBuffer = nullptr;
@@ -252,16 +284,30 @@
return NO_INIT;
}
- status_t result = mConsumer->detachBuffer(slot);
- if (result != NO_ERROR) {
- CB_LOGE("Failed to detach buffer: %d", result);
- return result;
+ return detachBufferLocked(slot);
+}
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+status_t ConsumerBase::detachBuffer(const sp<GraphicBuffer>& buffer) {
+ CB_LOGV("detachBuffer");
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ if (buffer == nullptr) {
+ return BAD_VALUE;
}
- freeBufferLocked(slot);
+ int slotIndex = getSlotForBufferLocked(buffer);
+ if (slotIndex == BufferQueue::INVALID_BUFFER_SLOT) {
+ return BAD_VALUE;
+ }
- return result;
+ return detachBufferLocked(slotIndex);
}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
Mutex::Autolock _l(mMutex);
diff --git a/libs/gui/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
index a905610..e383a40 100644
--- a/libs/gui/include/gui/BufferItemConsumer.h
+++ b/libs/gui/include/gui/BufferItemConsumer.h
@@ -17,13 +17,15 @@
#ifndef ANDROID_GUI_BUFFERITEMCONSUMER_H
#define ANDROID_GUI_BUFFERITEMCONSUMER_H
-#include <gui/ConsumerBase.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferQueue.h>
+#include <gui/ConsumerBase.h>
#define ANDROID_GRAPHICS_BUFFERITEMCONSUMER_JNI_ID "mBufferItemConsumer"
namespace android {
+class GraphicBuffer;
class String8;
/**
@@ -85,7 +87,15 @@
status_t releaseBuffer(const BufferItem &item,
const sp<Fence>& releaseFence = Fence::NO_FENCE);
- private:
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ status_t releaseBuffer(const sp<GraphicBuffer>& buffer,
+ const sp<Fence>& releaseFence = Fence::NO_FENCE);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+private:
+ status_t releaseBufferSlotLocked(int slotIndex, const sp<GraphicBuffer>& buffer,
+ const sp<Fence>& releaseFence);
+
void freeBufferLocked(int slotIndex) override;
// mBufferFreedListener is the listener object that will be called when
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 8ff0cd0..a031e66 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -17,18 +17,16 @@
#ifndef ANDROID_GUI_CONSUMERBASE_H
#define ANDROID_GUI_CONSUMERBASE_H
+#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferQueueDefs.h>
#include <gui/IConsumerListener.h>
#include <gui/IGraphicBufferConsumer.h>
#include <gui/OccupancyTracker.h>
-
#include <ui/PixelFormat.h>
-
#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/threads.h>
-
namespace android {
// ----------------------------------------------------------------------------
@@ -81,7 +79,13 @@
void setFrameAvailableListener(const wp<FrameAvailableListener>& listener);
// See IGraphicBufferConsumer::detachBuffer
- status_t detachBuffer(int slot);
+ status_t detachBuffer(int slot) __attribute((
+ deprecated("Please use the GraphicBuffer variant--slots are deprecated.")));
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ // See IGraphicBufferConsumer::detachBuffer
+ status_t detachBuffer(const sp<GraphicBuffer>& buffer);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
// See IGraphicBufferConsumer::setDefaultBufferSize
status_t setDefaultBufferSize(uint32_t width, uint32_t height);
@@ -150,6 +154,10 @@
virtual void onBuffersReleased() override;
virtual void onSidebandStreamChanged() override;
+ virtual int getSlotForBufferLocked(const sp<GraphicBuffer>& buffer);
+
+ virtual status_t detachBufferLocked(int slotIndex);
+
// freeBufferLocked frees up the given buffer slot. If the slot has been
// initialized this will release the reference to the GraphicBuffer in that
// slot. Otherwise it has no effect.
diff --git a/libs/gui/tests/BufferItemConsumer_test.cpp b/libs/gui/tests/BufferItemConsumer_test.cpp
index 6880678..7d33f28 100644
--- a/libs/gui/tests/BufferItemConsumer_test.cpp
+++ b/libs/gui/tests/BufferItemConsumer_test.cpp
@@ -17,10 +17,12 @@
#define LOG_TAG "BufferItemConsumer_test"
//#define LOG_NDEBUG 0
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+#include <ui/GraphicBuffer.h>
namespace android {
@@ -42,6 +44,17 @@
BufferItemConsumerTest* mTest;
};
+ struct TrackingProducerListener : public BnProducerListener {
+ TrackingProducerListener(BufferItemConsumerTest* test) : mTest(test) {}
+
+ virtual void onBufferReleased() override {}
+ virtual bool needsReleaseNotify() override { return true; }
+ virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
+ virtual void onBufferDetached(int slot) override { mTest->HandleBufferDetached(slot); }
+
+ BufferItemConsumerTest* mTest;
+ };
+
void SetUp() override {
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mBIC =
@@ -51,7 +64,7 @@
mBFL = new BufferFreedListener(this);
mBIC->setBufferFreedListener(mBFL);
- sp<IProducerListener> producerListener = new StubProducerListener();
+ sp<IProducerListener> producerListener = new TrackingProducerListener(this);
IGraphicBufferProducer::QueueBufferOutput bufferOutput;
ASSERT_EQ(NO_ERROR,
mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU,
@@ -71,6 +84,13 @@
ALOGD("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount);
}
+ void HandleBufferDetached(int slot) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mDetachedBufferSlots.push_back(slot);
+ ALOGD("HandleBufferDetached, slot=%d mDetachedBufferSlots-count=%zu", slot,
+ mDetachedBufferSlots.size());
+ }
+
void DequeueBuffer(int* outSlot) {
ASSERT_NE(outSlot, nullptr);
@@ -120,6 +140,7 @@
std::mutex mMutex;
int mFreedBufferCount{0};
+ std::vector<int> mDetachedBufferSlots = {};
sp<BufferItemConsumer> mBIC;
sp<BufferFreedListener> mBFL;
@@ -203,4 +224,19 @@
ASSERT_EQ(1, GetFreedBufferCount());
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+// Test that delete BufferItemConsumer triggers onBufferFreed.
+TEST_F(BufferItemConsumerTest, DetachBufferWithBuffer) {
+ int slot;
+ // Let buffer go through the cycle at least once.
+ DequeueBuffer(&slot);
+ QueueBuffer(slot);
+ AcquireBuffer(&slot);
+
+ sp<GraphicBuffer> buffer = mBuffers[slot];
+ EXPECT_EQ(OK, mBIC->detachBuffer(buffer));
+ EXPECT_THAT(mDetachedBufferSlots, testing::ElementsAre(slot));
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
} // namespace android