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