1 /*
2 * Copyright 2019 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 #undef LOG_TAG
18 #define LOG_TAG "TransactionApplicationTest"
19
20 #include <common/test/FlagUtils.h>
21 #include <compositionengine/Display.h>
22 #include <compositionengine/mock/DisplaySurface.h>
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include <gui/LayerState.h>
26 #include <gui/SurfaceComposerClient.h>
27 #include <gui/fake/BufferData.h>
28 #include <log/log.h>
29 #include <ui/MockFence.h>
30 #include <utils/String8.h>
31 #include <vector>
32 #include <binder/Binder.h>
33
34 #include "FrontEnd/TransactionHandler.h"
35 #include "TestableSurfaceFlinger.h"
36 #include "TransactionState.h"
37
38 #include <com_android_graphics_surfaceflinger_flags.h>
39
40 namespace android {
41
42 using namespace com::android::graphics::surfaceflinger;
43 using testing::_;
44 using testing::Return;
45
46 using frontend::TransactionHandler;
47
48 constexpr nsecs_t TRANSACTION_TIMEOUT = s2ns(5);
49 class TransactionApplicationTest : public testing::Test {
50 public:
TransactionApplicationTest()51 TransactionApplicationTest() {
52 const ::testing::TestInfo* const test_info =
53 ::testing::UnitTest::GetInstance()->current_test_info();
54 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
55
56 mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
57 mFlinger.setupMockScheduler();
58 mFlinger.flinger()->addTransactionReadyFilters();
59 }
60
~TransactionApplicationTest()61 ~TransactionApplicationTest() {
62 const ::testing::TestInfo* const test_info =
63 ::testing::UnitTest::GetInstance()->current_test_info();
64 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
65 }
66
67 TestableSurfaceFlinger mFlinger;
68
69 struct TransactionInfo {
70 Vector<ComposerState> states;
71 Vector<DisplayState> displays;
72 uint32_t flags = 0;
73 sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
74 InputWindowCommands inputWindowCommands;
75 int64_t desiredPresentTime = 0;
76 bool isAutoTimestamp = true;
77 FrameTimelineInfo frameTimelineInfo;
78 std::vector<client_cache_t> uncacheBuffers;
79 uint64_t id = static_cast<uint64_t>(-1);
80 std::vector<uint64_t> mergedTransactionIds;
81 static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
82 };
83
checkEqual(TransactionInfo info,TransactionState state)84 void checkEqual(TransactionInfo info, TransactionState state) {
85 EXPECT_EQ(0u, info.states.size());
86 EXPECT_EQ(0u, state.states.size());
87
88 EXPECT_EQ(0u, info.displays.size());
89 EXPECT_EQ(0u, state.displays.size());
90 EXPECT_EQ(info.flags, state.flags);
91 EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
92 }
93
setupSingle(TransactionInfo & transaction,uint32_t flags,int64_t desiredPresentTime,bool isAutoTimestamp,const FrameTimelineInfo & frameTimelineInfo)94 void setupSingle(TransactionInfo& transaction, uint32_t flags, int64_t desiredPresentTime,
95 bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo) {
96 mTransactionNumber++;
97 transaction.flags |= flags;
98 transaction.desiredPresentTime = desiredPresentTime;
99 transaction.isAutoTimestamp = isAutoTimestamp;
100 transaction.frameTimelineInfo = frameTimelineInfo;
101 }
102
NotPlacedOnTransactionQueue(uint32_t flags)103 void NotPlacedOnTransactionQueue(uint32_t flags) {
104 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
105 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
106 TransactionInfo transaction;
107 setupSingle(transaction, flags,
108 /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
109 FrameTimelineInfo{});
110 nsecs_t applicationTime = systemTime();
111 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
112 transaction.displays, transaction.flags,
113 transaction.applyToken, transaction.inputWindowCommands,
114 transaction.desiredPresentTime, transaction.isAutoTimestamp,
115 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
116 transaction.id, transaction.mergedTransactionIds);
117
118 // If transaction is synchronous, SF applyTransactionState should time out (5s) wating for
119 // SF to commit the transaction. If this is animation, it should not time out waiting.
120 nsecs_t returnedTime = systemTime();
121 EXPECT_LE(returnedTime, applicationTime + TRANSACTION_TIMEOUT);
122 // Each transaction should have been placed on the transaction queue
123 auto& transactionQueue = mFlinger.getTransactionQueue();
124 EXPECT_FALSE(transactionQueue.isEmpty());
125 }
126
PlaceOnTransactionQueue(uint32_t flags)127 void PlaceOnTransactionQueue(uint32_t flags) {
128 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
129 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
130
131 // first check will see desired present time has not passed,
132 // but afterwards it will look like the desired present time has passed
133 nsecs_t time = systemTime();
134 TransactionInfo transaction;
135 setupSingle(transaction, flags, /*desiredPresentTime*/ time + s2ns(1), false,
136 FrameTimelineInfo{});
137 nsecs_t applicationSentTime = systemTime();
138 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
139 transaction.displays, transaction.flags,
140 transaction.applyToken, transaction.inputWindowCommands,
141 transaction.desiredPresentTime, transaction.isAutoTimestamp,
142 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
143 transaction.id, transaction.mergedTransactionIds);
144
145 nsecs_t returnedTime = systemTime();
146 EXPECT_LE(returnedTime, applicationSentTime + TRANSACTION_TIMEOUT);
147 // This transaction should have been placed on the transaction queue
148 auto& transactionQueue = mFlinger.getTransactionQueue();
149 EXPECT_FALSE(transactionQueue.isEmpty());
150 }
151
BlockedByPriorTransaction(uint32_t flags)152 void BlockedByPriorTransaction(uint32_t flags) {
153 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
154 nsecs_t time = systemTime();
155 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
156
157 // transaction that should go on the pending thread
158 TransactionInfo transactionA;
159 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ time + s2ns(1), false,
160 FrameTimelineInfo{});
161
162 // transaction that would not have gone on the pending thread if not
163 // blocked
164 TransactionInfo transactionB;
165 setupSingle(transactionB, flags, /*desiredPresentTime*/ systemTime(),
166 /*isAutoTimestamp*/ true, FrameTimelineInfo{});
167
168 nsecs_t applicationSentTime = systemTime();
169 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
170 transactionA.displays, transactionA.flags,
171 transactionA.applyToken, transactionA.inputWindowCommands,
172 transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
173 transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
174 transactionA.id, transactionA.mergedTransactionIds);
175
176 // This thread should not have been blocked by the above transaction
177 // (5s is the timeout period that applyTransactionState waits for SF to
178 // commit the transaction)
179 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
180 // transaction that would goes to pending transaciton queue.
181 mFlinger.flushTransactionQueues();
182
183 applicationSentTime = systemTime();
184 mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
185 transactionB.displays, transactionB.flags,
186 transactionB.applyToken, transactionB.inputWindowCommands,
187 transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
188 transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
189 transactionB.id, transactionB.mergedTransactionIds);
190
191 // this thread should have been blocked by the above transaction
192 // if this is an animation, this thread should be blocked for 5s
193 // in setTransactionState waiting for transactionA to flush. Otherwise,
194 // the transaction should be placed on the pending queue
195 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
196
197 // transaction that would goes to pending transaciton queue.
198 mFlinger.flushTransactionQueues();
199
200 // check that the transaction was applied.
201 auto transactionQueue = mFlinger.getPendingTransactionQueue();
202 EXPECT_EQ(0u, transactionQueue.size());
203 }
204
modulateVsync()205 void modulateVsync() {
206 static_cast<void>(
207 mFlinger.mutableScheduler().vsyncModulator().onRefreshRateChangeInitiated());
208 }
209
210 bool mHasListenerCallbacks = false;
211 std::vector<ListenerCallbacks> mCallbacks;
212 int mTransactionNumber = 0;
213 };
214
TEST_F(TransactionApplicationTest,AddToPendingQueue)215 TEST_F(TransactionApplicationTest, AddToPendingQueue) {
216 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
217 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
218
219 TransactionInfo transactionA; // transaction to go on pending queue
220 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
221 FrameTimelineInfo{});
222 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
223 transactionA.displays, transactionA.flags, transactionA.applyToken,
224 transactionA.inputWindowCommands, transactionA.desiredPresentTime,
225 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
226 mHasListenerCallbacks, mCallbacks, transactionA.id,
227 transactionA.mergedTransactionIds);
228
229 auto& transactionQueue = mFlinger.getTransactionQueue();
230 ASSERT_FALSE(transactionQueue.isEmpty());
231
232 auto transactionState = transactionQueue.pop().value();
233 checkEqual(transactionA, transactionState);
234 }
235
TEST_F(TransactionApplicationTest,Flush_RemovesFromQueue)236 TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
237 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
238 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
239
240 TransactionInfo transactionA; // transaction to go on pending queue
241 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
242 FrameTimelineInfo{});
243 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
244 transactionA.displays, transactionA.flags, transactionA.applyToken,
245 transactionA.inputWindowCommands, transactionA.desiredPresentTime,
246 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
247 mHasListenerCallbacks, mCallbacks, transactionA.id,
248 transactionA.mergedTransactionIds);
249
250 auto& transactionQueue = mFlinger.getTransactionQueue();
251 ASSERT_FALSE(transactionQueue.isEmpty());
252
253 // because flushing uses the cached expected present time, we send an empty
254 // transaction here (sending a null applyToken to fake it as from a
255 // different process) to re-query and reset the cached expected present time
256 TransactionInfo empty;
257 empty.applyToken = sp<IBinder>();
258 mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
259 empty.applyToken, empty.inputWindowCommands,
260 empty.desiredPresentTime, empty.isAutoTimestamp,
261 empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id,
262 empty.mergedTransactionIds);
263
264 // flush transaction queue should flush as desiredPresentTime has
265 // passed
266 mFlinger.flushTransactionQueues();
267
268 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
269 }
270
TEST_F(TransactionApplicationTest,NotPlacedOnTransactionQueue_SyncInputWindows)271 TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) {
272 NotPlacedOnTransactionQueue(/*flags*/ 0);
273 }
274
TEST_F(TransactionApplicationTest,PlaceOnTransactionQueue_SyncInputWindows)275 TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) {
276 PlaceOnTransactionQueue(/*flags*/ 0);
277 }
278
TEST_F(TransactionApplicationTest,FromHandle)279 TEST_F(TransactionApplicationTest, FromHandle) {
280 sp<IBinder> badHandle;
281 auto ret = mFlinger.fromHandle(badHandle);
282 EXPECT_EQ(nullptr, ret.get());
283 }
284
285 class FakeExternalTexture : public renderengine::ExternalTexture {
286 const sp<GraphicBuffer> mEmptyBuffer = nullptr;
287 uint32_t mWidth;
288 uint32_t mHeight;
289 uint64_t mId;
290 PixelFormat mPixelFormat;
291 uint64_t mUsage;
292
293 public:
FakeExternalTexture(BufferData & bufferData)294 FakeExternalTexture(BufferData& bufferData)
295 : mWidth(bufferData.getWidth()),
296 mHeight(bufferData.getHeight()),
297 mId(bufferData.getId()),
298 mPixelFormat(bufferData.getPixelFormat()),
299 mUsage(bufferData.getUsage()) {}
getBuffer() const300 const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
hasSameBuffer(const renderengine::ExternalTexture & other) const301 bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
302 return getId() == other.getId();
303 }
getWidth() const304 uint32_t getWidth() const override { return mWidth; }
getHeight() const305 uint32_t getHeight() const override { return mHeight; }
getId() const306 uint64_t getId() const override { return mId; }
getPixelFormat() const307 PixelFormat getPixelFormat() const override { return mPixelFormat; }
getUsage() const308 uint64_t getUsage() const override { return mUsage; }
remapBuffer()309 void remapBuffer() override {}
310 ~FakeExternalTexture() = default;
311 };
312
TEST_F(TransactionApplicationTest,ApplyTokensUseDifferentQueues)313 TEST_F(TransactionApplicationTest, ApplyTokensUseDifferentQueues) {
314 auto applyToken1 = sp<BBinder>::make();
315 auto applyToken2 = sp<BBinder>::make();
316
317 // Transaction 1 has a buffer with an unfired fence. It should not be ready to be applied.
318 TransactionState transaction1;
319 transaction1.applyToken = applyToken1;
320 transaction1.id = 42069;
321 transaction1.states.emplace_back();
322 transaction1.states[0].state.what |= layer_state_t::eBufferChanged;
323 transaction1.states[0].state.bufferData =
324 std::make_shared<fake::BufferData>(/* bufferId */ 1, /* width */ 1, /* height */ 1,
325 /* pixelFormat */ 0, /* outUsage */ 0);
326 transaction1.states[0].externalTexture =
327 std::make_shared<FakeExternalTexture>(*transaction1.states[0].state.bufferData);
328 transaction1.states[0].state.surface =
329 sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
330 ->getHandle();
331 auto fence = sp<mock::MockFence>::make();
332 EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(Fence::Status::Unsignaled));
333 transaction1.states[0].state.bufferData->acquireFence = std::move(fence);
334 transaction1.states[0].state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
335 transaction1.isAutoTimestamp = true;
336
337 // Transaction 2 should be ready to be applied.
338 TransactionState transaction2;
339 transaction2.applyToken = applyToken2;
340 transaction2.id = 2;
341 transaction2.isAutoTimestamp = true;
342
343 mFlinger.setTransactionStateInternal(transaction1);
344 mFlinger.setTransactionStateInternal(transaction2);
345 mFlinger.flushTransactionQueues();
346 auto transactionQueues = mFlinger.getPendingTransactionQueue();
347
348 // Transaction 1 is still in its queue.
349 EXPECT_EQ(transactionQueues[applyToken1].size(), 1u);
350 // Transaction 2 has been dequeued.
351 EXPECT_EQ(transactionQueues[applyToken2].size(), 0u);
352 }
353
354 class LatchUnsignaledTest : public TransactionApplicationTest {
355 public:
TearDown()356 void TearDown() override {
357 // Clear all transaction queues to release all transactions we sent
358 // in the tests. Otherwise, gmock complains about memory leaks.
359 while (!mFlinger.getTransactionQueue().isEmpty()) {
360 mFlinger.getTransactionQueue().pop();
361 }
362 mFlinger.getPendingTransactionQueue().clear();
363 mFlinger.commitTransactionsLocked(eTransactionMask);
364 mFlinger.mutableCurrentState().layersSortedByZ.clear();
365 mFlinger.mutableDrawingState().layersSortedByZ.clear();
366 }
367
fence(Fence::Status status)368 static sp<Fence> fence(Fence::Status status) {
369 const auto fence = sp<mock::MockFence>::make();
370 EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(status));
371 return fence;
372 }
373
createComposerState(int layerId,sp<Fence> fence,uint64_t what,std::optional<sp<IBinder>> layerHandle=std::nullopt)374 ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what,
375 std::optional<sp<IBinder>> layerHandle = std::nullopt) {
376 ComposerState state;
377 state.state.bufferData =
378 std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
379 /* height */ 2, /* pixelFormat */ 0,
380 /* outUsage */ 0);
381 state.state.bufferData->acquireFence = std::move(fence);
382 state.state.layerId = layerId;
383 state.state.surface = layerHandle.value_or(
384 sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
385 ->getHandle());
386 state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
387
388 state.state.what = what;
389 if (what & layer_state_t::eCropChanged) {
390 state.state.crop = Rect(1, 2, 3, 4);
391 }
392 if (what & layer_state_t::eFlagsChanged) {
393 state.state.flags = layer_state_t::eEnableBackpressure;
394 state.state.mask = layer_state_t::eEnableBackpressure;
395 }
396
397 return state;
398 }
399
createTransactionInfo(const sp<IBinder> & applyToken,const std::vector<ComposerState> & states)400 TransactionInfo createTransactionInfo(const sp<IBinder>& applyToken,
401 const std::vector<ComposerState>& states) {
402 TransactionInfo transaction;
403 const uint32_t kFlags = 0;
404 const nsecs_t kDesiredPresentTime = systemTime();
405 const bool kIsAutoTimestamp = true;
406 const auto kFrameTimelineInfo = FrameTimelineInfo{};
407
408 setupSingle(transaction, kFlags, kDesiredPresentTime, kIsAutoTimestamp, kFrameTimelineInfo);
409 transaction.applyToken = applyToken;
410 for (const auto& state : states) {
411 transaction.states.push_back(state);
412 }
413
414 return transaction;
415 }
416
setTransactionStates(const std::vector<TransactionInfo> & transactions,size_t expectedTransactionsPending)417 void setTransactionStates(const std::vector<TransactionInfo>& transactions,
418 size_t expectedTransactionsPending) {
419 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
420 EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
421
422 for (auto transaction : transactions) {
423 std::vector<ResolvedComposerState> resolvedStates;
424 resolvedStates.reserve(transaction.states.size());
425 for (auto& state : transaction.states) {
426 ResolvedComposerState resolvedState;
427 resolvedState.state = std::move(state.state);
428 resolvedState.externalTexture =
429 std::make_shared<FakeExternalTexture>(*resolvedState.state.bufferData);
430 resolvedStates.emplace_back(resolvedState);
431 }
432
433 TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,
434 transaction.displays, transaction.flags,
435 transaction.applyToken,
436 transaction.inputWindowCommands,
437 transaction.desiredPresentTime,
438 transaction.isAutoTimestamp, {}, systemTime(),
439 mHasListenerCallbacks, mCallbacks, getpid(),
440 static_cast<int>(getuid()), transaction.id,
441 transaction.mergedTransactionIds);
442 mFlinger.setTransactionStateInternal(transactionState);
443 }
444 mFlinger.flushTransactionQueues();
445 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
446 EXPECT_EQ(expectedTransactionsPending, mFlinger.getPendingTransactionCount());
447 }
448 };
449
450 class LatchUnsignaledAutoSingleLayerTest : public LatchUnsignaledTest {
451 public:
SetUp()452 void SetUp() override {
453 LatchUnsignaledTest::SetUp();
454 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::AutoSingleLayer;
455 }
456 };
457
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_RemovesSingleSignaledFromTheQueue)458 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
459 const sp<IBinder> kApplyToken =
460 IInterface::asBinder(TransactionCompletedListener::getIInstance());
461 const auto kLayerId = 1;
462 const auto kExpectedTransactionsPending = 0u;
463
464 const auto signaledTransaction =
465 createTransactionInfo(kApplyToken,
466 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
467 layer_state_t::eBufferChanged)});
468 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
469 }
470
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_RemovesSingleUnSignaledFromTheQueue)471 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleUnSignaledFromTheQueue) {
472 const sp<IBinder> kApplyToken =
473 IInterface::asBinder(TransactionCompletedListener::getIInstance());
474 const auto kLayerId = 1;
475 const auto kExpectedTransactionsPending = 0u;
476
477 const auto unsignaledTransaction =
478 createTransactionInfo(kApplyToken,
479 {
480 createComposerState(kLayerId,
481 fence(Fence::Status::Unsignaled),
482 layer_state_t::eBufferChanged),
483 });
484 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
485 }
486
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange)487 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange) {
488 const sp<IBinder> kApplyToken =
489 IInterface::asBinder(TransactionCompletedListener::getIInstance());
490 const auto kLayerId = 1;
491 const auto kExpectedTransactionsPending = 1u;
492
493 const auto unsignaledTransaction =
494 createTransactionInfo(kApplyToken,
495 {
496 createComposerState(kLayerId,
497 fence(Fence::Status::Unsignaled),
498 layer_state_t::eCropChanged |
499 layer_state_t::
500 eBufferChanged),
501 });
502 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
503 }
504
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsUnSignaledInTheQueue_AutoRefreshChanged)505 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_AutoRefreshChanged) {
506 SET_FLAG_FOR_TEST(flags::latch_unsignaled_with_auto_refresh_changed, false);
507 const sp<IBinder> kApplyToken =
508 IInterface::asBinder(TransactionCompletedListener::getIInstance());
509 const auto kLayerId = 1;
510 const auto kExpectedTransactionsPending = 1u;
511
512 const auto unsignaledTransaction =
513 createTransactionInfo(kApplyToken,
514 {
515 createComposerState(kLayerId,
516 fence(Fence::Status::Unsignaled),
517 layer_state_t::eAutoRefreshChanged |
518 layer_state_t::
519 eBufferChanged),
520 });
521 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
522 }
523
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_RemovesUnSignaledInTheQueue_AutoRefreshChanged)524 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesUnSignaledInTheQueue_AutoRefreshChanged) {
525 SET_FLAG_FOR_TEST(flags::latch_unsignaled_with_auto_refresh_changed, true);
526 const sp<IBinder> kApplyToken =
527 IInterface::asBinder(TransactionCompletedListener::getIInstance());
528 const auto kLayerId = 1;
529 const auto kExpectedTransactionsPending = 0u;
530
531 const auto unsignaledTransaction =
532 createTransactionInfo(kApplyToken,
533 {
534 createComposerState(kLayerId,
535 fence(Fence::Status::Unsignaled),
536 layer_state_t::eAutoRefreshChanged |
537 layer_state_t::
538 eBufferChanged),
539 });
540 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
541 }
542
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed)543 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed) {
544 const sp<IBinder> kApplyToken =
545 IInterface::asBinder(TransactionCompletedListener::getIInstance());
546 const auto kLayerId = 1;
547 const auto kExpectedTransactionsPending = 1u;
548
549 const auto unsignaledTransaction =
550 createTransactionInfo(kApplyToken,
551 {
552 createComposerState(kLayerId,
553 fence(Fence::Status::Unsignaled),
554 layer_state_t::eCropChanged |
555 layer_state_t::
556 eBufferChanged),
557 });
558 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
559 }
560
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsInTheQueueSameApplyTokenMultiState)561 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueueSameApplyTokenMultiState) {
562 const sp<IBinder> kApplyToken =
563 IInterface::asBinder(TransactionCompletedListener::getIInstance());
564 const auto kLayerId = 1;
565 const auto kExpectedTransactionsPending = 1u;
566
567 const auto mixedTransaction =
568 createTransactionInfo(kApplyToken,
569 {
570 createComposerState(kLayerId,
571 fence(Fence::Status::Unsignaled),
572 layer_state_t::eBufferChanged),
573 createComposerState(kLayerId,
574 fence(Fence::Status::Signaled),
575 layer_state_t::eBufferChanged),
576 });
577 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
578 }
579
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsInTheQueue_MultipleStateTransaction)580 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueue_MultipleStateTransaction) {
581 const sp<IBinder> kApplyToken =
582 IInterface::asBinder(TransactionCompletedListener::getIInstance());
583 const auto kLayerId1 = 1;
584 const auto kLayerId2 = 2;
585 const auto kExpectedTransactionsPending = 1u;
586
587 const auto mixedTransaction =
588 createTransactionInfo(kApplyToken,
589 {
590 createComposerState(kLayerId1,
591 fence(Fence::Status::Unsignaled),
592 layer_state_t::eBufferChanged),
593 createComposerState(kLayerId2,
594 fence(Fence::Status::Signaled),
595 layer_state_t::eBufferChanged),
596 });
597 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
598 }
599
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_RemovesSignaledFromTheQueue)600 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
601 const sp<IBinder> kApplyToken =
602 IInterface::asBinder(TransactionCompletedListener::getIInstance());
603 const auto kLayerId1 = 1;
604 const auto kLayerId2 = 2;
605 const auto kExpectedTransactionsPending = 0u;
606
607 const auto signaledTransaction =
608 createTransactionInfo(kApplyToken,
609 {
610 createComposerState(kLayerId1,
611 fence(Fence::Status::Signaled),
612 layer_state_t::eBufferChanged),
613 });
614 const auto signaledTransaction2 =
615 createTransactionInfo(kApplyToken,
616 {
617 createComposerState(kLayerId2,
618 fence(Fence::Status::Signaled),
619 layer_state_t::eBufferChanged),
620 });
621 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
622 }
623
TEST_F(LatchUnsignaledAutoSingleLayerTest,UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst)624 TEST_F(LatchUnsignaledAutoSingleLayerTest,
625 UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) {
626 const sp<IBinder> kApplyToken1 =
627 IInterface::asBinder(TransactionCompletedListener::getIInstance());
628 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
629 const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
630 const auto kLayerId1 = 1;
631 const auto kLayerId2 = 2;
632 const auto kExpectedTransactionsPending = 1u;
633
634 const auto unsignaledTransaction =
635 createTransactionInfo(kApplyToken1,
636 {
637 createComposerState(kLayerId1,
638 fence(Fence::Status::Unsignaled),
639 layer_state_t::eBufferChanged),
640 });
641
642 const auto signaledTransaction =
643 createTransactionInfo(kApplyToken2,
644 {
645 createComposerState(kLayerId2,
646 fence(Fence::Status::Signaled),
647 layer_state_t::eBufferChanged),
648 });
649 const auto signaledTransaction2 =
650 createTransactionInfo(kApplyToken3,
651 {
652 createComposerState(kLayerId2,
653 fence(Fence::Status::Signaled),
654 layer_state_t::eBufferChanged),
655 });
656
657 setTransactionStates({unsignaledTransaction, signaledTransaction, signaledTransaction2},
658 kExpectedTransactionsPending);
659 }
660
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsTransactionInTheQueueSameApplyToken)661 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {
662 const sp<IBinder> kApplyToken =
663 IInterface::asBinder(TransactionCompletedListener::getIInstance());
664 const auto kLayerId1 = 1;
665 const auto kLayerId2 = 2;
666 const auto kExpectedTransactionsPending = 1u;
667
668 const auto unsignaledTransaction =
669 createTransactionInfo(kApplyToken,
670 {
671 createComposerState(kLayerId1,
672 fence(Fence::Status::Unsignaled),
673 layer_state_t::eBufferChanged),
674 });
675 const auto signaledTransaction =
676 createTransactionInfo(kApplyToken,
677 {
678 createComposerState(kLayerId2,
679 fence(Fence::Status::Signaled),
680 layer_state_t::eBufferChanged),
681 });
682 setTransactionStates({unsignaledTransaction, signaledTransaction},
683 kExpectedTransactionsPending);
684 }
685
TEST_F(LatchUnsignaledAutoSingleLayerTest,Flush_KeepsTransactionInTheQueue)686 TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueue) {
687 const sp<IBinder> kApplyToken1 =
688 IInterface::asBinder(TransactionCompletedListener::getIInstance());
689 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
690 const auto kLayerId1 = 1;
691 const auto kLayerId2 = 2;
692 const auto kExpectedTransactionsPending = 1u;
693
694 const auto unsignaledTransaction =
695 createTransactionInfo(kApplyToken1,
696 {
697 createComposerState(kLayerId1,
698 fence(Fence::Status::Unsignaled),
699 layer_state_t::eBufferChanged),
700 });
701 const auto unsignaledTransaction2 =
702 createTransactionInfo(kApplyToken2,
703 {
704 createComposerState(kLayerId2,
705 fence(Fence::Status::Unsignaled),
706 layer_state_t::eBufferChanged),
707 });
708 setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
709 kExpectedTransactionsPending);
710 }
711
TEST_F(LatchUnsignaledAutoSingleLayerTest,DontLatchUnsignaledWhenEarlyOffset)712 TEST_F(LatchUnsignaledAutoSingleLayerTest, DontLatchUnsignaledWhenEarlyOffset) {
713 const sp<IBinder> kApplyToken =
714 IInterface::asBinder(TransactionCompletedListener::getIInstance());
715 const auto kLayerId = 1;
716 const auto kExpectedTransactionsPending = 1u;
717
718 const auto unsignaledTransaction =
719 createTransactionInfo(kApplyToken,
720 {
721 createComposerState(kLayerId,
722 fence(Fence::Status::Unsignaled),
723 layer_state_t::eBufferChanged),
724 });
725
726 modulateVsync();
727 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
728 }
729
TEST_F(LatchUnsignaledAutoSingleLayerTest,UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst)730 TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) {
731 const sp<IBinder> kApplyToken1 =
732 IInterface::asBinder(TransactionCompletedListener::getIInstance());
733 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
734 const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
735 const auto kLayerId1 = 1;
736 const auto kLayerId2 = 2;
737 const auto kExpectedTransactionsPending = 1u;
738
739 const auto signaledTransaction =
740 createTransactionInfo(kApplyToken1,
741 {
742 createComposerState(kLayerId1,
743 fence(Fence::Status::Signaled),
744 layer_state_t::eBufferChanged),
745 });
746 const auto signaledTransaction2 =
747 createTransactionInfo(kApplyToken2,
748 {
749 createComposerState(kLayerId1,
750 fence(Fence::Status::Signaled),
751 layer_state_t::eBufferChanged),
752 });
753 const auto unsignaledTransaction =
754 createTransactionInfo(kApplyToken3,
755 {
756 createComposerState(kLayerId2,
757 fence(Fence::Status::Unsignaled),
758 layer_state_t::eBufferChanged),
759 });
760
761 setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction},
762 kExpectedTransactionsPending);
763 }
764
765 class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
766 public:
SetUp()767 void SetUp() override {
768 LatchUnsignaledTest::SetUp();
769 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
770 }
771 };
772
TEST_F(LatchUnsignaledDisabledTest,Flush_RemovesSignaledFromTheQueue)773 TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
774 const sp<IBinder> kApplyToken =
775 IInterface::asBinder(TransactionCompletedListener::getIInstance());
776 const auto kLayerId = 1;
777 const auto kExpectedTransactionsPending = 0u;
778
779 const auto signaledTransaction =
780 createTransactionInfo(kApplyToken,
781 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
782 layer_state_t::eBufferChanged)});
783 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
784 }
785
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepsInTheQueue)786 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueue) {
787 const sp<IBinder> kApplyToken =
788 IInterface::asBinder(TransactionCompletedListener::getIInstance());
789 const auto kLayerId = 1;
790 const auto kExpectedTransactionsPending = 1u;
791
792 const auto unsignaledTransaction =
793 createTransactionInfo(kApplyToken,
794 {
795 createComposerState(kLayerId,
796 fence(Fence::Status::Unsignaled),
797 layer_state_t::eBufferChanged),
798 });
799 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
800 }
801
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepsInTheQueueSameLayerId)802 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueSameLayerId) {
803 const sp<IBinder> kApplyToken =
804 IInterface::asBinder(TransactionCompletedListener::getIInstance());
805 const auto kLayerId = 1;
806 const auto kExpectedTransactionsPending = 1u;
807
808 const auto unsignaledTransaction =
809 createTransactionInfo(kApplyToken,
810 {
811 createComposerState(kLayerId,
812 fence(Fence::Status::Unsignaled),
813 layer_state_t::eBufferChanged),
814 createComposerState(kLayerId,
815 fence(Fence::Status::Unsignaled),
816 layer_state_t::eBufferChanged),
817 });
818 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
819 }
820
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepsInTheQueueDifferentLayerId)821 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueDifferentLayerId) {
822 const sp<IBinder> kApplyToken =
823 IInterface::asBinder(TransactionCompletedListener::getIInstance());
824 const auto kLayerId1 = 1;
825 const auto kLayerId2 = 2;
826 const auto kExpectedTransactionsPending = 1u;
827
828 const auto unsignaledTransaction =
829 createTransactionInfo(kApplyToken,
830 {
831 createComposerState(kLayerId1,
832 fence(Fence::Status::Unsignaled),
833 layer_state_t::eBufferChanged),
834 createComposerState(kLayerId2,
835 fence(Fence::Status::Unsignaled),
836 layer_state_t::eBufferChanged),
837 });
838 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
839 }
840
TEST_F(LatchUnsignaledDisabledTest,Flush_RemovesSignaledFromTheQueue_MultipleLayers)841 TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
842 const sp<IBinder> kApplyToken =
843 IInterface::asBinder(TransactionCompletedListener::getIInstance());
844 const auto kLayerId1 = 1;
845 const auto kLayerId2 = 2;
846 const auto kExpectedTransactionsPending = 0u;
847
848 const auto signaledTransaction =
849 createTransactionInfo(kApplyToken,
850 {
851 createComposerState(kLayerId1,
852 fence(Fence::Status::Signaled),
853 layer_state_t::eBufferChanged),
854 });
855 const auto signaledTransaction2 =
856 createTransactionInfo(kApplyToken,
857 {
858 createComposerState(kLayerId2,
859 fence(Fence::Status::Signaled),
860 layer_state_t::eBufferChanged),
861 });
862 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
863 }
864
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepInTheQueueDifferentApplyToken)865 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueDifferentApplyToken) {
866 const sp<IBinder> kApplyToken1 =
867 IInterface::asBinder(TransactionCompletedListener::getIInstance());
868 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
869 const auto kLayerId1 = 1;
870 const auto kLayerId2 = 2;
871 const auto kExpectedTransactionsPending = 1u;
872
873 const auto unsignaledTransaction =
874 createTransactionInfo(kApplyToken1,
875 {
876 createComposerState(kLayerId1,
877 fence(Fence::Status::Unsignaled),
878 layer_state_t::eBufferChanged),
879 });
880 const auto signaledTransaction =
881 createTransactionInfo(kApplyToken2,
882 {
883 createComposerState(kLayerId2,
884 fence(Fence::Status::Signaled),
885 layer_state_t::eBufferChanged),
886 });
887 setTransactionStates({unsignaledTransaction, signaledTransaction},
888 kExpectedTransactionsPending);
889 }
890
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepInTheQueueSameApplyToken)891 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueSameApplyToken) {
892 const sp<IBinder> kApplyToken =
893 IInterface::asBinder(TransactionCompletedListener::getIInstance());
894 const auto kLayerId1 = 1;
895 const auto kLayerId2 = 2;
896 const auto kExpectedTransactionsPending = 1u;
897
898 const auto signaledTransaction =
899 createTransactionInfo(kApplyToken,
900 {
901 createComposerState(kLayerId1,
902 fence(Fence::Status::Signaled),
903 layer_state_t::eBufferChanged),
904 });
905 const auto unsignaledTransaction =
906 createTransactionInfo(kApplyToken,
907 {
908 createComposerState(kLayerId2,
909 fence(Fence::Status::Unsignaled),
910 layer_state_t::eBufferChanged),
911 });
912 setTransactionStates({signaledTransaction, unsignaledTransaction},
913 kExpectedTransactionsPending);
914 }
915
TEST_F(LatchUnsignaledDisabledTest,Flush_KeepInTheUnsignaledTheQueue)916 TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) {
917 const sp<IBinder> kApplyToken =
918 IInterface::asBinder(TransactionCompletedListener::getIInstance());
919 const auto kLayerId1 = 1;
920 const auto kLayerId2 = 2;
921 const auto kExpectedTransactionsPending = 2u;
922
923 const auto unsignaledTransaction =
924 createTransactionInfo(kApplyToken,
925 {
926 createComposerState(kLayerId1,
927 fence(Fence::Status::Unsignaled),
928 layer_state_t::eBufferChanged),
929 });
930 const auto unsignaledTransaction2 =
931 createTransactionInfo(kApplyToken,
932 {
933 createComposerState(kLayerId2,
934 fence(Fence::Status::Unsignaled),
935 layer_state_t::eBufferChanged),
936 });
937 setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
938 kExpectedTransactionsPending);
939 }
940
TEST(TransactionHandlerTest,QueueTransaction)941 TEST(TransactionHandlerTest, QueueTransaction) {
942 TransactionHandler handler;
943 TransactionState transaction;
944 transaction.applyToken = sp<BBinder>::make();
945 transaction.id = 42;
946 handler.queueTransaction(std::move(transaction));
947 handler.collectTransactions();
948 std::vector<TransactionState> transactionsReadyToBeApplied = handler.flushTransactions();
949
950 EXPECT_EQ(transactionsReadyToBeApplied.size(), 1u);
951 EXPECT_EQ(transactionsReadyToBeApplied.front().id, 42u);
952 }
953
TEST(TransactionHandlerTest,TransactionsKeepTrackOfDirectMerges)954 TEST(TransactionHandlerTest, TransactionsKeepTrackOfDirectMerges) {
955 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3, transaction4;
956
957 uint64_t transaction2Id = transaction2.getId();
958 uint64_t transaction3Id = transaction3.getId();
959 EXPECT_NE(transaction2Id, transaction3Id);
960
961 transaction1.merge(std::move(transaction2));
962 transaction1.merge(std::move(transaction3));
963
964 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 2u);
965 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction3Id);
966 EXPECT_EQ(transaction1.getMergedTransactionIds()[1], transaction2Id);
967 }
968
TEST(TransactionHandlerTest,TransactionsKeepTrackOfIndirectMerges)969 TEST(TransactionHandlerTest, TransactionsKeepTrackOfIndirectMerges) {
970 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3, transaction4;
971
972 uint64_t transaction2Id = transaction2.getId();
973 uint64_t transaction3Id = transaction3.getId();
974 uint64_t transaction4Id = transaction4.getId();
975 EXPECT_NE(transaction2Id, transaction3Id);
976 EXPECT_NE(transaction2Id, transaction4Id);
977 EXPECT_NE(transaction3Id, transaction4Id);
978
979 transaction4.merge(std::move(transaction2));
980 transaction4.merge(std::move(transaction3));
981
982 EXPECT_EQ(transaction4.getMergedTransactionIds().size(), 2u);
983 EXPECT_EQ(transaction4.getMergedTransactionIds()[0], transaction3Id);
984 EXPECT_EQ(transaction4.getMergedTransactionIds()[1], transaction2Id);
985
986 transaction1.merge(std::move(transaction4));
987
988 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 3u);
989 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction4Id);
990 EXPECT_EQ(transaction1.getMergedTransactionIds()[1], transaction3Id);
991 EXPECT_EQ(transaction1.getMergedTransactionIds()[2], transaction2Id);
992 }
993
TEST(TransactionHandlerTest,TransactionMergesAreCleared)994 TEST(TransactionHandlerTest, TransactionMergesAreCleared) {
995 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3;
996
997 transaction1.merge(std::move(transaction2));
998 transaction1.merge(std::move(transaction3));
999
1000 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 2u);
1001
1002 transaction1.clear();
1003
1004 EXPECT_EQ(transaction1.getMergedTransactionIds().empty(), true);
1005 }
1006
TEST(TransactionHandlerTest,TransactionMergesAreCapped)1007 TEST(TransactionHandlerTest, TransactionMergesAreCapped) {
1008 SurfaceComposerClient::Transaction transaction;
1009 std::vector<uint64_t> mergedTransactionIds;
1010
1011 for (uint i = 0; i < 20u; i++) {
1012 SurfaceComposerClient::Transaction transactionToMerge;
1013 mergedTransactionIds.push_back(transactionToMerge.getId());
1014 transaction.merge(std::move(transactionToMerge));
1015 }
1016
1017 // Keeps latest 10 merges in order of merge recency
1018 EXPECT_EQ(transaction.getMergedTransactionIds().size(), 10u);
1019 for (uint i = 0; i < 10u; i++) {
1020 EXPECT_EQ(transaction.getMergedTransactionIds()[i],
1021 mergedTransactionIds[mergedTransactionIds.size() - 1 - i]);
1022 }
1023 }
1024
TEST(TransactionHandlerTest,KeepsMergesFromMoreRecentMerge)1025 TEST(TransactionHandlerTest, KeepsMergesFromMoreRecentMerge) {
1026 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3;
1027 std::vector<uint64_t> mergedTransactionIds1, mergedTransactionIds2, mergedTransactionIds3;
1028 uint64_t transaction2Id = transaction2.getId();
1029 uint64_t transaction3Id = transaction3.getId();
1030
1031 for (uint i = 0; i < 20u; i++) {
1032 SurfaceComposerClient::Transaction transactionToMerge;
1033 mergedTransactionIds1.push_back(transactionToMerge.getId());
1034 transaction1.merge(std::move(transactionToMerge));
1035 }
1036
1037 for (uint i = 0; i < 5u; i++) {
1038 SurfaceComposerClient::Transaction transactionToMerge;
1039 mergedTransactionIds2.push_back(transactionToMerge.getId());
1040 transaction2.merge(std::move(transactionToMerge));
1041 }
1042
1043 transaction1.merge(std::move(transaction2));
1044 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1045 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction2Id);
1046 for (uint i = 0; i < 5u; i++) {
1047 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 1u],
1048 mergedTransactionIds2[mergedTransactionIds2.size() - 1 - i]);
1049 }
1050 for (uint i = 0; i < 4u; i++) {
1051 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 6u],
1052 mergedTransactionIds1[mergedTransactionIds1.size() - 1 - i]);
1053 }
1054
1055 for (uint i = 0; i < 20u; i++) {
1056 SurfaceComposerClient::Transaction transactionToMerge;
1057 mergedTransactionIds3.push_back(transactionToMerge.getId());
1058 transaction3.merge(std::move(transactionToMerge));
1059 }
1060
1061 transaction1.merge(std::move(transaction3));
1062 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1063 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction3Id);
1064 for (uint i = 0; i < 9u; i++) {
1065 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 1],
1066 mergedTransactionIds3[mergedTransactionIds3.size() - 1 - i]);
1067 }
1068 }
1069
TEST(TransactionHandlerTest,CanAddTransactionWithFullMergedIds)1070 TEST(TransactionHandlerTest, CanAddTransactionWithFullMergedIds) {
1071 SurfaceComposerClient::Transaction transaction1, transaction2;
1072 for (uint i = 0; i < 20u; i++) {
1073 SurfaceComposerClient::Transaction transactionToMerge;
1074 transaction1.merge(std::move(transactionToMerge));
1075 }
1076
1077 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1078
1079 auto transaction1Id = transaction1.getId();
1080 transaction2.merge(std::move(transaction1));
1081 EXPECT_EQ(transaction2.getMergedTransactionIds().size(), 10u);
1082 auto mergedTransactionIds = transaction2.getMergedTransactionIds();
1083 EXPECT_TRUE(std::count(mergedTransactionIds.begin(), mergedTransactionIds.end(),
1084 transaction1Id) > 0);
1085 }
1086
1087 } // namespace android
1088