xref: /aosp_15_r20/frameworks/native/libs/gui/tests/BufferItemConsumer_test.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BufferItemConsumer_test"
18 //#define LOG_NDEBUG 0
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include <gui/BufferItemConsumer.h>
23 #include <gui/IProducerListener.h>
24 #include <gui/Surface.h>
25 #include <ui/GraphicBuffer.h>
26 
27 namespace android {
28 
29 static constexpr int kWidth = 100;
30 static constexpr int kHeight = 100;
31 static constexpr int kMaxLockedBuffers = 3;
32 static constexpr int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
33 static constexpr int kUsage = GRALLOC_USAGE_SW_READ_RARELY;
34 static constexpr int kFrameSleepUs = 30 * 1000;
35 
36 class BufferItemConsumerTest : public ::testing::Test {
37    protected:
38     struct BufferFreedListener
39         : public BufferItemConsumer::BufferFreedListener {
BufferFreedListenerandroid::BufferItemConsumerTest::BufferFreedListener40         explicit BufferFreedListener(BufferItemConsumerTest* test)
41             : mTest(test) {}
onBufferFreedandroid::BufferItemConsumerTest::BufferFreedListener42         void onBufferFreed(const wp<GraphicBuffer>& /* gBuffer */) override {
43             mTest->HandleBufferFreed();
44         }
45         BufferItemConsumerTest* mTest;
46     };
47 
48     struct TrackingProducerListener : public BnProducerListener {
TrackingProducerListenerandroid::BufferItemConsumerTest::TrackingProducerListener49         TrackingProducerListener(BufferItemConsumerTest* test) : mTest(test) {}
50 
onBufferReleasedandroid::BufferItemConsumerTest::TrackingProducerListener51         virtual void onBufferReleased() override {}
needsReleaseNotifyandroid::BufferItemConsumerTest::TrackingProducerListener52         virtual bool needsReleaseNotify() override { return true; }
onBuffersDiscardedandroid::BufferItemConsumerTest::TrackingProducerListener53         virtual void onBuffersDiscarded(const std::vector<int32_t>&) override {}
onBufferDetachedandroid::BufferItemConsumerTest::TrackingProducerListener54         virtual void onBufferDetached(int slot) override { mTest->HandleBufferDetached(slot); }
55 
56         BufferItemConsumerTest* mTest;
57     };
58 
SetUp()59     void SetUp() override {
60         mBIC = new BufferItemConsumer(kUsage, kMaxLockedBuffers, true);
61         String8 name("BufferItemConsumer_Under_Test");
62         mBIC->setName(name);
63         mBFL = new BufferFreedListener(this);
64         mBIC->setBufferFreedListener(mBFL);
65 
66         sp<IProducerListener> producerListener = new TrackingProducerListener(this);
67         mProducer = mBIC->getSurface()->getIGraphicBufferProducer();
68         IGraphicBufferProducer::QueueBufferOutput bufferOutput;
69         ASSERT_EQ(NO_ERROR,
70                   mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU,
71                                      true, &bufferOutput));
72         ASSERT_EQ(NO_ERROR,
73                   mProducer->setMaxDequeuedBufferCount(kMaxLockedBuffers));
74     }
75 
GetFreedBufferCount()76     int GetFreedBufferCount() {
77         std::lock_guard<std::mutex> lock(mMutex);
78         return mFreedBufferCount;
79     }
80 
HandleBufferFreed()81     void HandleBufferFreed() {
82         std::lock_guard<std::mutex> lock(mMutex);
83         mFreedBufferCount++;
84         ALOGD("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount);
85     }
86 
HandleBufferDetached(int slot)87     void HandleBufferDetached(int slot) {
88         std::lock_guard<std::mutex> lock(mMutex);
89         mDetachedBufferSlots.push_back(slot);
90         ALOGD("HandleBufferDetached, slot=%d mDetachedBufferSlots-count=%zu", slot,
91               mDetachedBufferSlots.size());
92     }
93 
DequeueBuffer(int * outSlot)94     void DequeueBuffer(int* outSlot) {
95         ASSERT_NE(outSlot, nullptr);
96 
97         int slot;
98         sp<Fence> outFence;
99         status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth, kHeight, 0, 0,
100                                                 nullptr, nullptr);
101         ASSERT_GE(ret, 0);
102 
103         ALOGD("dequeueBuffer: slot=%d", slot);
104         if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
105             ret = mProducer->requestBuffer(slot, &mBuffers[slot]);
106             ASSERT_EQ(NO_ERROR, ret);
107         }
108         *outSlot = slot;
109     }
110 
QueueBuffer(int slot)111     void QueueBuffer(int slot) {
112         ALOGD("enqueueBuffer: slot=%d", slot);
113         IGraphicBufferProducer::QueueBufferInput bufferInput(
114             0ULL, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
115             NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
116         IGraphicBufferProducer::QueueBufferOutput bufferOutput;
117         status_t ret = mProducer->queueBuffer(slot, bufferInput, &bufferOutput);
118         ASSERT_EQ(NO_ERROR, ret);
119     }
120 
AcquireBuffer(int * outSlot)121     void AcquireBuffer(int* outSlot) {
122         ASSERT_NE(outSlot, nullptr);
123         BufferItem buffer;
124         status_t ret = mBIC->acquireBuffer(&buffer, 0, false);
125         ASSERT_EQ(NO_ERROR, ret);
126 
127         ALOGD("acquireBuffer: slot=%d", buffer.mSlot);
128         *outSlot = buffer.mSlot;
129     }
130 
ReleaseBuffer(int slot)131     void ReleaseBuffer(int slot) {
132         ALOGD("releaseBuffer: slot=%d", slot);
133         BufferItem buffer;
134         buffer.mSlot = slot;
135         buffer.mGraphicBuffer = mBuffers[slot];
136         status_t ret = mBIC->releaseBuffer(buffer, Fence::NO_FENCE);
137         ASSERT_EQ(NO_ERROR, ret);
138     }
139 
140 
141     std::mutex mMutex;
142     int mFreedBufferCount{0};
143     std::vector<int> mDetachedBufferSlots = {};
144 
145     sp<BufferItemConsumer> mBIC;
146     sp<BufferFreedListener> mBFL;
147     sp<IGraphicBufferProducer> mProducer;
148     sp<IGraphicBufferConsumer> mConsumer;
149     sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
150 };
151 
152 // Test that detaching buffer from consumer side triggers onBufferFreed.
TEST_F(BufferItemConsumerTest,TriggerBufferFreed_DetachBufferFromConsumer)153 TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromConsumer) {
154     int slot;
155     // Producer: generate a placeholder buffer.
156     DequeueBuffer(&slot);
157     QueueBuffer(slot);
158 
159     ASSERT_EQ(0, GetFreedBufferCount());
160     // Consumer: acquire the buffer and then detach it.
161     AcquireBuffer(&slot);
162     status_t ret = mBIC->detachBuffer(slot);
163     ASSERT_EQ(NO_ERROR, ret);
164 
165     // Sleep to give some time for callbacks to happen.
166     usleep(kFrameSleepUs);
167     ASSERT_EQ(1, GetFreedBufferCount());
168 }
169 
170 // Test that detaching buffer from producer side triggers onBufferFreed.
TEST_F(BufferItemConsumerTest,TriggerBufferFreed_DetachBufferFromProducer)171 TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromProducer) {
172     int slot;
173     // Let buffer go through the cycle at least once.
174     DequeueBuffer(&slot);
175     QueueBuffer(slot);
176     AcquireBuffer(&slot);
177     ReleaseBuffer(slot);
178 
179     ASSERT_EQ(0, GetFreedBufferCount());
180 
181     // Producer: generate the buffer again.
182     DequeueBuffer(&slot);
183 
184     // Producer: detach the buffer.
185     status_t ret = mProducer->detachBuffer(slot);
186     ASSERT_EQ(NO_ERROR, ret);
187 
188     // Sleep to give some time for callbacks to happen.
189     usleep(kFrameSleepUs);
190     ASSERT_EQ(1, GetFreedBufferCount());
191 }
192 
193 // Test that abandoning BufferItemConsumer triggers onBufferFreed.
TEST_F(BufferItemConsumerTest,TriggerBufferFreed_AbandonBufferItemConsumer)194 TEST_F(BufferItemConsumerTest, TriggerBufferFreed_AbandonBufferItemConsumer) {
195     int slot;
196     // Let buffer go through the cycle at least once.
197     DequeueBuffer(&slot);
198     QueueBuffer(slot);
199     AcquireBuffer(&slot);
200     ReleaseBuffer(slot);
201 
202     // Abandon the BufferItemConsumer.
203     mBIC->abandon();
204 
205     // Sleep to give some time for callbacks to happen.
206     usleep(kFrameSleepUs);
207     ASSERT_EQ(1, GetFreedBufferCount());
208 }
209 
210 // Test that delete BufferItemConsumer triggers onBufferFreed.
TEST_F(BufferItemConsumerTest,TriggerBufferFreed_DeleteBufferItemConsumer)211 TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DeleteBufferItemConsumer) {
212     int slot;
213     // Let buffer go through the cycle at least once.
214     DequeueBuffer(&slot);
215     QueueBuffer(slot);
216     AcquireBuffer(&slot);
217     ReleaseBuffer(slot);
218 
219     // Delete the BufferItemConsumer.
220     mBIC.clear();
221 
222     // Sleep to give some time for callbacks to happen.
223     usleep(kFrameSleepUs);
224     ASSERT_EQ(1, GetFreedBufferCount());
225 }
226 
227 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
228 // Test that delete BufferItemConsumer triggers onBufferFreed.
TEST_F(BufferItemConsumerTest,DetachBufferWithBuffer)229 TEST_F(BufferItemConsumerTest, DetachBufferWithBuffer) {
230     int slot;
231     // Let buffer go through the cycle at least once.
232     DequeueBuffer(&slot);
233     QueueBuffer(slot);
234     AcquireBuffer(&slot);
235 
236     sp<GraphicBuffer> buffer = mBuffers[slot];
237     EXPECT_EQ(OK, mBIC->detachBuffer(buffer));
238     EXPECT_THAT(mDetachedBufferSlots, testing::ElementsAre(slot));
239 }
240 #endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
241 
242 }  // namespace android
243