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