Skip to content

Commit 6075c6a

Browse files
Jim ShargoAndroid (Google) Code Review
authored andcommitted
Merge changes I13283720,Iddd8f902 into main
* changes: BufferItemConsumer: Add/expose methods BufferQueue: Fix deadlock in setMaxAcquiredBufferCount
2 parents 269580e + f3b0012 commit 6075c6a

9 files changed

Lines changed: 108 additions & 16 deletions

libs/gui/BufferItemConsumer.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//#define LOG_NDEBUG 0
1818
#define LOG_TAG "BufferItemConsumer"
1919
//#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20+
#include <utils/Errors.h>
2021
#include <utils/Log.h>
2122

2223
#include <inttypes.h>
@@ -132,13 +133,36 @@ status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
132133
return OK;
133134
}
134135

136+
status_t BufferItemConsumer::attachBuffer(const sp<GraphicBuffer>& buffer) {
137+
if (!buffer) {
138+
BI_LOGE("BufferItemConsumer::attachBuffer no input buffer specified.");
139+
return BAD_VALUE;
140+
}
141+
142+
Mutex::Autolock _l(mMutex);
143+
144+
int slot = INVALID_BUFFER_SLOT;
145+
status_t status = mConsumer->attachBuffer(&slot, buffer);
146+
if (status != OK) {
147+
BI_LOGE("BufferItemConsumer::attachBuffer unable to attach buffer %d", status);
148+
return status;
149+
}
150+
151+
mSlots[slot] = {
152+
.mGraphicBuffer = buffer,
153+
.mFence = nullptr,
154+
.mFrameNumber = 0,
155+
};
156+
157+
return OK;
158+
}
159+
135160
status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
136161
const sp<Fence>& releaseFence) {
137162
Mutex::Autolock _l(mMutex);
138163
return releaseBufferSlotLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
139164
}
140165

