blob: 7fb9247ee05c734ab60af5d4d31aec7004af0d8d [file] [log] [blame]
Valerie Haud251afb2019-03-29 14:19:02 -07001/*
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
Ying Wei1fd9bfc2023-06-29 16:47:00 +000018#define LOG_TAG "TransactionApplicationTest"
Valerie Haud251afb2019-03-29 14:19:02 -070019
Ady Abrahambb1ad762024-03-27 18:31:28 -070020#include <common/test/FlagUtils.h>
Valerie Haud251afb2019-03-29 14:19:02 -070021#include <compositionengine/Display.h>
22#include <compositionengine/mock/DisplaySurface.h>
23#include <gmock/gmock.h>
24#include <gtest/gtest.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070025#include <gui/LayerState.h>
Valerie Haud251afb2019-03-29 14:19:02 -070026#include <gui/SurfaceComposerClient.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070027#include <gui/fake/BufferData.h>
Valerie Haud251afb2019-03-29 14:19:02 -070028#include <log/log.h>
ramindani4d48f902021-09-20 21:07:45 +000029#include <ui/MockFence.h>
Valerie Haud251afb2019-03-29 14:19:02 -070030#include <utils/String8.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070031#include <vector>
32#include <binder/Binder.h>
Dominik Laskowski068173d2021-08-11 17:22:59 -070033
Vishnu Naira61e4fb2022-10-18 18:29:37 +000034#include "FrontEnd/TransactionHandler.h"
Valerie Haud251afb2019-03-29 14:19:02 -070035#include "TestableSurfaceFlinger.h"
Vishnu Nair40fff5c2022-11-04 02:46:28 +000036#include "TransactionState.h"
Valerie Haud251afb2019-03-29 14:19:02 -070037
Ady Abrahambb1ad762024-03-27 18:31:28 -070038#include <com_android_graphics_surfaceflinger_flags.h>
39
Valerie Haud251afb2019-03-29 14:19:02 -070040namespace android {
41
Ady Abrahambb1ad762024-03-27 18:31:28 -070042using namespace com::android::graphics::surfaceflinger;
Valerie Haud251afb2019-03-29 14:19:02 -070043using testing::_;
44using testing::Return;
45
Vishnu Nairaf6d2972022-11-18 06:26:38 +000046using frontend::TransactionHandler;
47
Vishnu Nair1523dad2022-09-29 16:05:18 -070048constexpr nsecs_t TRANSACTION_TIMEOUT = s2ns(5);
Valerie Haud251afb2019-03-29 14:19:02 -070049class TransactionApplicationTest : public testing::Test {
50public:
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
Dominik Laskowskiaee9a622023-02-11 14:24:19 -050056 mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
57 mFlinger.setupMockScheduler();
58 mFlinger.flinger()->addTransactionReadyFilters();
Valerie Haud251afb2019-03-29 14:19:02 -070059 }
60
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
Valerie Haud251afb2019-03-29 14:19:02 -070067 TestableSurfaceFlinger mFlinger;
68
Valerie Haud251afb2019-03-29 14:19:02 -070069 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;
Ady Abrahamf0c56492020-12-17 18:04:15 -080075 int64_t desiredPresentTime = 0;
76 bool isAutoTimestamp = true;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100077 FrameTimelineInfo frameTimelineInfo;
Patrick Williams6c6dd3b2023-02-13 22:53:06 +000078 std::vector<client_cache_t> uncacheBuffers;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100079 uint64_t id = static_cast<uint64_t>(-1);
Pablo Gamito23780be2023-04-18 08:30:00 +000080 std::vector<uint64_t> mergedTransactionIds;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100081 static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
Valerie Haud251afb2019-03-29 14:19:02 -070082 };
83
Vishnu Nair6b591152021-10-08 11:45:14 -070084 void checkEqual(TransactionInfo info, TransactionState state) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100085 EXPECT_EQ(0u, info.states.size());
86 EXPECT_EQ(0u, state.states.size());
Valerie Haud251afb2019-03-29 14:19:02 -070087
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100088 EXPECT_EQ(0u, info.displays.size());
89 EXPECT_EQ(0u, state.displays.size());
Valerie Haud251afb2019-03-29 14:19:02 -070090 EXPECT_EQ(info.flags, state.flags);
91 EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
92 }
93
Patrick Williams641f7f22022-06-22 19:25:35 +000094 void setupSingle(TransactionInfo& transaction, uint32_t flags, int64_t desiredPresentTime,
95 bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo) {
Valerie Haud251afb2019-03-29 14:19:02 -070096 mTransactionNumber++;
Vishnu Nair1523dad2022-09-29 16:05:18 -070097 transaction.flags |= flags;
Valerie Haud251afb2019-03-29 14:19:02 -070098 transaction.desiredPresentTime = desiredPresentTime;
Ady Abrahamf0c56492020-12-17 18:04:15 -080099 transaction.isAutoTimestamp = isAutoTimestamp;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000100 transaction.frameTimelineInfo = frameTimelineInfo;
Valerie Haud251afb2019-03-29 14:19:02 -0700101 }
102
Patrick Williams641f7f22022-06-22 19:25:35 +0000103 void NotPlacedOnTransactionQueue(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000104 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700105 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700106 TransactionInfo transaction;
Patrick Williams641f7f22022-06-22 19:25:35 +0000107 setupSingle(transaction, flags,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800108 /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000109 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700110 nsecs_t applicationTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000111 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700112 transaction.displays, transaction.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700113 transaction.applyToken, transaction.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800114 transaction.desiredPresentTime, transaction.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000115 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000116 transaction.id, transaction.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700117
Patrick Williams641f7f22022-06-22 19:25:35 +0000118 // 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.
Valerie Haud251afb2019-03-29 14:19:02 -0700120 nsecs_t returnedTime = systemTime();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700121 EXPECT_LE(returnedTime, applicationTime + TRANSACTION_TIMEOUT);
Arthur Hung58144272021-01-16 03:43:53 +0000122 // Each transaction should have been placed on the transaction queue
Vishnu Nair60d902e2022-07-20 02:55:37 +0000123 auto& transactionQueue = mFlinger.getTransactionQueue();
124 EXPECT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700125 }
126
Patrick Williams641f7f22022-06-22 19:25:35 +0000127 void PlaceOnTransactionQueue(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000128 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700129 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700130
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();
Valerie Haud251afb2019-03-29 14:19:02 -0700134 TransactionInfo transaction;
Patrick Williams641f7f22022-06-22 19:25:35 +0000135 setupSingle(transaction, flags, /*desiredPresentTime*/ time + s2ns(1), false,
136 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700137 nsecs_t applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000138 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700139 transaction.displays, transaction.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700140 transaction.applyToken, transaction.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800141 transaction.desiredPresentTime, transaction.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000142 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000143 transaction.id, transaction.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700144
145 nsecs_t returnedTime = systemTime();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700146 EXPECT_LE(returnedTime, applicationSentTime + TRANSACTION_TIMEOUT);
Valerie Haud251afb2019-03-29 14:19:02 -0700147 // This transaction should have been placed on the transaction queue
Vishnu Nair60d902e2022-07-20 02:55:37 +0000148 auto& transactionQueue = mFlinger.getTransactionQueue();
149 EXPECT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700150 }
151
Patrick Williams641f7f22022-06-22 19:25:35 +0000152 void BlockedByPriorTransaction(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000153 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700154 nsecs_t time = systemTime();
Patrick Williams641f7f22022-06-22 19:25:35 +0000155 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
156
Valerie Haud251afb2019-03-29 14:19:02 -0700157 // transaction that should go on the pending thread
158 TransactionInfo transactionA;
Patrick Williams641f7f22022-06-22 19:25:35 +0000159 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ time + s2ns(1), false,
160 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700161
162 // transaction that would not have gone on the pending thread if not
163 // blocked
164 TransactionInfo transactionB;
Patrick Williams641f7f22022-06-22 19:25:35 +0000165 setupSingle(transactionB, flags, /*desiredPresentTime*/ systemTime(),
166 /*isAutoTimestamp*/ true, FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700167
168 nsecs_t applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000169 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700170 transactionA.displays, transactionA.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700171 transactionA.applyToken, transactionA.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800172 transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000173 transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000174 transactionA.id, transactionA.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700175
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)
Vishnu Nair1523dad2022-09-29 16:05:18 -0700179 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
Arthur Hung58144272021-01-16 03:43:53 +0000180 // transaction that would goes to pending transaciton queue.
181 mFlinger.flushTransactionQueues();
Valerie Haud251afb2019-03-29 14:19:02 -0700182
183 applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000184 mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700185 transactionB.displays, transactionB.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700186 transactionB.applyToken, transactionB.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800187 transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000188 transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000189 transactionB.id, transactionB.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700190
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
Vishnu Nair1523dad2022-09-29 16:05:18 -0700195 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
Valerie Haud251afb2019-03-29 14:19:02 -0700196
Arthur Hung58144272021-01-16 03:43:53 +0000197 // transaction that would goes to pending transaciton queue.
198 mFlinger.flushTransactionQueues();
199
Ady Abrahame46243a2021-02-23 19:33:49 -0800200 // check that the transaction was applied.
Arthur Hung58144272021-01-16 03:43:53 +0000201 auto transactionQueue = mFlinger.getPendingTransactionQueue();
Ady Abrahame46243a2021-02-23 19:33:49 -0800202 EXPECT_EQ(0u, transactionQueue.size());
Valerie Haud251afb2019-03-29 14:19:02 -0700203 }
204
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500205 void modulateVsync() {
206 static_cast<void>(
Dominik Laskowski14956dc2023-02-22 13:43:57 -0500207 mFlinger.mutableScheduler().vsyncModulator().onRefreshRateChangeInitiated());
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500208 }
209
Valerie Haud251afb2019-03-29 14:19:02 -0700210 bool mHasListenerCallbacks = false;
211 std::vector<ListenerCallbacks> mCallbacks;
212 int mTransactionNumber = 0;
213};
214
Vishnu Nair60d902e2022-07-20 02:55:37 +0000215TEST_F(TransactionApplicationTest, AddToPendingQueue) {
216 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700217 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700218
Valerie Haud251afb2019-03-29 14:19:02 -0700219 TransactionInfo transactionA; // transaction to go on pending queue
Patrick Williams641f7f22022-06-22 19:25:35 +0000220 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
221 FrameTimelineInfo{});
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000222 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700223 transactionA.displays, transactionA.flags, transactionA.applyToken,
224 transactionA.inputWindowCommands, transactionA.desiredPresentTime,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000225 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
Pablo Gamito23780be2023-04-18 08:30:00 +0000226 mHasListenerCallbacks, mCallbacks, transactionA.id,
227 transactionA.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700228
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000229 auto& transactionQueue = mFlinger.getTransactionQueue();
Vishnu Nair60d902e2022-07-20 02:55:37 +0000230 ASSERT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700231
Vishnu Nair60d902e2022-07-20 02:55:37 +0000232 auto transactionState = transactionQueue.pop().value();
Valerie Haud251afb2019-03-29 14:19:02 -0700233 checkEqual(transactionA, transactionState);
Vishnu Nair60d902e2022-07-20 02:55:37 +0000234}
235
236TEST_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,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000246 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
Pablo Gamito23780be2023-04-18 08:30:00 +0000247 mHasListenerCallbacks, mCallbacks, transactionA.id,
248 transactionA.mergedTransactionIds);
Vishnu Nair60d902e2022-07-20 02:55:37 +0000249
250 auto& transactionQueue = mFlinger.getTransactionQueue();
251 ASSERT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700252
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>();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000258 mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
259 empty.applyToken, empty.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800260 empty.desiredPresentTime, empty.isAutoTimestamp,
Pablo Gamito23780be2023-04-18 08:30:00 +0000261 empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id,
262 empty.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700263
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000264 // flush transaction queue should flush as desiredPresentTime has
Valerie Haud251afb2019-03-29 14:19:02 -0700265 // passed
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000266 mFlinger.flushTransactionQueues();
Valerie Haud251afb2019-03-29 14:19:02 -0700267
Vishnu Nair60d902e2022-07-20 02:55:37 +0000268 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700269}
270
Valerie Haud251afb2019-03-29 14:19:02 -0700271TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) {
Patrick Williams641f7f22022-06-22 19:25:35 +0000272 NotPlacedOnTransactionQueue(/*flags*/ 0);
Valerie Haud251afb2019-03-29 14:19:02 -0700273}
274
Valerie Haud251afb2019-03-29 14:19:02 -0700275TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) {
Patrick Williams641f7f22022-06-22 19:25:35 +0000276 PlaceOnTransactionQueue(/*flags*/ 0);
Valerie Haud251afb2019-03-29 14:19:02 -0700277}
278
Valerie Hau09e60052019-12-15 14:51:15 -0800279TEST_F(TransactionApplicationTest, FromHandle) {
280 sp<IBinder> badHandle;
281 auto ret = mFlinger.fromHandle(badHandle);
Vishnu Nair07e2a482022-10-18 19:18:16 +0000282 EXPECT_EQ(nullptr, ret.get());
Valerie Hau09e60052019-12-15 14:51:15 -0800283}
ramindani4d48f902021-09-20 21:07:45 +0000284
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700285class 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
293public:
294 FakeExternalTexture(BufferData& bufferData)
295 : mWidth(bufferData.getWidth()),
296 mHeight(bufferData.getHeight()),
297 mId(bufferData.getId()),
298 mPixelFormat(bufferData.getPixelFormat()),
299 mUsage(bufferData.getUsage()) {}
300 const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
301 bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
302 return getId() == other.getId();
303 }
304 uint32_t getWidth() const override { return mWidth; }
305 uint32_t getHeight() const override { return mHeight; }
306 uint64_t getId() const override { return mId; }
307 PixelFormat getPixelFormat() const override { return mPixelFormat; }
308 uint64_t getUsage() const override { return mUsage; }
309 void remapBuffer() override {}
310 ~FakeExternalTexture() = default;
311};
312
Patrick Williams1cd73f82023-07-31 15:54:48 -0500313TEST_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
Ady Abraham9dada822022-02-03 10:26:59 -0800354class LatchUnsignaledTest : public TransactionApplicationTest {
355public:
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.
Vishnu Nair60d902e2022-07-20 02:55:37 +0000359 while (!mFlinger.getTransactionQueue().isEmpty()) {
360 mFlinger.getTransactionQueue().pop();
361 }
Ady Abraham9dada822022-02-03 10:26:59 -0800362 mFlinger.getPendingTransactionQueue().clear();
Ady Abraham9dada822022-02-03 10:26:59 -0800363 mFlinger.commitTransactionsLocked(eTransactionMask);
364 mFlinger.mutableCurrentState().layersSortedByZ.clear();
365 mFlinger.mutableDrawingState().layersSortedByZ.clear();
366 }
367
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
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000374 ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what,
375 std::optional<sp<IBinder>> layerHandle = std::nullopt) {
Ady Abraham9dada822022-02-03 10:26:59 -0800376 ComposerState state;
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700377 state.state.bufferData =
378 std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
379 /* height */ 2, /* pixelFormat */ 0,
380 /* outUsage */ 0);
Ady Abraham9dada822022-02-03 10:26:59 -0800381 state.state.bufferData->acquireFence = std::move(fence);
382 state.state.layerId = layerId;
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000383 state.state.surface = layerHandle.value_or(
Patrick Williams83f36b22022-09-14 17:57:35 +0000384 sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000385 ->getHandle());
Ady Abraham9dada822022-02-03 10:26:59 -0800386 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 }
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000392 if (what & layer_state_t::eFlagsChanged) {
393 state.state.flags = layer_state_t::eEnableBackpressure;
394 state.state.mask = layer_state_t::eEnableBackpressure;
395 }
396
Ady Abraham9dada822022-02-03 10:26:59 -0800397 return state;
398 }
399
400 TransactionInfo createTransactionInfo(const sp<IBinder>& applyToken,
401 const std::vector<ComposerState>& states) {
402 TransactionInfo transaction;
Vishnu Nair1523dad2022-09-29 16:05:18 -0700403 const uint32_t kFlags = 0;
Ady Abraham9dada822022-02-03 10:26:59 -0800404 const nsecs_t kDesiredPresentTime = systemTime();
405 const bool kIsAutoTimestamp = true;
406 const auto kFrameTimelineInfo = FrameTimelineInfo{};
407
Patrick Williams641f7f22022-06-22 19:25:35 +0000408 setupSingle(transaction, kFlags, kDesiredPresentTime, kIsAutoTimestamp, kFrameTimelineInfo);
Ady Abraham9dada822022-02-03 10:26:59 -0800409 transaction.applyToken = applyToken;
410 for (const auto& state : states) {
411 transaction.states.push_back(state);
412 }
413
414 return transaction;
415 }
416
417 void setTransactionStates(const std::vector<TransactionInfo>& transactions,
Ady Abraham9dada822022-02-03 10:26:59 -0800418 size_t expectedTransactionsPending) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000419 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Ady Abraham9dada822022-02-03 10:26:59 -0800420 EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
421
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000422 for (auto transaction : transactions) {
423 std::vector<ResolvedComposerState> resolvedStates;
424 resolvedStates.reserve(transaction.states.size());
425 for (auto& state : transaction.states) {
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700426 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);
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000431 }
432
433 TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,
434 transaction.displays, transaction.flags,
435 transaction.applyToken,
436 transaction.inputWindowCommands,
437 transaction.desiredPresentTime,
Chavi Weingartenc78f53c2023-04-14 18:50:53 +0000438 transaction.isAutoTimestamp, {}, systemTime(),
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000439 mHasListenerCallbacks, mCallbacks, getpid(),
Pablo Gamito23780be2023-04-18 08:30:00 +0000440 static_cast<int>(getuid()), transaction.id,
441 transaction.mergedTransactionIds);
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000442 mFlinger.setTransactionStateInternal(transactionState);
Ady Abraham9dada822022-02-03 10:26:59 -0800443 }
444 mFlinger.flushTransactionQueues();
Vishnu Nair60d902e2022-07-20 02:55:37 +0000445 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700446 EXPECT_EQ(expectedTransactionsPending, mFlinger.getPendingTransactionCount());
Ady Abraham9dada822022-02-03 10:26:59 -0800447 }
448};
449
450class LatchUnsignaledAutoSingleLayerTest : public LatchUnsignaledTest {
451public:
452 void SetUp() override {
453 LatchUnsignaledTest::SetUp();
454 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::AutoSingleLayer;
455 }
456};
457
458TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
459 const sp<IBinder> kApplyToken =
460 IInterface::asBinder(TransactionCompletedListener::getIInstance());
461 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800462 const auto kExpectedTransactionsPending = 0u;
463
464 const auto signaledTransaction =
465 createTransactionInfo(kApplyToken,
466 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
467 layer_state_t::eBufferChanged)});
Vishnu Nair1523dad2022-09-29 16:05:18 -0700468 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000469}
470
Ady Abraham9dada822022-02-03 10:26:59 -0800471TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleUnSignaledFromTheQueue) {
472 const sp<IBinder> kApplyToken =
473 IInterface::asBinder(TransactionCompletedListener::getIInstance());
474 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800475 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700484 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000485}
486
Ady Abraham9dada822022-02-03 10:26:59 -0800487TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange) {
488 const sp<IBinder> kApplyToken =
489 IInterface::asBinder(TransactionCompletedListener::getIInstance());
490 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800491 const auto kExpectedTransactionsPending = 1u;
492
493 const auto unsignaledTransaction =
494 createTransactionInfo(kApplyToken,
495 {
496 createComposerState(kLayerId,
497 fence(Fence::Status::Unsignaled),
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700498 layer_state_t::eCropChanged |
499 layer_state_t::
500 eBufferChanged),
Ady Abraham9dada822022-02-03 10:26:59 -0800501 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700502 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000503}
504
Ady Abrahambb1ad762024-03-27 18:31:28 -0700505TEST_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
524TEST_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
Ady Abraham9dada822022-02-03 10:26:59 -0800543TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed) {
544 const sp<IBinder> kApplyToken =
545 IInterface::asBinder(TransactionCompletedListener::getIInstance());
546 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800547 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700558 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000559}
560
Ady Abraham9dada822022-02-03 10:26:59 -0800561TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueueSameApplyTokenMultiState) {
562 const sp<IBinder> kApplyToken =
563 IInterface::asBinder(TransactionCompletedListener::getIInstance());
564 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800565 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700577 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000578}
579
Ady Abraham9dada822022-02-03 10:26:59 -0800580TEST_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;
Ady Abraham9dada822022-02-03 10:26:59 -0800585 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700597 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000598}
599
Ady Abraham9dada822022-02-03 10:26:59 -0800600TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
601 const sp<IBinder> kApplyToken =
602 IInterface::asBinder(TransactionCompletedListener::getIInstance());
603 const auto kLayerId1 = 1;
604 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800605 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700621 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000622}
623
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800624TEST_F(LatchUnsignaledAutoSingleLayerTest,
625 UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) {
Ady Abraham9dada822022-02-03 10:26:59 -0800626 const sp<IBinder> kApplyToken1 =
627 IInterface::asBinder(TransactionCompletedListener::getIInstance());
628 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800629 const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
Ady Abraham9dada822022-02-03 10:26:59 -0800630 const auto kLayerId1 = 1;
631 const auto kLayerId2 = 2;
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800632 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},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700658 kExpectedTransactionsPending);
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800659}
660
Ady Abraham9dada822022-02-03 10:26:59 -0800661TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {
662 const sp<IBinder> kApplyToken =
663 IInterface::asBinder(TransactionCompletedListener::getIInstance());
664 const auto kLayerId1 = 1;
665 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800666 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700682 setTransactionStates({unsignaledTransaction, signaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800683 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000684}
685
Ady Abraham9dada822022-02-03 10:26:59 -0800686TEST_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;
Ady Abraham9dada822022-02-03 10:26:59 -0800692 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},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700709 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000710}
711
Ady Abraham2739e832022-02-14 17:42:00 -0800712TEST_F(LatchUnsignaledAutoSingleLayerTest, DontLatchUnsignaledWhenEarlyOffset) {
713 const sp<IBinder> kApplyToken =
714 IInterface::asBinder(TransactionCompletedListener::getIInstance());
715 const auto kLayerId = 1;
Ady Abraham2739e832022-02-14 17:42:00 -0800716 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
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500726 modulateVsync();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700727 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
Ady Abraham2739e832022-02-14 17:42:00 -0800728}
729
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000730TEST_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
Ady Abraham9dada822022-02-03 10:26:59 -0800765class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
766public:
767 void SetUp() override {
768 LatchUnsignaledTest::SetUp();
769 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
770 }
771};
772
773TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
774 const sp<IBinder> kApplyToken =
775 IInterface::asBinder(TransactionCompletedListener::getIInstance());
776 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800777 const auto kExpectedTransactionsPending = 0u;
778
779 const auto signaledTransaction =
780 createTransactionInfo(kApplyToken,
781 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
782 layer_state_t::eBufferChanged)});
Vishnu Nair1523dad2022-09-29 16:05:18 -0700783 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000784}
785
Ady Abraham9dada822022-02-03 10:26:59 -0800786TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueue) {
787 const sp<IBinder> kApplyToken =
788 IInterface::asBinder(TransactionCompletedListener::getIInstance());
789 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800790 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700799 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000800}
801
Ady Abraham9dada822022-02-03 10:26:59 -0800802TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueSameLayerId) {
803 const sp<IBinder> kApplyToken =
804 IInterface::asBinder(TransactionCompletedListener::getIInstance());
805 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800806 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700818 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000819}
820
Ady Abraham9dada822022-02-03 10:26:59 -0800821TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueDifferentLayerId) {
822 const sp<IBinder> kApplyToken =
823 IInterface::asBinder(TransactionCompletedListener::getIInstance());
824 const auto kLayerId1 = 1;
825 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800826 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700838 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000839}
840
Ady Abraham9dada822022-02-03 10:26:59 -0800841TEST_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;
Ady Abraham9dada822022-02-03 10:26:59 -0800846 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700862 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000863}
864
Ady Abraham9dada822022-02-03 10:26:59 -0800865TEST_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;
Ady Abraham9dada822022-02-03 10:26:59 -0800871 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700887 setTransactionStates({unsignaledTransaction, signaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800888 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000889}
890
Ady Abraham9dada822022-02-03 10:26:59 -0800891TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueSameApplyToken) {
892 const sp<IBinder> kApplyToken =
893 IInterface::asBinder(TransactionCompletedListener::getIInstance());
894 const auto kLayerId1 = 1;
895 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800896 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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700912 setTransactionStates({signaledTransaction, unsignaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800913 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000914}
915
Ady Abraham9dada822022-02-03 10:26:59 -0800916TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) {
917 const sp<IBinder> kApplyToken =
918 IInterface::asBinder(TransactionCompletedListener::getIInstance());
919 const auto kLayerId1 = 1;
920 const auto kLayerId2 = 2;
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700921 const auto kExpectedTransactionsPending = 2u;
Ady Abraham9dada822022-02-03 10:26:59 -0800922
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},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700938 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000939}
940
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700941TEST(TransactionHandlerTest, QueueTransaction) {
942 TransactionHandler handler;
943 TransactionState transaction;
944 transaction.applyToken = sp<BBinder>::make();
945 transaction.id = 42;
946 handler.queueTransaction(std::move(transaction));
Vishnu Nair4d9cef92023-06-24 22:34:41 +0000947 handler.collectTransactions();
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700948 std::vector<TransactionState> transactionsReadyToBeApplied = handler.flushTransactions();
949
950 EXPECT_EQ(transactionsReadyToBeApplied.size(), 1u);
951 EXPECT_EQ(transactionsReadyToBeApplied.front().id, 42u);
952}
953
Pablo Gamito23780be2023-04-18 08:30:00 +0000954TEST(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
969TEST(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
994TEST(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
1007TEST(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
1025TEST(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
1070TEST(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
Valerie Haud251afb2019-03-29 14:19:02 -07001087} // namespace android