1 /*
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 <gui/test/CallbackUtils.h>
18 #include "LayerTransactionTest.h"
19 
20 using namespace std::chrono_literals;
21 
22 namespace android {
23 
24 using 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
30 class ReleaseBufferCallbackHelper {
31 public:
function(void * callbackContext,ReleaseCallbackId callbackId,const sp<Fence> & releaseFence,uint32_t)32     static void function(void* callbackContext, ReleaseCallbackId callbackId,
33                          const sp<Fence>& releaseFence,
34                          uint32_t /*currentMaxAcquiredBufferCount*/) {
35         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(callbackId, releaseFence);
42         helper->mConditionVariable.notify_all();
43     }
44 
getCallbackData(ReleaseCallbackId * callbackId)45     void getCallbackData(ReleaseCallbackId* callbackId) {
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         *callbackId = callbackData.first;
57     }
58 
verifyNoCallbacks()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(), 0U) << "extra callbacks received";
65         mCallbackDataQueue = {};
66     }
67 
getCallback()68     android::ReleaseBufferCallback getCallback() {
69         return std::bind(function, static_cast<void*>(this) /* callbackContext */,
70                          std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
71     }
72 
73     std::mutex mMutex;
74     std::condition_variable mConditionVariable;
75     std::queue<std::pair<ReleaseCallbackId, sp<Fence>>> mCallbackDataQueue;
76 };
77 
78 class ReleaseBufferCallbackTest : public LayerTransactionTest {
79 public:
createBufferStateLayer()80     virtual sp<SurfaceControl> createBufferStateLayer() {
81         return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
82     }
83 
submitBuffer(const sp<SurfaceControl> & layer,sp<GraphicBuffer> buffer,sp<Fence> fence,CallbackHelper & callback,const ReleaseCallbackId & id,ReleaseBufferCallbackHelper & releaseCallback)84     static void submitBuffer(const sp<SurfaceControl>& layer, sp<GraphicBuffer> buffer,
85                              sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
86                              ReleaseBufferCallbackHelper& releaseCallback) {
87         Transaction t;
88         t.setFrameNumber(layer, id.framenumber);
89         t.setBuffer(layer, buffer, id, releaseCallback.getCallback());
90         t.setAcquireFence(layer, fence);
91         t.addTransactionCompletedCallback(callback.function, callback.getContext());
92         t.apply();
93     }
94 
waitForCallback(CallbackHelper & helper,const ExpectedResult & expectedResult)95     static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult) {
96         CallbackData callbackData;
97         helper.getCallbackData(&callbackData);
98         expectedResult.verifyCallbackData(callbackData);
99     }
100 
waitForReleaseBufferCallback(ReleaseBufferCallbackHelper & releaseCallback,const ReleaseCallbackId & expectedReleaseBufferId)101     static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
102                                              const ReleaseCallbackId& expectedReleaseBufferId) {
103         ReleaseCallbackId actualReleaseBufferId;
104         releaseCallback.getCallbackData(&actualReleaseBufferId);
105         EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId);
106         releaseCallback.verifyNoCallbacks();
107     }
getReleaseBufferCallbackHelper()108     static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
109         static std::vector<ReleaseBufferCallbackHelper*> sCallbacks;
110         sCallbacks.emplace_back(new ReleaseBufferCallbackHelper());
111         return sCallbacks.back();
112     }
113 
getBuffer()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     }
generateFrameNumber()120     static uint64_t generateFrameNumber() {
121         static uint64_t sFrameNumber = 0;
122         return ++sFrameNumber;
123     }
124 };
125 
TEST_F(ReleaseBufferCallbackTest,DISABLED_PresentBuffer)126 TEST_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();
133     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
134     submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
135                  *releaseCallback);
136     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();
153     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
154     submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
155                  *releaseCallback);
156     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));
161     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
162 }
163 
TEST_F(ReleaseBufferCallbackTest,DISABLED_OffScreenLayer)164 TEST_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();
172     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
173     submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, firstBufferCallbackId,
174                  *releaseCallback);
175     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();
198     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
199     submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, secondBufferCallbackId,
200                  *releaseCallback);
201     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));
206     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
207 
208     // If continue to submit buffer we continue to get release callbacks
209     sp<GraphicBuffer> thirdBuffer = getBuffer();
210     ReleaseCallbackId thirdBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
211     submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, thirdBufferCallbackId,
212                  *releaseCallback);
213     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));
218     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
219 }
220 
TEST_F(ReleaseBufferCallbackTest,DISABLED_LayerLifecycle_layerdestroy)221 TEST_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();
228     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
229     submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
230                  *releaseCallback);
231     {
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 
245     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
246 }
247 
248 // Destroying a never presented layer emits a callback.
TEST_F(ReleaseBufferCallbackTest,DISABLED_LayerLifecycle_OffScreenLayerDestroy)249 TEST_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();
262     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
263     submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, firstBufferCallbackId,
264                  *releaseCallback);
265     {
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();
275     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
276     submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, secondBufferCallbackId,
277                  *releaseCallback);
278     {
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(
284                 waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
285     }
286 
287     // Destroying the offscreen layer emits a callback.
288     layer = nullptr;
289     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBufferCallbackId));
290 }
291 
TEST_F(ReleaseBufferCallbackTest,DISABLED_FrameDropping)292 TEST_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();
299     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
300 
301     // Try to present 100ms in the future
302     nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
303 
304     Transaction t;
305     t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback());
306     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();
320     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
321     t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback());
322     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));
333     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
334 }
335 
TEST_F(ReleaseBufferCallbackTest,DISABLED_Merge_Different_Processes)336 TEST_F(ReleaseBufferCallbackTest, DISABLED_Merge_Different_Processes) {
337     sp<TransactionCompletedListener> firstCompletedListener = new TransactionCompletedListener();
338     sp<TransactionCompletedListener> secondCompletedListener = new TransactionCompletedListener();
339 
340     CallbackHelper callback1, callback2;
341 
342     TransactionCompletedListener::setInstance(firstCompletedListener);
343 
344     sp<SurfaceControl> layer = createBufferStateLayer();
345     ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
346 
347     sp<GraphicBuffer> firstBuffer = getBuffer();
348     ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
349 
350     // Send initial buffer for the layer
351     submitBuffer(layer, firstBuffer, Fence::NO_FENCE, callback1, firstBufferCallbackId,
352                  *releaseCallback);
353 
354     ExpectedResult expected;
355     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
356                         ExpectedResult::Buffer::NOT_ACQUIRED);
357     ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
358 
359     // Sent a second buffer to allow the first buffer to get released.
360     sp<GraphicBuffer> secondBuffer = getBuffer();
361     ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
362 
363     Transaction transaction1;
364     transaction1.setFrameNumber(layer, secondBufferCallbackId.framenumber);
365     transaction1.setBuffer(layer, secondBuffer, secondBufferCallbackId,
366                            releaseCallback->getCallback());
367     transaction1.setAcquireFence(layer, Fence::NO_FENCE);
368     transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
369 
370     // Set a different TransactionCompletedListener to mimic a second process
371     TransactionCompletedListener::setInstance(secondCompletedListener);
372 
373     // Make sure the second "process" has a callback set up.
374     Transaction transaction2;
375     transaction2.addTransactionCompletedCallback(callback2.function, callback2.getContext());
376 
377     // This merging order, merge transaction1 first then transaction2, seems to ensure the listener
378     // for transaction2 is ordered first. This makes sure the wrong process is added first to the
379     // layer's vector of listeners. With the bug, only the secondCompletedListener will get the
380     // release callback id, since it's ordered first. Then firstCompletedListener would fail to get
381     // the release callback id and not invoke the release callback.
382     Transaction().merge(std::move(transaction1)).merge(std::move(transaction2)).apply();
383 
384     expected = ExpectedResult();
385     expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
386                         ExpectedResult::Buffer::NOT_ACQUIRED,
387                         ExpectedResult::PreviousBuffer::RELEASED);
388     ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
389     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
390 }
391 
392 } // namespace android
393