141-
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
142166
status_t BufferItemConsumer::releaseBuffer(const sp<GraphicBuffer>& buffer,
143167
const sp<Fence>& releaseFence) {
144168
Mutex::Autolock _l(mMutex);
@@ -154,7 +178,6 @@ status_t BufferItemConsumer::releaseBuffer(const sp<GraphicBuffer>& buffer,
154178

155179
return releaseBufferSlotLocked(slotIndex, buffer, releaseFence);
156180
}
157-
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
158181

159182
status_t BufferItemConsumer::releaseBufferSlotLocked(int slotIndex, const sp<GraphicBuffer>& buffer,
160183
const sp<Fence>& releaseFence) {

libs/gui/BufferQueueConsumer.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
#include <inttypes.h>
18-
#include <pwd.h>
19-
#include <sys/types.h>
20-
2117
#define LOG_TAG "BufferQueueConsumer"
2218
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
2319
//#define LOG_NDEBUG 0
@@ -48,6 +44,11 @@
4844

4945
#include <com_android_graphics_libgui_flags.h>
5046

47+
#include <inttypes.h>
48+
#include <pwd.h>
49+
#include <sys/types.h>
50+
#include <optional>
51+
5152
namespace android {
5253

5354
// Macros for include BufferQueueCore information in log messages
@@ -767,11 +768,15 @@ status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
767768
return NO_ERROR;
768769
}
769770

771+
status_t BufferQueueConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
772+
return setMaxAcquiredBufferCount(maxAcquiredBuffers, std::nullopt);
773+
}
774+
770775
status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
771-
int maxAcquiredBuffers) {
776+
int maxAcquiredBuffers, std::optional<OnBufferReleasedCallback> onBuffersReleasedCallback) {
772777
ATRACE_FORMAT("%s(%d)", __func__, maxAcquiredBuffers);
773778

774-
sp<IConsumerListener> listener;
779+
std::optional<OnBufferReleasedCallback> callback;
775780
{ // Autolock scope
776781
std::unique_lock<std::mutex> lock(mCore->mMutex);
777782

@@ -833,13 +838,20 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
833838
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
834839
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
835840
VALIDATE_CONSISTENCY();
836-
if (delta < 0 && mCore->mBufferReleasedCbEnabled) {
837-
listener = mCore->mConsumerListener;
841+
if (delta < 0) {
842+
if (onBuffersReleasedCallback) {
843+
callback = std::move(onBuffersReleasedCallback);
844+
} else if (mCore->mBufferReleasedCbEnabled) {
845+
callback = [listener = mCore->mConsumerListener]() {
846+
listener->onBuffersReleased();
847+
};
848+
}
838849
}
839850
}
851+
840852
// Call back without lock held
841-
if (listener != nullptr) {
842-
listener->onBuffersReleased();
853+
if (callback) {
854+
(*callback)();
843855
}
844856

845857
return NO_ERROR;

libs/gui/ConsumerBase.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,10 @@ void ConsumerBase::onFrameReplaced(const BufferItem &item) {
264264

265265
void ConsumerBase::onBuffersReleased() {
266266
Mutex::Autolock lock(mMutex);
267+
onBuffersReleasedLocked();
268+
}
267269

270+
void ConsumerBase::onBuffersReleasedLocked() {
268271
CB_LOGV("onBuffersReleased");
269272

270273
if (mAbandoned) {
@@ -481,7 +484,8 @@ status_t ConsumerBase::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
481484
CB_LOGE("setMaxAcquiredBufferCount: ConsumerBase is abandoned!");
482485
return NO_INIT;
483486
}
484-
return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
487+
return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers,
488+
{[this]() { onBuffersReleasedLocked(); }});
485489
}
486490

487491
status_t ConsumerBase::setConsumerIsProtected(bool isProtected) {

libs/gui/include/gui/BufferItemConsumer.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ class BufferItemConsumer: public ConsumerBase
9696
status_t acquireBuffer(BufferItem* item, nsecs_t presentWhen,
9797
bool waitForFence = true);
9898

99+
// Transfer ownership of a buffer to the BufferQueue. On NO_ERROR, the buffer
100+
// is considered as if it were acquired. Buffer must not be null.
101+
//
102+
// Returns
103+
// - BAD_VALUE if buffer is null
104+
// - INVALID_OPERATION if too many buffers have already been acquired
105+
status_t attachBuffer(const sp<GraphicBuffer>& buffer);
106+
99107
// Returns an acquired buffer to the queue, allowing it to be reused. Since
100108
// only a fixed number of buffers may be acquired at a time, old buffers
101109
// must be released by calling releaseBuffer to ensure new buffers can be
@@ -105,10 +113,8 @@ class BufferItemConsumer: public ConsumerBase
105113
status_t releaseBuffer(const BufferItem &item,
106114
const sp<Fence>& releaseFence = Fence::NO_FENCE);
107115

108-
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
109116
status_t releaseBuffer(const sp<GraphicBuffer>& buffer,
110117
const sp<Fence>& releaseFence = Fence::NO_FENCE);
111-
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
112118

113119
protected:
114120
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)

libs/gui/include/gui/BufferQueueConsumer.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ class BufferQueueConsumer : public IGraphicBufferConsumer {
122122
// setMaxAcquiredBufferCount sets the maximum number of buffers that can
123123
// be acquired by the consumer at one time (default 1). This call will
124124
// fail if a producer is connected to the BufferQueue.
125-
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
125+
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) override;
126+
virtual status_t setMaxAcquiredBufferCount(
127+
int maxAcquiredBuffers,
128+
std::optional<OnBufferReleasedCallback> onBuffersReleasedCallback) override;
126129

127130
// setConsumerName sets the name used in logging
128131
status_t setConsumerName(const String8& name) override;

libs/gui/include/gui/ConsumerBase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ class ConsumerBase : public virtual RefBase,
191191
#endif
192192
virtual int getSlotForBufferLocked(const sp<GraphicBuffer>& buffer);
193193

194+
virtual void onBuffersReleasedLocked();
195+
194196
virtual status_t detachBufferLocked(int slotIndex);
195197

196198
// freeBufferLocked frees up the given buffer slot. If the slot has been

libs/gui/include/gui/IGraphicBufferConsumer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ class IGraphicBufferConsumer : public RefBase {
243243
// maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS. It also cannot
244244
// cause the maxBufferCount value to be exceeded.
245245
//
246+
// If called with onBuffersReleasedCallback, that call back will be called in lieu of
247+
// IConsumerListener::onBuffersReleased.
248+
//
246249
// Return of a value other than NO_ERROR means an error has occurred:
247250
// * NO_INIT - the BufferQueue has been abandoned
248251
// * BAD_VALUE - one of the below conditions occurred:
@@ -253,6 +256,11 @@ class IGraphicBufferConsumer : public RefBase {
253256
// * INVALID_OPERATION - attempting to call this after a producer connected.
254257
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
255258

259+
using OnBufferReleasedCallback = std::function<void(void)>;
260+
virtual status_t setMaxAcquiredBufferCount(
261+
int maxAcquiredBuffers,
262+
std::optional<OnBufferReleasedCallback> onBuffersReleasedCallback) = 0;
263+
256264
// setConsumerName sets the name used in logging
257265
virtual status_t setConsumerName(const String8& name) = 0;
258266

libs/gui/include/gui/mock/GraphicBufferConsumer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class GraphicBufferConsumer : public IGraphicBufferConsumer {
4747
MOCK_METHOD2(setDefaultBufferSize, status_t(uint32_t, uint32_t));
4848
MOCK_METHOD1(setMaxBufferCount, status_t(int));
4949
MOCK_METHOD1(setMaxAcquiredBufferCount, status_t(int));
50+
MOCK_METHOD2(setMaxAcquiredBufferCount, status_t(int, std::optional<OnBufferReleasedCallback>));
5051
MOCK_METHOD1(setConsumerName, status_t(const String8&));
5152
MOCK_METHOD1(setDefaultBufferFormat, status_t(PixelFormat));
5253
MOCK_METHOD1(setDefaultBufferDataSpace, status_t(android_dataspace));

libs/gui/tests/BufferItemConsumer_test.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <gui/Surface.h>
2525
#include <ui/BufferQueueDefs.h>
2626
#include <ui/GraphicBuffer.h>
27+
#include <utils/Errors.h>
2728

2829
#include <unordered_set>
2930

@@ -235,6 +236,38 @@ TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DeleteBufferItemConsumer) {
235236
ASSERT_EQ(1, GetFreedBufferCount());
236237
}
237238

239+
TEST_F(BufferItemConsumerTest, ResizeAcquireCount) {
240+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers + 1));
241+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers + 2));
242+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers - 1));
243+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers - 2));
244+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers + 1));
245+
EXPECT_EQ(OK, mBIC->setMaxAcquiredBufferCount(kMaxLockedBuffers - 1));
246+
}
247+
248+
TEST_F(BufferItemConsumerTest, AttachBuffer) {
249+
ASSERT_EQ(OK, mBIC->setMaxAcquiredBufferCount(1));
250+
251+
int slot;
252+
DequeueBuffer(&slot);
253+
QueueBuffer(slot);
254+
AcquireBuffer(&slot);
255+
256+
sp<GraphicBuffer> newBuffer1 = sp<GraphicBuffer>::make(kWidth, kHeight, kFormat, kUsage);
257+
sp<GraphicBuffer> newBuffer2 = sp<GraphicBuffer>::make(kWidth, kHeight, kFormat, kUsage);
258+
259+
// For some reason, you can attach an extra buffer?
260+
// b/400973991 to investigate
261+
EXPECT_EQ(OK, mBIC->attachBuffer(newBuffer1));
262+
EXPECT_EQ(INVALID_OPERATION, mBIC->attachBuffer(newBuffer2));
263+
264+
ReleaseBuffer(slot);
265+
266+
EXPECT_EQ(OK, mBIC->attachBuffer(newBuffer2));
267+
EXPECT_EQ(OK, mBIC->releaseBuffer(newBuffer1, Fence::NO_FENCE));
268+
EXPECT_EQ(OK, mBIC->releaseBuffer(newBuffer2, Fence::NO_FENCE));
269+
}
270+
238271
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
239272
// Test that delete BufferItemConsumer triggers onBufferFreed.
240273
TEST_F(BufferItemConsumerTest, DetachBufferWithBuffer) {

0 commit comments

Comments
 (0)