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 <gtest/gtest.h> 21#include <gui/BufferItemConsumer.h> 22#include <gui/IProducerListener.h> 23#include <gui/Surface.h> 24 25namespace android { 26 27static constexpr int kWidth = 100; 28static constexpr int kHeight = 100; 29static constexpr int kMaxLockedBuffers = 3; 30static constexpr int kFormat = HAL_PIXEL_FORMAT_RGBA_8888; 31static constexpr int kFrameSleepUs = 30 * 1000; 32 33class BufferItemConsumerTest : public ::testing::Test { 34 protected: 35 struct BufferFreedListener 36 : public BufferItemConsumer::BufferFreedListener { 37 explicit BufferFreedListener(BufferItemConsumerTest* test) 38 : mTest(test) {} 39 void onBufferFreed(const wp<GraphicBuffer>& /* gBuffer */) override { 40 mTest->HandleBufferFreed(); 41 } 42 BufferItemConsumerTest* mTest; 43 }; 44 45 void SetUp() override { 46 BufferQueue::createBufferQueue(&mProducer, &mConsumer); 47 mBIC = 48 new BufferItemConsumer(mConsumer, kFormat, kMaxLockedBuffers, true); 49 String8 name("BufferItemConsumer_Under_Test"); 50 mBIC->setName(name); 51 mBFL = new BufferFreedListener(this); 52 mBIC->setBufferFreedListener(mBFL); 53 54 sp<IProducerListener> producerListener = new DummyProducerListener(); 55 IGraphicBufferProducer::QueueBufferOutput bufferOutput; 56 ASSERT_EQ(NO_ERROR, 57 mProducer->connect(producerListener, NATIVE_WINDOW_API_CPU, 58 true, &bufferOutput)); 59 ASSERT_EQ(NO_ERROR, 60 mProducer->setMaxDequeuedBufferCount(kMaxLockedBuffers)); 61 } 62 63 int GetFreedBufferCount() { 64 std::lock_guard<std::mutex> lock(mMutex); 65 return mFreedBufferCount; 66 } 67 68 void HandleBufferFreed() { 69 std::lock_guard<std::mutex> lock(mMutex); 70 mFreedBufferCount++; 71 ALOGV("HandleBufferFreed, mFreedBufferCount=%d", mFreedBufferCount); 72 } 73 74 void DequeueBuffer(int* outSlot) { 75 ASSERT_NE(outSlot, nullptr); 76 77 int slot; 78 sp<Fence> outFence; 79 status_t ret = mProducer->dequeueBuffer(&slot, &outFence, kWidth, kHeight, 0, 0, 80 nullptr, nullptr); 81 ASSERT_GE(ret, 0); 82 83 ALOGV("dequeueBuffer: slot=%d", slot); 84 if (ret & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { 85 ret = mProducer->requestBuffer(slot, &mBuffers[slot]); 86 ASSERT_EQ(NO_ERROR, ret); 87 } 88 *outSlot = slot; 89 } 90 91 void QueueBuffer(int slot) { 92 ALOGV("enqueueBuffer: slot=%d", slot); 93 IGraphicBufferProducer::QueueBufferInput bufferInput( 94 0ULL, true, HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT, 95 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); 96 IGraphicBufferProducer::QueueBufferOutput bufferOutput; 97 status_t ret = mProducer->queueBuffer(slot, bufferInput, &bufferOutput); 98 ASSERT_EQ(NO_ERROR, ret); 99 } 100 101 void AcquireBuffer(int* outSlot) { 102 ASSERT_NE(outSlot, nullptr); 103 BufferItem buffer; 104 status_t ret = mBIC->acquireBuffer(&buffer, 0, false); 105 ASSERT_EQ(NO_ERROR, ret); 106 107 ALOGV("acquireBuffer: slot=%d", buffer.mSlot); 108 *outSlot = buffer.mSlot; 109 } 110 111 void ReleaseBuffer(int slot) { 112 ALOGV("releaseBuffer: slot=%d", slot); 113 BufferItem buffer; 114 buffer.mSlot = slot; 115 buffer.mGraphicBuffer = mBuffers[slot]; 116 status_t ret = mBIC->releaseBuffer(buffer, Fence::NO_FENCE); 117 ASSERT_EQ(NO_ERROR, ret); 118 } 119 120 121 std::mutex mMutex; 122 int mFreedBufferCount{0}; 123 124 sp<BufferItemConsumer> mBIC; 125 sp<BufferFreedListener> mBFL; 126 sp<IGraphicBufferProducer> mProducer; 127 sp<IGraphicBufferConsumer> mConsumer; 128 sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; 129}; 130 131// Test that detaching buffer from consumer side triggers onBufferFreed. 132TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromConsumer) { 133 int slot; 134 // Producer: generate a dummy buffer. 135 DequeueBuffer(&slot); 136 QueueBuffer(slot); 137 138 ASSERT_EQ(0, GetFreedBufferCount()); 139 // Consumer: acquire the buffer and then detach it. 140 AcquireBuffer(&slot); 141 status_t ret = mBIC->detachBuffer(slot); 142 ASSERT_EQ(NO_ERROR, ret); 143 144 // Sleep to give some time for callbacks to happen. 145 usleep(kFrameSleepUs); 146 ASSERT_EQ(1, GetFreedBufferCount()); 147} 148 149// Test that detaching buffer from producer side triggers onBufferFreed. 150TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DetachBufferFromProducer) { 151 int slot; 152 // Let buffer go through the cycle at least once. 153 DequeueBuffer(&slot); 154 QueueBuffer(slot); 155 AcquireBuffer(&slot); 156 ReleaseBuffer(slot); 157 158 ASSERT_EQ(0, GetFreedBufferCount()); 159 160 // Producer: generate the buffer again. 161 DequeueBuffer(&slot); 162 163 // Producer: detach the buffer. 164 status_t ret = mProducer->detachBuffer(slot); 165 ASSERT_EQ(NO_ERROR, ret); 166 167 // Sleep to give some time for callbacks to happen. 168 usleep(kFrameSleepUs); 169 ASSERT_EQ(1, GetFreedBufferCount()); 170} 171 172// Test that abandoning BufferItemConsumer triggers onBufferFreed. 173TEST_F(BufferItemConsumerTest, TriggerBufferFreed_AbandonBufferItemConsumer) { 174 int slot; 175 // Let buffer go through the cycle at least once. 176 DequeueBuffer(&slot); 177 QueueBuffer(slot); 178 AcquireBuffer(&slot); 179 ReleaseBuffer(slot); 180 181 // Abandon the BufferItemConsumer. 182 mBIC->abandon(); 183 184 // Sleep to give some time for callbacks to happen. 185 usleep(kFrameSleepUs); 186 ASSERT_EQ(1, GetFreedBufferCount()); 187} 188 189// Test that delete BufferItemConsumer triggers onBufferFreed. 190TEST_F(BufferItemConsumerTest, TriggerBufferFreed_DeleteBufferItemConsumer) { 191 int slot; 192 // Let buffer go through the cycle at least once. 193 DequeueBuffer(&slot); 194 QueueBuffer(slot); 195 AcquireBuffer(&slot); 196 ReleaseBuffer(slot); 197 198 // Delete the BufferItemConsumer. 199 mBIC.clear(); 200 201 // Sleep to give some time for callbacks to happen. 202 usleep(kFrameSleepUs); 203 ASSERT_EQ(1, GetFreedBufferCount()); 204} 205 206} // namespace android 207