blob: 579a26ebf449937ca6872da8a7492df00b12995b [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:
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070032 static void function(void* callbackContext, ReleaseCallbackId callbackId,
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);
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070041 helper->mCallbackDataQueue.emplace(callbackId, releaseFence);
Vishnu Nair1506b182021-02-22 14:35:15 -080042 helper->mConditionVariable.notify_all();
43 }
44
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070045 void getCallbackData(ReleaseCallbackId* callbackId) {
Vishnu Nair1506b182021-02-22 14:35:15 -080046 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();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070056 *callbackId = callbackData.first;
Vishnu Nair1506b182021-02-22 14:35:15 -080057 }
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;
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070075 std::queue<std::pair<ReleaseCallbackId, sp<Fence>>> mCallbackDataQueue;
Vishnu Nair1506b182021-02-22 14:35:15 -080076};
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,
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070085 sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
Vishnu Nair1506b182021-02-22 14:35:15 -080086 ReleaseBufferCallbackHelper& releaseCallback) {
87 Transaction t;
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -070088 t.setFrameNumber(layer, id.framenumber);
89 t.setBuffer(layer, buffer, id, releaseCallback.getCallback());
Vishnu Nair1506b182021-02-22 14:35:15 -080090 t.setAcquireFence(layer, fence);
91 t.addTransactionCompletedCallback(callback.function, callback.getContext());
92 t.apply();
93 }
94
95 static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult) {
96 CallbackData callbackData;
97 helper.getCallbackData(&callbackData);
98 expectedResult.verifyCallbackData(callbackData);
99 }
100
101 static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700102 const ReleaseCallbackId& expectedCallbackId) {
103 ReleaseCallbackId actualReleaseBufferId;
Vishnu Nair1506b182021-02-22 14:35:15 -0800104 releaseCallback.getCallbackData(&actualReleaseBufferId);
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700105 EXPECT_EQ(expectedCallbackId, actualReleaseBufferId);
Vishnu Nair1506b182021-02-22 14:35:15 -0800106 releaseCallback.verifyNoCallbacks();
107 }
108 static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
109 static std::vector<ReleaseBufferCallbackHelper*> sCallbacks;
110 sCallbacks.emplace_back(new ReleaseBufferCallbackHelper());
111 return sCallbacks.back();
112 }
113
114 static sp<GraphicBuffer> getBuffer() {
115 return new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
116 BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
117 BufferUsage::COMPOSER_OVERLAY,
118 "test");
119 }
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700120 static uint64_t generateFrameNumber() {
121 static uint64_t sFrameNumber = 0;
122 return ++sFrameNumber;
123 }
Vishnu Nair1506b182021-02-22 14:35:15 -0800124};
125
126TEST_F(ReleaseBufferCallbackTest, DISABLED_PresentBuffer) {
127 sp<SurfaceControl> layer = createBufferStateLayer();
128 CallbackHelper transactionCallback;
129 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
130
131 // If a buffer is being presented, we should not emit a release callback.
132 sp<GraphicBuffer> firstBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700133 ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
134 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
135 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800136 ExpectedResult expected;
137 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
138 ExpectedResult::Buffer::NOT_ACQUIRED);
139 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
140 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
141
142 // if state doesn't change, no release callbacks are expected
143 Transaction t;
144 t.addTransactionCompletedCallback(transactionCallback.function,
145 transactionCallback.getContext());
146 t.apply();
147 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, ExpectedResult()));
148 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
149
150 // If a presented buffer is replaced, we should emit a release callback for the
151 // previously presented buffer.
152 sp<GraphicBuffer> secondBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700153 ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
154 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
155 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800156 expected = ExpectedResult();
157 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
158 ExpectedResult::Buffer::NOT_ACQUIRED,
159 ExpectedResult::PreviousBuffer::RELEASED);
160 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700161 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800162}
163
164TEST_F(ReleaseBufferCallbackTest, DISABLED_OffScreenLayer) {
165 sp<SurfaceControl> layer = createBufferStateLayer();
166
167 CallbackHelper transactionCallback;
168 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
169
170 // If a buffer is being presented, we should not emit a release callback.
171 sp<GraphicBuffer> firstBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700172 ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
173 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
174 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800175 ExpectedResult expected;
176 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
177 ExpectedResult::Buffer::NOT_ACQUIRED);
178 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
179 releaseCallback->verifyNoCallbacks();
180
181 // If a layer is parented offscreen then it should not emit a callback since sf still owns
182 // the buffer and can render it again.
183 Transaction t;
184 t.reparent(layer, nullptr);
185 t.addTransactionCompletedCallback(transactionCallback.function,
186 transactionCallback.getContext());
187 t.apply();
188 expected = ExpectedResult();
189 expected.addSurface(ExpectedResult::Transaction::NOT_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(releaseCallback->verifyNoCallbacks());
194
195 // If a presented buffer is replaced, we should emit a release callback for the
196 // previously presented buffer.
197 sp<GraphicBuffer> secondBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700198 ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
199 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
200 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800201 expected = ExpectedResult();
202 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
203 ExpectedResult::Buffer::NOT_ACQUIRED,
204 ExpectedResult::PreviousBuffer::NOT_RELEASED);
205 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700206 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800207
208 // If continue to submit buffer we continue to get release callbacks
209 sp<GraphicBuffer> thirdBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700210 ReleaseCallbackId thirdBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
211 submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, thirdBufferCallbackId,
212 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800213 expected = ExpectedResult();
214 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
215 ExpectedResult::Buffer::NOT_ACQUIRED,
216 ExpectedResult::PreviousBuffer::NOT_RELEASED);
217 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700218 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800219}
220
221TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_layerdestroy) {
222 sp<SurfaceControl> layer = createBufferStateLayer();
223 CallbackHelper* transactionCallback = new CallbackHelper();
224 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
225
226 // If a buffer is being presented, we should not emit a release callback.
227 sp<GraphicBuffer> firstBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700228 ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
229 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
230 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800231 {
232 ExpectedResult expected;
233 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
234 ExpectedResult::Buffer::NOT_ACQUIRED);
235 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
236 ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
237 }
238
239 // Destroying a currently presenting layer emits a callback.
240 Transaction t;
241 t.reparent(layer, nullptr);
242 t.apply();
243 layer = nullptr;
244
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700245 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800246}
247
248// Destroying a never presented layer emits a callback.
249TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_OffScreenLayerDestroy) {
250 sp<SurfaceControl> layer = createBufferStateLayer();
251
252 // make layer offscreen
253 Transaction t;
254 t.reparent(layer, nullptr);
255 t.apply();
256
257 CallbackHelper* transactionCallback = new CallbackHelper();
258 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
259
260 // Submitting a buffer does not emit a callback.
261 sp<GraphicBuffer> firstBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700262 ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
263 submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
264 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800265 {
266 ExpectedResult expected;
267 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
268 ExpectedResult::Buffer::NOT_ACQUIRED);
269 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
270 ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
271 }
272
273 // Submitting a second buffer will replace the drawing state buffer and emit a callback.
274 sp<GraphicBuffer> secondBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700275 ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
276 submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, secondBufferCallbackId,
277 *releaseCallback);
Vishnu Nair1506b182021-02-22 14:35:15 -0800278 {
279 ExpectedResult expected;
280 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
281 ExpectedResult::Buffer::NOT_ACQUIRED);
282 ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected));
283 ASSERT_NO_FATAL_FAILURE(
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700284 waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800285 }
286
287 // Destroying the offscreen layer emits a callback.
288 layer = nullptr;
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700289 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800290}
291
292TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) {
293 sp<SurfaceControl> layer = createBufferStateLayer();
294 CallbackHelper transactionCallback;
295 ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
296
297 // If a buffer is being presented, we should not emit a release callback.
298 sp<GraphicBuffer> firstBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700299 ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
Vishnu Nair1506b182021-02-22 14:35:15 -0800300
301 // Try to present 100ms in the future
302 nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
303
304 Transaction t;
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700305 t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback());
Vishnu Nair1506b182021-02-22 14:35:15 -0800306 t.setAcquireFence(layer, Fence::NO_FENCE);
307 t.addTransactionCompletedCallback(transactionCallback.function,
308 transactionCallback.getContext());
309 t.setDesiredPresentTime(time);
310 t.apply();
311
312 ExpectedResult expected;
313 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
314 ExpectedResult::Buffer::NOT_ACQUIRED);
315 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
316 EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks());
317
318 // Dropping frames in transaction queue emits a callback
319 sp<GraphicBuffer> secondBuffer = getBuffer();
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700320 ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
321 t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback());
Vishnu Nair1506b182021-02-22 14:35:15 -0800322 t.setAcquireFence(layer, Fence::NO_FENCE);
323 t.addTransactionCompletedCallback(transactionCallback.function,
324 transactionCallback.getContext());
325 t.setDesiredPresentTime(time);
326 t.apply();
327
328 expected = ExpectedResult();
329 expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
330 ExpectedResult::Buffer::NOT_ACQUIRED,
331 ExpectedResult::PreviousBuffer::RELEASED);
332 ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected));
Vishnu Nair4ba0c2e2021-06-24 11:27:17 -0700333 ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
Vishnu Nair1506b182021-02-22 14:35:15 -0800334}
335
336} // namespace android