blob: fb7d41c81e42c26e0e9df94e4bb4209157d384a0 [file] [log] [blame]
Vishnu Nair1506b182021-02-22 14:35:15 -08001/*
2 * Copyright (C) 2021 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#include "LayerTransactionTest.h"
18#include "utils/CallbackUtils.h"
19
20using namespace std::chrono_literals;
21
22namespace android {
23
24using android::hardware::graphics::common::V1_1::BufferUsage;
25
26::testing::Environment* const binderEnv =
27 ::testing::AddGlobalTestEnvironment(new BinderEnvironment());
28
29// b/181132765 - disabled until cuttlefish failures are investigated
30class ReleaseBufferCallbackHelper {
31public:
32 static void function(void* callbackContext, uint64_t graphicsBufferId,
33 const sp<Fence>& releaseFence) {
34 if (!callbackContext) {
35 FAIL() << "failed to get callback context";
36 }
37 ReleaseBufferCallbackHelper* helper =
38 static_cast<ReleaseBufferCallbackHelper*>(callbackContext);
39 std::lock_guard lock(helper->mMutex);
40 helper->mCallbackDataQueue.emplace(graphicsBufferId, releaseFence);
41 helper->mConditionVariable.notify_all();
42 }
43
44 void getCallbackData(uint64_t* bufferId) {
45 std::unique_lock lock(mMutex);
46 if (mCallbackDataQueue.empty()) {
47 if (!mConditionVariable.wait_for(lock, std::chrono::seconds(3),
48 [&] { return !mCallbackDataQueue.empty(); })) {
49 FAIL() << "failed to get releaseBuffer callback";
50 }
51 }
52
53 auto callbackData = mCallbackDataQueue.front();
54 mCallbackDataQueue.pop();
55 *bufferId = callbackData.first;
56 }
57
58 void verifyNoCallbacks() {
59 // Wait to see if there are extra callbacks
60 std::this_thread::sleep_for(300ms);
61
62 std::lock_guard lock(mMutex);
63 EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received";
64 mCallbackDataQueue = {};
65 }
66
67 android::ReleaseBufferCallback getCallback() {
68 return std::bind(function, static_cast<void*>(this) /* callbackContext */,
69 std::placeholders::_1, std::placeholders::_2);
70 }
71
72 std::mutex mMutex;
73 std::condition_variable mConditionVariable;
74 std::queue<std::pair<uint64_t, sp<Fence>>> mCallbackDataQueue;
75};
76
77class ReleaseBufferCallbackTest : public LayerTransactionTest {
78public:
79 virtual sp<SurfaceControl> createBufferStateLayer() {
80 return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
81 }
82
83 static void submitBuffer(const sp<SurfaceControl>& layer, sp<GraphicBuffer> buffer,
84 sp<Fence> fence, CallbackHelper& callback,
85 ReleaseBufferCallbackHelper& releaseCallback) {
86 Transaction t;
87 t.setBuffer(layer, buffer, releaseCallback.getCallback());
88 t.setAcquireFence(layer, fence);
89 t.addTransactionCompletedCallback(callback.function, callback.getContext());
90 t.apply();
91 }
92
93 static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult) {
94 CallbackData callbackData;
95 helper.getCallbackData(&callbackData);
96 expectedResult.verifyCallbackData(callbackData);
97 }
98
99 static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
100 uint64_t expectedReleaseBufferId) {
101 uint64_t actualReleaseBufferId;
102 releaseCallback.getCallbackData(&actualReleaseBufferId);
103 EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId);
104 releaseCallback.verifyNoCallbacks();
105 }
106 static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
107 static std::vector<ReleaseBufferCallbackHelper*> sCallbacks;
108 sCallbacks.emplace_back(new ReleaseBufferCallbackHelper());
109 return sCallbacks.back();
110 }
111
112 static sp<GraphicBuffer> getBuffer() {
113 return new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
114 BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
115 BufferUsage::COMPOSER_OVERLAY,
116 "test");
117 }
118};
119
120TEST_F(ReleaseBufferCallbackTest, DISABLED_PresentBuffer) {
121 sp<SurfaceControl> layer = createBufferStateLayer();
122 CallbackHelper transactionCallback;
123 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
124
125 // If a buffer is being presented, we should not emit a release callback.
126 sp<GraphicBuffer> firstBuffer = getBuffer();
127 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
128 ExpectedResult expected;
129 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
130 ExpectedResult::Buffer::NOT_ACQUIRED);
131 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
132 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
133
134 // if state doesn't change, no release callbacks are expected
135 Transaction t;
136 t.addTransactionCompletedCallback(transactionCallback.function,
137 transactionCallback.getContext());
138 t.apply();
139 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, ExpectedResult()));
140 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
141
142 // If a presented buffer is replaced, we should emit a release callback for the
143 // previously presented buffer.
144 sp<GraphicBuffer> secondBuffer = getBuffer();
145 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
146 expected = ExpectedResult();
147 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
148 ExpectedResult::Buffer::NOT_ACQUIRED,
149 ExpectedResult::PreviousBuffer::RELEASED);
150 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
151 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
152}
153
154TEST_F(ReleaseBufferCallbackTest, DISABLED_OffScreenLayer) {
155 sp<SurfaceControl> layer = createBufferStateLayer();
156
157 CallbackHelper transactionCallback;
158 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
159
160 // If a buffer is being presented, we should not emit a release callback.
161 sp<GraphicBuffer> firstBuffer = getBuffer();
162 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
163 ExpectedResult expected;
164 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
165 ExpectedResult::Buffer::NOT_ACQUIRED);
166 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
167 releaseCallback->verifyNoCallbacks();
168
169 // If a layer is parented offscreen then it should not emit a callback since sf still owns
170 // the buffer and can render it again.
171 Transaction t;
172 t.reparent(layer, nullptr);
173 t.addTransactionCompletedCallback(transactionCallback.function,
174 transactionCallback.getContext());
175 t.apply();
176 expected = ExpectedResult();
177 expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
178 ExpectedResult::Buffer::NOT_ACQUIRED,
179 ExpectedResult::PreviousBuffer::NOT_RELEASED);
180 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
181 ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
182
183 // If a presented buffer is replaced, we should emit a release callback for the
184 // previously presented buffer.
185 sp<GraphicBuffer> secondBuffer = getBuffer();
186 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
187 expected = ExpectedResult();
188 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
189 ExpectedResult::Buffer::NOT_ACQUIRED,
190 ExpectedResult::PreviousBuffer::NOT_RELEASED);
191 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
192 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
193
194 // If continue to submit buffer we continue to get release callbacks
195 sp<GraphicBuffer> thirdBuffer = getBuffer();
196 submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback);
197 expected = ExpectedResult();
198 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
199 ExpectedResult::Buffer::NOT_ACQUIRED,
200 ExpectedResult::PreviousBuffer::NOT_RELEASED);
201 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
202 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId()));
203}
204
205TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_layerdestroy) {
206 sp<SurfaceControl> layer = createBufferStateLayer();
207 CallbackHelper* transactionCallback = new CallbackHelper();
208 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
209
210 // If a buffer is being presented, we should not emit a release callback.
211 sp<GraphicBuffer> firstBuffer = getBuffer();
212 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
213 {
214 ExpectedResult expected;
215 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
216 ExpectedResult::Buffer::NOT_ACQUIRED);
217 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
218 ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
219 }
220
221 // Destroying a currently presenting layer emits a callback.
222 Transaction t;
223 t.reparent(layer, nullptr);
224 t.apply();
225 layer = nullptr;
226
227 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
228}
229
230// Destroying a never presented layer emits a callback.
231TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_OffScreenLayerDestroy) {
232 sp<SurfaceControl> layer = createBufferStateLayer();
233
234 // make layer offscreen
235 Transaction t;
236 t.reparent(layer, nullptr);
237 t.apply();
238
239 CallbackHelper* transactionCallback = new CallbackHelper();
240 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
241
242 // Submitting a buffer does not emit a callback.
243 sp<GraphicBuffer> firstBuffer = getBuffer();
244 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
245 {
246 ExpectedResult expected;
247 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
248 ExpectedResult::Buffer::NOT_ACQUIRED);
249 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
250 ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
251 }
252
253 // Submitting a second buffer will replace the drawing state buffer and emit a callback.
254 sp<GraphicBuffer> secondBuffer = getBuffer();
255 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback);
256 {
257 ExpectedResult expected;
258 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
259 ExpectedResult::Buffer::NOT_ACQUIRED);
260 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
261 ASSERT_NO_FATAL_FAILURE(
262 waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
263 }
264
265 // Destroying the offscreen layer emits a callback.
266 layer = nullptr;
267 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId()));
268}
269
270TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) {
271 sp<SurfaceControl> layer = createBufferStateLayer();
272 CallbackHelper transactionCallback;
273 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
274
275 // If a buffer is being presented, we should not emit a release callback.
276 sp<GraphicBuffer> firstBuffer = getBuffer();
277
278 // Try to present 100ms in the future
279 nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
280
281 Transaction t;
282 t.setBuffer(layer, firstBuffer, releaseCallback->getCallback());
283 t.setAcquireFence(layer, Fence::NO_FENCE);
284 t.addTransactionCompletedCallback(transactionCallback.function,
285 transactionCallback.getContext());
286 t.setDesiredPresentTime(time);
287 t.apply();
288
289 ExpectedResult expected;
290 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
291 ExpectedResult::Buffer::NOT_ACQUIRED);
292 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
293 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
294
295 // Dropping frames in transaction queue emits a callback
296 sp<GraphicBuffer> secondBuffer = getBuffer();
297 t.setBuffer(layer, secondBuffer, releaseCallback->getCallback());
298 t.setAcquireFence(layer, Fence::NO_FENCE);
299 t.addTransactionCompletedCallback(transactionCallback.function,
300 transactionCallback.getContext());
301 t.setDesiredPresentTime(time);
302 t.apply();
303
304 expected = ExpectedResult();
305 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
306 ExpectedResult::Buffer::NOT_ACQUIRED,
307 ExpectedResult::PreviousBuffer::RELEASED);
308 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
309 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId()));
310}
311
312} // namespace android