blob: 23c684217d643e9ee4e33a447ad6096bdbc5f7e5 [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
Vishnu Nair0a51a872024-07-22 23:08:39 +000020#include <binder/Binder.h>
Ady Abrahambb1ad762024-03-27 18:31:28 -070021#include <common/test/FlagUtils.h>
Valerie Haud251afb2019-03-29 14:19:02 -070022#include <compositionengine/Display.h>
23#include <compositionengine/mock/DisplaySurface.h>
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070026#include <gui/LayerState.h>
Valerie Haud251afb2019-03-29 14:19:02 -070027#include <gui/SurfaceComposerClient.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070028#include <gui/fake/BufferData.h>
Valerie Haud251afb2019-03-29 14:19:02 -070029#include <log/log.h>
Vishnu Nair0a51a872024-07-22 23:08:39 +000030#include <renderengine/mock/RenderEngine.h>
ramindani4d48f902021-09-20 21:07:45 +000031#include <ui/MockFence.h>
Valerie Haud251afb2019-03-29 14:19:02 -070032#include <utils/String8.h>
Vishnu Nair59f6d2d2022-10-05 16:59:56 -070033#include <vector>
Dominik Laskowski068173d2021-08-11 17:22:59 -070034
Vishnu Naira61e4fb2022-10-18 18:29:37 +000035#include "FrontEnd/TransactionHandler.h"
Valerie Haud251afb2019-03-29 14:19:02 -070036#include "TestableSurfaceFlinger.h"
Vishnu Nair40fff5c2022-11-04 02:46:28 +000037#include "TransactionState.h"
Valerie Haud251afb2019-03-29 14:19:02 -070038
Ady Abrahambb1ad762024-03-27 18:31:28 -070039#include <com_android_graphics_surfaceflinger_flags.h>
40
Valerie Haud251afb2019-03-29 14:19:02 -070041namespace android {
42
Ady Abrahambb1ad762024-03-27 18:31:28 -070043using namespace com::android::graphics::surfaceflinger;
Valerie Haud251afb2019-03-29 14:19:02 -070044using testing::_;
45using testing::Return;
46
Vishnu Nairaf6d2972022-11-18 06:26:38 +000047using frontend::TransactionHandler;
48
Vishnu Nair1523dad2022-09-29 16:05:18 -070049constexpr nsecs_t TRANSACTION_TIMEOUT = s2ns(5);
Valerie Haud251afb2019-03-29 14:19:02 -070050class TransactionApplicationTest : public testing::Test {
51public:
52 TransactionApplicationTest() {
53 const ::testing::TestInfo* const test_info =
54 ::testing::UnitTest::GetInstance()->current_test_info();
55 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
56
Dominik Laskowskiaee9a622023-02-11 14:24:19 -050057 mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
58 mFlinger.setupMockScheduler();
Vishnu Nair0a51a872024-07-22 23:08:39 +000059 mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
Dominik Laskowskiaee9a622023-02-11 14:24:19 -050060 mFlinger.flinger()->addTransactionReadyFilters();
Vishnu Nair0a51a872024-07-22 23:08:39 +000061 mFlinger.enableLayerLifecycleManager();
Valerie Haud251afb2019-03-29 14:19:02 -070062 }
63
64 ~TransactionApplicationTest() {
65 const ::testing::TestInfo* const test_info =
66 ::testing::UnitTest::GetInstance()->current_test_info();
67 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
68 }
69
Valerie Haud251afb2019-03-29 14:19:02 -070070 TestableSurfaceFlinger mFlinger;
Vishnu Nair0a51a872024-07-22 23:08:39 +000071 renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
Valerie Haud251afb2019-03-29 14:19:02 -070072
Valerie Haud251afb2019-03-29 14:19:02 -070073 struct TransactionInfo {
74 Vector<ComposerState> states;
75 Vector<DisplayState> displays;
76 uint32_t flags = 0;
77 sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
78 InputWindowCommands inputWindowCommands;
Ady Abrahamf0c56492020-12-17 18:04:15 -080079 int64_t desiredPresentTime = 0;
80 bool isAutoTimestamp = true;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100081 FrameTimelineInfo frameTimelineInfo;
Patrick Williams6c6dd3b2023-02-13 22:53:06 +000082 std::vector<client_cache_t> uncacheBuffers;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100083 uint64_t id = static_cast<uint64_t>(-1);
Pablo Gamito23780be2023-04-18 08:30:00 +000084 std::vector<uint64_t> mergedTransactionIds;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100085 static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
Valerie Haud251afb2019-03-29 14:19:02 -070086 };
87
Vishnu Nair6b591152021-10-08 11:45:14 -070088 void checkEqual(TransactionInfo info, TransactionState state) {
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100089 EXPECT_EQ(0u, info.states.size());
90 EXPECT_EQ(0u, state.states.size());
Valerie Haud251afb2019-03-29 14:19:02 -070091
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -100092 EXPECT_EQ(0u, info.displays.size());
93 EXPECT_EQ(0u, state.displays.size());
Valerie Haud251afb2019-03-29 14:19:02 -070094 EXPECT_EQ(info.flags, state.flags);
95 EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
96 }
97
Patrick Williams641f7f22022-06-22 19:25:35 +000098 void setupSingle(TransactionInfo& transaction, uint32_t flags, int64_t desiredPresentTime,
99 bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo) {
Valerie Haud251afb2019-03-29 14:19:02 -0700100 mTransactionNumber++;
Vishnu Nair1523dad2022-09-29 16:05:18 -0700101 transaction.flags |= flags;
Valerie Haud251afb2019-03-29 14:19:02 -0700102 transaction.desiredPresentTime = desiredPresentTime;
Ady Abrahamf0c56492020-12-17 18:04:15 -0800103 transaction.isAutoTimestamp = isAutoTimestamp;
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000104 transaction.frameTimelineInfo = frameTimelineInfo;
Valerie Haud251afb2019-03-29 14:19:02 -0700105 }
106
Patrick Williams641f7f22022-06-22 19:25:35 +0000107 void NotPlacedOnTransactionQueue(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000108 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700109 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700110 TransactionInfo transaction;
Patrick Williams641f7f22022-06-22 19:25:35 +0000111 setupSingle(transaction, flags,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800112 /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000113 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700114 nsecs_t applicationTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000115 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700116 transaction.displays, transaction.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700117 transaction.applyToken, transaction.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800118 transaction.desiredPresentTime, transaction.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000119 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000120 transaction.id, transaction.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700121
Patrick Williams641f7f22022-06-22 19:25:35 +0000122 // If transaction is synchronous, SF applyTransactionState should time out (5s) wating for
123 // SF to commit the transaction. If this is animation, it should not time out waiting.
Valerie Haud251afb2019-03-29 14:19:02 -0700124 nsecs_t returnedTime = systemTime();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700125 EXPECT_LE(returnedTime, applicationTime + TRANSACTION_TIMEOUT);
Arthur Hung58144272021-01-16 03:43:53 +0000126 // Each transaction should have been placed on the transaction queue
Vishnu Nair60d902e2022-07-20 02:55:37 +0000127 auto& transactionQueue = mFlinger.getTransactionQueue();
128 EXPECT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700129 }
130
Patrick Williams641f7f22022-06-22 19:25:35 +0000131 void PlaceOnTransactionQueue(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000132 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700133 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700134
135 // first check will see desired present time has not passed,
136 // but afterwards it will look like the desired present time has passed
137 nsecs_t time = systemTime();
Valerie Haud251afb2019-03-29 14:19:02 -0700138 TransactionInfo transaction;
Patrick Williams641f7f22022-06-22 19:25:35 +0000139 setupSingle(transaction, flags, /*desiredPresentTime*/ time + s2ns(1), false,
140 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700141 nsecs_t applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000142 mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700143 transaction.displays, transaction.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700144 transaction.applyToken, transaction.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800145 transaction.desiredPresentTime, transaction.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000146 transaction.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000147 transaction.id, transaction.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700148
149 nsecs_t returnedTime = systemTime();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700150 EXPECT_LE(returnedTime, applicationSentTime + TRANSACTION_TIMEOUT);
Valerie Haud251afb2019-03-29 14:19:02 -0700151 // This transaction should have been placed on the transaction queue
Vishnu Nair60d902e2022-07-20 02:55:37 +0000152 auto& transactionQueue = mFlinger.getTransactionQueue();
153 EXPECT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700154 }
155
Patrick Williams641f7f22022-06-22 19:25:35 +0000156 void BlockedByPriorTransaction(uint32_t flags) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000157 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700158 nsecs_t time = systemTime();
Patrick Williams641f7f22022-06-22 19:25:35 +0000159 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
160
Valerie Haud251afb2019-03-29 14:19:02 -0700161 // transaction that should go on the pending thread
162 TransactionInfo transactionA;
Patrick Williams641f7f22022-06-22 19:25:35 +0000163 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ time + s2ns(1), false,
164 FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700165
166 // transaction that would not have gone on the pending thread if not
167 // blocked
168 TransactionInfo transactionB;
Patrick Williams641f7f22022-06-22 19:25:35 +0000169 setupSingle(transactionB, flags, /*desiredPresentTime*/ systemTime(),
170 /*isAutoTimestamp*/ true, FrameTimelineInfo{});
Valerie Haud251afb2019-03-29 14:19:02 -0700171
172 nsecs_t applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000173 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700174 transactionA.displays, transactionA.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700175 transactionA.applyToken, transactionA.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800176 transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000177 transactionA.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000178 transactionA.id, transactionA.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700179
180 // This thread should not have been blocked by the above transaction
181 // (5s is the timeout period that applyTransactionState waits for SF to
182 // commit the transaction)
Vishnu Nair1523dad2022-09-29 16:05:18 -0700183 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
Arthur Hung58144272021-01-16 03:43:53 +0000184 // transaction that would goes to pending transaciton queue.
185 mFlinger.flushTransactionQueues();
Valerie Haud251afb2019-03-29 14:19:02 -0700186
187 applicationSentTime = systemTime();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000188 mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700189 transactionB.displays, transactionB.flags,
Valerie Haud251afb2019-03-29 14:19:02 -0700190 transactionB.applyToken, transactionB.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800191 transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000192 transactionB.uncacheBuffers, mHasListenerCallbacks, mCallbacks,
Pablo Gamito23780be2023-04-18 08:30:00 +0000193 transactionB.id, transactionB.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700194
195 // this thread should have been blocked by the above transaction
196 // if this is an animation, this thread should be blocked for 5s
197 // in setTransactionState waiting for transactionA to flush. Otherwise,
198 // the transaction should be placed on the pending queue
Vishnu Nair1523dad2022-09-29 16:05:18 -0700199 EXPECT_LE(systemTime(), applicationSentTime + TRANSACTION_TIMEOUT);
Valerie Haud251afb2019-03-29 14:19:02 -0700200
Arthur Hung58144272021-01-16 03:43:53 +0000201 // transaction that would goes to pending transaciton queue.
202 mFlinger.flushTransactionQueues();
203
Ady Abrahame46243a2021-02-23 19:33:49 -0800204 // check that the transaction was applied.
Arthur Hung58144272021-01-16 03:43:53 +0000205 auto transactionQueue = mFlinger.getPendingTransactionQueue();
Ady Abrahame46243a2021-02-23 19:33:49 -0800206 EXPECT_EQ(0u, transactionQueue.size());
Valerie Haud251afb2019-03-29 14:19:02 -0700207 }
208
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500209 void modulateVsync() {
210 static_cast<void>(
Dominik Laskowski14956dc2023-02-22 13:43:57 -0500211 mFlinger.mutableScheduler().vsyncModulator().onRefreshRateChangeInitiated());
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500212 }
213
Valerie Haud251afb2019-03-29 14:19:02 -0700214 bool mHasListenerCallbacks = false;
215 std::vector<ListenerCallbacks> mCallbacks;
216 int mTransactionNumber = 0;
217};
218
Vishnu Nair60d902e2022-07-20 02:55:37 +0000219TEST_F(TransactionApplicationTest, AddToPendingQueue) {
220 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Dominik Laskowski46f3e3b2021-08-10 11:44:24 -0700221 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
Valerie Haud251afb2019-03-29 14:19:02 -0700222
Valerie Haud251afb2019-03-29 14:19:02 -0700223 TransactionInfo transactionA; // transaction to go on pending queue
Patrick Williams641f7f22022-06-22 19:25:35 +0000224 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
225 FrameTimelineInfo{});
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000226 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
Ady Abraham22c7b5c2020-09-22 19:33:40 -0700227 transactionA.displays, transactionA.flags, transactionA.applyToken,
228 transactionA.inputWindowCommands, transactionA.desiredPresentTime,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000229 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
Pablo Gamito23780be2023-04-18 08:30:00 +0000230 mHasListenerCallbacks, mCallbacks, transactionA.id,
231 transactionA.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700232
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000233 auto& transactionQueue = mFlinger.getTransactionQueue();
Vishnu Nair60d902e2022-07-20 02:55:37 +0000234 ASSERT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700235
Vishnu Nair60d902e2022-07-20 02:55:37 +0000236 auto transactionState = transactionQueue.pop().value();
Valerie Haud251afb2019-03-29 14:19:02 -0700237 checkEqual(transactionA, transactionState);
Vishnu Nair60d902e2022-07-20 02:55:37 +0000238}
239
240TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
241 ASSERT_TRUE(mFlinger.getTransactionQueue().isEmpty());
242 EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
243
244 TransactionInfo transactionA; // transaction to go on pending queue
245 setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
246 FrameTimelineInfo{});
247 mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
248 transactionA.displays, transactionA.flags, transactionA.applyToken,
249 transactionA.inputWindowCommands, transactionA.desiredPresentTime,
Patrick Williams6c6dd3b2023-02-13 22:53:06 +0000250 transactionA.isAutoTimestamp, transactionA.uncacheBuffers,
Pablo Gamito23780be2023-04-18 08:30:00 +0000251 mHasListenerCallbacks, mCallbacks, transactionA.id,
252 transactionA.mergedTransactionIds);
Vishnu Nair60d902e2022-07-20 02:55:37 +0000253
254 auto& transactionQueue = mFlinger.getTransactionQueue();
255 ASSERT_FALSE(transactionQueue.isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700256
257 // because flushing uses the cached expected present time, we send an empty
258 // transaction here (sending a null applyToken to fake it as from a
259 // different process) to re-query and reset the cached expected present time
260 TransactionInfo empty;
261 empty.applyToken = sp<IBinder>();
Siarhei Vishniakoufc434ac2021-01-13 10:28:00 -1000262 mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
263 empty.applyToken, empty.inputWindowCommands,
Ady Abrahamf0c56492020-12-17 18:04:15 -0800264 empty.desiredPresentTime, empty.isAutoTimestamp,
Pablo Gamito23780be2023-04-18 08:30:00 +0000265 empty.uncacheBuffers, mHasListenerCallbacks, mCallbacks, empty.id,
266 empty.mergedTransactionIds);
Valerie Haud251afb2019-03-29 14:19:02 -0700267
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000268 // flush transaction queue should flush as desiredPresentTime has
Valerie Haud251afb2019-03-29 14:19:02 -0700269 // passed
Zhuoyao Zhang3d3540d2021-01-14 05:14:54 +0000270 mFlinger.flushTransactionQueues();
Valerie Haud251afb2019-03-29 14:19:02 -0700271
Vishnu Nair60d902e2022-07-20 02:55:37 +0000272 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Valerie Haud251afb2019-03-29 14:19:02 -0700273}
274
Valerie Haud251afb2019-03-29 14:19:02 -0700275TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) {
Patrick Williams641f7f22022-06-22 19:25:35 +0000276 NotPlacedOnTransactionQueue(/*flags*/ 0);
Valerie Haud251afb2019-03-29 14:19:02 -0700277}
278
Valerie Haud251afb2019-03-29 14:19:02 -0700279TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) {
Patrick Williams641f7f22022-06-22 19:25:35 +0000280 PlaceOnTransactionQueue(/*flags*/ 0);
Valerie Haud251afb2019-03-29 14:19:02 -0700281}
282
Valerie Hau09e60052019-12-15 14:51:15 -0800283TEST_F(TransactionApplicationTest, FromHandle) {
284 sp<IBinder> badHandle;
285 auto ret = mFlinger.fromHandle(badHandle);
Vishnu Nair07e2a482022-10-18 19:18:16 +0000286 EXPECT_EQ(nullptr, ret.get());
Valerie Hau09e60052019-12-15 14:51:15 -0800287}
ramindani4d48f902021-09-20 21:07:45 +0000288
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700289class FakeExternalTexture : public renderengine::ExternalTexture {
290 const sp<GraphicBuffer> mEmptyBuffer = nullptr;
291 uint32_t mWidth;
292 uint32_t mHeight;
293 uint64_t mId;
294 PixelFormat mPixelFormat;
295 uint64_t mUsage;
296
297public:
298 FakeExternalTexture(BufferData& bufferData)
299 : mWidth(bufferData.getWidth()),
300 mHeight(bufferData.getHeight()),
301 mId(bufferData.getId()),
302 mPixelFormat(bufferData.getPixelFormat()),
303 mUsage(bufferData.getUsage()) {}
304 const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
305 bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
306 return getId() == other.getId();
307 }
308 uint32_t getWidth() const override { return mWidth; }
309 uint32_t getHeight() const override { return mHeight; }
310 uint64_t getId() const override { return mId; }
311 PixelFormat getPixelFormat() const override { return mPixelFormat; }
312 uint64_t getUsage() const override { return mUsage; }
313 void remapBuffer() override {}
314 ~FakeExternalTexture() = default;
315};
316
Patrick Williams1cd73f82023-07-31 15:54:48 -0500317TEST_F(TransactionApplicationTest, ApplyTokensUseDifferentQueues) {
318 auto applyToken1 = sp<BBinder>::make();
319 auto applyToken2 = sp<BBinder>::make();
320
321 // Transaction 1 has a buffer with an unfired fence. It should not be ready to be applied.
322 TransactionState transaction1;
323 transaction1.applyToken = applyToken1;
324 transaction1.id = 42069;
325 transaction1.states.emplace_back();
326 transaction1.states[0].state.what |= layer_state_t::eBufferChanged;
327 transaction1.states[0].state.bufferData =
328 std::make_shared<fake::BufferData>(/* bufferId */ 1, /* width */ 1, /* height */ 1,
329 /* pixelFormat */ 0, /* outUsage */ 0);
Vishnu Nair0a51a872024-07-22 23:08:39 +0000330 mFlinger.addLayer(1);
331 bool out;
332 mFlinger.updateLayerSnapshots(VsyncId{1}, 0, /* transactionsFlushed */ true, out);
Patrick Williams1cd73f82023-07-31 15:54:48 -0500333 transaction1.states[0].externalTexture =
334 std::make_shared<FakeExternalTexture>(*transaction1.states[0].state.bufferData);
Vishnu Nair0a51a872024-07-22 23:08:39 +0000335 transaction1.states[0].state.surface = mFlinger.getLegacyLayer(1)->getHandle();
Patrick Williams1cd73f82023-07-31 15:54:48 -0500336 auto fence = sp<mock::MockFence>::make();
337 EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(Fence::Status::Unsignaled));
338 transaction1.states[0].state.bufferData->acquireFence = std::move(fence);
339 transaction1.states[0].state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
Vishnu Nair0a51a872024-07-22 23:08:39 +0000340 transaction1.states[0].layerId = 1;
Patrick Williams1cd73f82023-07-31 15:54:48 -0500341 transaction1.isAutoTimestamp = true;
342
343 // Transaction 2 should be ready to be applied.
344 TransactionState transaction2;
345 transaction2.applyToken = applyToken2;
346 transaction2.id = 2;
347 transaction2.isAutoTimestamp = true;
348
349 mFlinger.setTransactionStateInternal(transaction1);
350 mFlinger.setTransactionStateInternal(transaction2);
351 mFlinger.flushTransactionQueues();
352 auto transactionQueues = mFlinger.getPendingTransactionQueue();
353
354 // Transaction 1 is still in its queue.
355 EXPECT_EQ(transactionQueues[applyToken1].size(), 1u);
356 // Transaction 2 has been dequeued.
357 EXPECT_EQ(transactionQueues[applyToken2].size(), 0u);
358}
359
Ady Abraham9dada822022-02-03 10:26:59 -0800360class LatchUnsignaledTest : public TransactionApplicationTest {
361public:
362 void TearDown() override {
363 // Clear all transaction queues to release all transactions we sent
364 // in the tests. Otherwise, gmock complains about memory leaks.
Vishnu Nair60d902e2022-07-20 02:55:37 +0000365 while (!mFlinger.getTransactionQueue().isEmpty()) {
366 mFlinger.getTransactionQueue().pop();
367 }
Ady Abraham9dada822022-02-03 10:26:59 -0800368 mFlinger.getPendingTransactionQueue().clear();
Ady Abraham9dada822022-02-03 10:26:59 -0800369 mFlinger.commitTransactionsLocked(eTransactionMask);
Vishnu Nair0a51a872024-07-22 23:08:39 +0000370 mFlinger.destroyAllLayerHandles();
Ady Abraham9dada822022-02-03 10:26:59 -0800371 }
372
373 static sp<Fence> fence(Fence::Status status) {
374 const auto fence = sp<mock::MockFence>::make();
375 EXPECT_CALL(*fence, getStatus()).WillRepeatedly(Return(status));
376 return fence;
377 }
378
Vishnu Nair0a51a872024-07-22 23:08:39 +0000379 ComposerState createComposerState(int layerId, sp<Fence> fence, uint64_t what) {
Ady Abraham9dada822022-02-03 10:26:59 -0800380 ComposerState state;
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700381 state.state.bufferData =
382 std::make_shared<fake::BufferData>(/* bufferId */ 123L, /* width */ 1,
383 /* height */ 2, /* pixelFormat */ 0,
384 /* outUsage */ 0);
Ady Abraham9dada822022-02-03 10:26:59 -0800385 state.state.bufferData->acquireFence = std::move(fence);
386 state.state.layerId = layerId;
Ady Abraham9dada822022-02-03 10:26:59 -0800387 state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
388
389 state.state.what = what;
390 if (what & layer_state_t::eCropChanged) {
391 state.state.crop = Rect(1, 2, 3, 4);
392 }
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000393 if (what & layer_state_t::eFlagsChanged) {
394 state.state.flags = layer_state_t::eEnableBackpressure;
395 state.state.mask = layer_state_t::eEnableBackpressure;
396 }
397
Ady Abraham9dada822022-02-03 10:26:59 -0800398 return state;
399 }
400
401 TransactionInfo createTransactionInfo(const sp<IBinder>& applyToken,
402 const std::vector<ComposerState>& states) {
403 TransactionInfo transaction;
Vishnu Nair1523dad2022-09-29 16:05:18 -0700404 const uint32_t kFlags = 0;
Ady Abraham9dada822022-02-03 10:26:59 -0800405 const nsecs_t kDesiredPresentTime = systemTime();
406 const bool kIsAutoTimestamp = true;
407 const auto kFrameTimelineInfo = FrameTimelineInfo{};
408
Patrick Williams641f7f22022-06-22 19:25:35 +0000409 setupSingle(transaction, kFlags, kDesiredPresentTime, kIsAutoTimestamp, kFrameTimelineInfo);
Ady Abraham9dada822022-02-03 10:26:59 -0800410 transaction.applyToken = applyToken;
411 for (const auto& state : states) {
412 transaction.states.push_back(state);
413 }
414
415 return transaction;
416 }
417
418 void setTransactionStates(const std::vector<TransactionInfo>& transactions,
Ady Abraham9dada822022-02-03 10:26:59 -0800419 size_t expectedTransactionsPending) {
Vishnu Nair60d902e2022-07-20 02:55:37 +0000420 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Ady Abraham9dada822022-02-03 10:26:59 -0800421 EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size());
Vishnu Nair0a51a872024-07-22 23:08:39 +0000422 std::unordered_set<uint32_t> createdLayers;
423 for (auto transaction : transactions) {
424 for (auto& state : transaction.states) {
425 auto layerId = static_cast<uint32_t>(state.state.layerId);
426 if (createdLayers.find(layerId) == createdLayers.end()) {
427 mFlinger.addLayer(layerId);
428 createdLayers.insert(layerId);
429 }
430 }
431 }
432 bool unused;
433 bool mustComposite = mFlinger.updateLayerSnapshots(VsyncId{1}, /*frameTimeNs=*/0,
434 /*transactionsFlushed=*/true, unused);
Ady Abraham9dada822022-02-03 10:26:59 -0800435
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000436 for (auto transaction : transactions) {
437 std::vector<ResolvedComposerState> resolvedStates;
438 resolvedStates.reserve(transaction.states.size());
439 for (auto& state : transaction.states) {
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700440 ResolvedComposerState resolvedState;
441 resolvedState.state = std::move(state.state);
442 resolvedState.externalTexture =
443 std::make_shared<FakeExternalTexture>(*resolvedState.state.bufferData);
Vishnu Nair0a51a872024-07-22 23:08:39 +0000444 resolvedState.layerId = static_cast<uint32_t>(state.state.layerId);
445 resolvedState.state.surface =
446 mFlinger.getLegacyLayer(resolvedState.layerId)->getHandle();
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700447 resolvedStates.emplace_back(resolvedState);
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000448 }
449
450 TransactionState transactionState(transaction.frameTimelineInfo, resolvedStates,
451 transaction.displays, transaction.flags,
452 transaction.applyToken,
453 transaction.inputWindowCommands,
454 transaction.desiredPresentTime,
Chavi Weingartenc78f53c2023-04-14 18:50:53 +0000455 transaction.isAutoTimestamp, {}, systemTime(),
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000456 mHasListenerCallbacks, mCallbacks, getpid(),
Pablo Gamito23780be2023-04-18 08:30:00 +0000457 static_cast<int>(getuid()), transaction.id,
458 transaction.mergedTransactionIds);
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000459 mFlinger.setTransactionStateInternal(transactionState);
Ady Abraham9dada822022-02-03 10:26:59 -0800460 }
461 mFlinger.flushTransactionQueues();
Vishnu Nair60d902e2022-07-20 02:55:37 +0000462 EXPECT_TRUE(mFlinger.getTransactionQueue().isEmpty());
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700463 EXPECT_EQ(expectedTransactionsPending, mFlinger.getPendingTransactionCount());
Ady Abraham9dada822022-02-03 10:26:59 -0800464 }
465};
466
467class LatchUnsignaledAutoSingleLayerTest : public LatchUnsignaledTest {
468public:
469 void SetUp() override {
470 LatchUnsignaledTest::SetUp();
471 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::AutoSingleLayer;
472 }
473};
474
475TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleSignaledFromTheQueue) {
476 const sp<IBinder> kApplyToken =
477 IInterface::asBinder(TransactionCompletedListener::getIInstance());
Vishnu Nair0a51a872024-07-22 23:08:39 +0000478 const auto kLayerId = 10;
Ady Abraham9dada822022-02-03 10:26:59 -0800479 const auto kExpectedTransactionsPending = 0u;
Ady Abraham9dada822022-02-03 10:26:59 -0800480 const auto signaledTransaction =
481 createTransactionInfo(kApplyToken,
482 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
483 layer_state_t::eBufferChanged)});
Vishnu Nair1523dad2022-09-29 16:05:18 -0700484 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000485}
486
Ady Abraham9dada822022-02-03 10:26:59 -0800487TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSingleUnSignaledFromTheQueue) {
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 = 0u;
492
493 const auto unsignaledTransaction =
494 createTransactionInfo(kApplyToken,
495 {
496 createComposerState(kLayerId,
497 fence(Fence::Status::Unsignaled),
498 layer_state_t::eBufferChanged),
499 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700500 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000501}
502
Ady Abraham9dada822022-02-03 10:26:59 -0800503TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange) {
504 const sp<IBinder> kApplyToken =
505 IInterface::asBinder(TransactionCompletedListener::getIInstance());
506 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800507 const auto kExpectedTransactionsPending = 1u;
508
509 const auto unsignaledTransaction =
510 createTransactionInfo(kApplyToken,
511 {
512 createComposerState(kLayerId,
513 fence(Fence::Status::Unsignaled),
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700514 layer_state_t::eCropChanged |
515 layer_state_t::
516 eBufferChanged),
Ady Abraham9dada822022-02-03 10:26:59 -0800517 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700518 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000519}
520
Ady Abrahambb1ad762024-03-27 18:31:28 -0700521TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_AutoRefreshChanged) {
522 SET_FLAG_FOR_TEST(flags::latch_unsignaled_with_auto_refresh_changed, false);
523 const sp<IBinder> kApplyToken =
524 IInterface::asBinder(TransactionCompletedListener::getIInstance());
525 const auto kLayerId = 1;
526 const auto kExpectedTransactionsPending = 1u;
527
528 const auto unsignaledTransaction =
529 createTransactionInfo(kApplyToken,
530 {
531 createComposerState(kLayerId,
532 fence(Fence::Status::Unsignaled),
533 layer_state_t::eAutoRefreshChanged |
534 layer_state_t::
535 eBufferChanged),
536 });
537 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
538}
539
540TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesUnSignaledInTheQueue_AutoRefreshChanged) {
541 SET_FLAG_FOR_TEST(flags::latch_unsignaled_with_auto_refresh_changed, true);
542 const sp<IBinder> kApplyToken =
543 IInterface::asBinder(TransactionCompletedListener::getIInstance());
544 const auto kLayerId = 1;
545 const auto kExpectedTransactionsPending = 0u;
546
547 const auto unsignaledTransaction =
548 createTransactionInfo(kApplyToken,
549 {
550 createComposerState(kLayerId,
551 fence(Fence::Status::Unsignaled),
552 layer_state_t::eAutoRefreshChanged |
553 layer_state_t::
554 eBufferChanged),
555 });
556 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
557}
558
Ady Abraham9dada822022-02-03 10:26:59 -0800559TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed) {
560 const sp<IBinder> kApplyToken =
561 IInterface::asBinder(TransactionCompletedListener::getIInstance());
562 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800563 const auto kExpectedTransactionsPending = 1u;
564
565 const auto unsignaledTransaction =
566 createTransactionInfo(kApplyToken,
567 {
568 createComposerState(kLayerId,
569 fence(Fence::Status::Unsignaled),
570 layer_state_t::eCropChanged |
571 layer_state_t::
572 eBufferChanged),
573 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700574 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000575}
576
Ady Abraham9dada822022-02-03 10:26:59 -0800577TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueueSameApplyTokenMultiState) {
578 const sp<IBinder> kApplyToken =
579 IInterface::asBinder(TransactionCompletedListener::getIInstance());
580 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800581 const auto kExpectedTransactionsPending = 1u;
582
583 const auto mixedTransaction =
584 createTransactionInfo(kApplyToken,
585 {
586 createComposerState(kLayerId,
587 fence(Fence::Status::Unsignaled),
588 layer_state_t::eBufferChanged),
589 createComposerState(kLayerId,
590 fence(Fence::Status::Signaled),
591 layer_state_t::eBufferChanged),
592 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700593 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000594}
595
Ady Abraham9dada822022-02-03 10:26:59 -0800596TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsInTheQueue_MultipleStateTransaction) {
597 const sp<IBinder> kApplyToken =
598 IInterface::asBinder(TransactionCompletedListener::getIInstance());
599 const auto kLayerId1 = 1;
600 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800601 const auto kExpectedTransactionsPending = 1u;
602
603 const auto mixedTransaction =
604 createTransactionInfo(kApplyToken,
605 {
606 createComposerState(kLayerId1,
607 fence(Fence::Status::Unsignaled),
608 layer_state_t::eBufferChanged),
609 createComposerState(kLayerId2,
610 fence(Fence::Status::Signaled),
611 layer_state_t::eBufferChanged),
612 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700613 setTransactionStates({mixedTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000614}
615
Ady Abraham9dada822022-02-03 10:26:59 -0800616TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_RemovesSignaledFromTheQueue) {
617 const sp<IBinder> kApplyToken =
618 IInterface::asBinder(TransactionCompletedListener::getIInstance());
619 const auto kLayerId1 = 1;
620 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800621 const auto kExpectedTransactionsPending = 0u;
622
623 const auto signaledTransaction =
624 createTransactionInfo(kApplyToken,
625 {
626 createComposerState(kLayerId1,
627 fence(Fence::Status::Signaled),
628 layer_state_t::eBufferChanged),
629 });
630 const auto signaledTransaction2 =
631 createTransactionInfo(kApplyToken,
632 {
633 createComposerState(kLayerId2,
634 fence(Fence::Status::Signaled),
635 layer_state_t::eBufferChanged),
636 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700637 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000638}
639
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800640TEST_F(LatchUnsignaledAutoSingleLayerTest,
641 UnsignaledNotAppliedWhenThereAreSignaled_UnsignaledFirst) {
Ady Abraham9dada822022-02-03 10:26:59 -0800642 const sp<IBinder> kApplyToken1 =
643 IInterface::asBinder(TransactionCompletedListener::getIInstance());
644 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800645 const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
Ady Abraham9dada822022-02-03 10:26:59 -0800646 const auto kLayerId1 = 1;
647 const auto kLayerId2 = 2;
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800648 const auto kExpectedTransactionsPending = 1u;
649
650 const auto unsignaledTransaction =
651 createTransactionInfo(kApplyToken1,
652 {
653 createComposerState(kLayerId1,
654 fence(Fence::Status::Unsignaled),
655 layer_state_t::eBufferChanged),
656 });
657
658 const auto signaledTransaction =
659 createTransactionInfo(kApplyToken2,
660 {
661 createComposerState(kLayerId2,
662 fence(Fence::Status::Signaled),
663 layer_state_t::eBufferChanged),
664 });
665 const auto signaledTransaction2 =
666 createTransactionInfo(kApplyToken3,
667 {
668 createComposerState(kLayerId2,
669 fence(Fence::Status::Signaled),
670 layer_state_t::eBufferChanged),
671 });
672
673 setTransactionStates({unsignaledTransaction, signaledTransaction, signaledTransaction2},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700674 kExpectedTransactionsPending);
Ady Abrahame1bfaac2022-02-22 21:32:08 -0800675}
676
Ady Abraham9dada822022-02-03 10:26:59 -0800677TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueueSameApplyToken) {
678 const sp<IBinder> kApplyToken =
679 IInterface::asBinder(TransactionCompletedListener::getIInstance());
680 const auto kLayerId1 = 1;
681 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800682 const auto kExpectedTransactionsPending = 1u;
683
684 const auto unsignaledTransaction =
685 createTransactionInfo(kApplyToken,
686 {
687 createComposerState(kLayerId1,
688 fence(Fence::Status::Unsignaled),
689 layer_state_t::eBufferChanged),
690 });
691 const auto signaledTransaction =
692 createTransactionInfo(kApplyToken,
693 {
694 createComposerState(kLayerId2,
695 fence(Fence::Status::Signaled),
696 layer_state_t::eBufferChanged),
697 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700698 setTransactionStates({unsignaledTransaction, signaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800699 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000700}
701
Ady Abraham9dada822022-02-03 10:26:59 -0800702TEST_F(LatchUnsignaledAutoSingleLayerTest, Flush_KeepsTransactionInTheQueue) {
703 const sp<IBinder> kApplyToken1 =
704 IInterface::asBinder(TransactionCompletedListener::getIInstance());
705 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
706 const auto kLayerId1 = 1;
707 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800708 const auto kExpectedTransactionsPending = 1u;
709
710 const auto unsignaledTransaction =
711 createTransactionInfo(kApplyToken1,
712 {
713 createComposerState(kLayerId1,
714 fence(Fence::Status::Unsignaled),
715 layer_state_t::eBufferChanged),
716 });
717 const auto unsignaledTransaction2 =
718 createTransactionInfo(kApplyToken2,
719 {
720 createComposerState(kLayerId2,
721 fence(Fence::Status::Unsignaled),
722 layer_state_t::eBufferChanged),
723 });
724 setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700725 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000726}
727
Ady Abraham2739e832022-02-14 17:42:00 -0800728TEST_F(LatchUnsignaledAutoSingleLayerTest, DontLatchUnsignaledWhenEarlyOffset) {
729 const sp<IBinder> kApplyToken =
730 IInterface::asBinder(TransactionCompletedListener::getIInstance());
731 const auto kLayerId = 1;
Ady Abraham2739e832022-02-14 17:42:00 -0800732 const auto kExpectedTransactionsPending = 1u;
733
734 const auto unsignaledTransaction =
735 createTransactionInfo(kApplyToken,
736 {
737 createComposerState(kLayerId,
738 fence(Fence::Status::Unsignaled),
739 layer_state_t::eBufferChanged),
740 });
741
Dominik Laskowski1c99a002023-01-20 17:10:36 -0500742 modulateVsync();
Vishnu Nair1523dad2022-09-29 16:05:18 -0700743 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
Ady Abraham2739e832022-02-14 17:42:00 -0800744}
745
Vishnu Nairf01a6f12023-04-03 22:34:17 +0000746TEST_F(LatchUnsignaledAutoSingleLayerTest, UnsignaledNotAppliedWhenThereAreSignaled_SignaledFirst) {
747 const sp<IBinder> kApplyToken1 =
748 IInterface::asBinder(TransactionCompletedListener::getIInstance());
749 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
750 const sp<IBinder> kApplyToken3 = sp<BBinder>::make();
751 const auto kLayerId1 = 1;
752 const auto kLayerId2 = 2;
753 const auto kExpectedTransactionsPending = 1u;
754
755 const auto signaledTransaction =
756 createTransactionInfo(kApplyToken1,
757 {
758 createComposerState(kLayerId1,
759 fence(Fence::Status::Signaled),
760 layer_state_t::eBufferChanged),
761 });
762 const auto signaledTransaction2 =
763 createTransactionInfo(kApplyToken2,
764 {
765 createComposerState(kLayerId1,
766 fence(Fence::Status::Signaled),
767 layer_state_t::eBufferChanged),
768 });
769 const auto unsignaledTransaction =
770 createTransactionInfo(kApplyToken3,
771 {
772 createComposerState(kLayerId2,
773 fence(Fence::Status::Unsignaled),
774 layer_state_t::eBufferChanged),
775 });
776
777 setTransactionStates({signaledTransaction, signaledTransaction2, unsignaledTransaction},
778 kExpectedTransactionsPending);
779}
780
Ady Abraham9dada822022-02-03 10:26:59 -0800781class LatchUnsignaledDisabledTest : public LatchUnsignaledTest {
782public:
783 void SetUp() override {
784 LatchUnsignaledTest::SetUp();
785 SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled;
786 }
787};
788
789TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue) {
790 const sp<IBinder> kApplyToken =
791 IInterface::asBinder(TransactionCompletedListener::getIInstance());
Vishnu Nair0a51a872024-07-22 23:08:39 +0000792 const auto kLayerId = 10;
Ady Abraham9dada822022-02-03 10:26:59 -0800793 const auto kExpectedTransactionsPending = 0u;
794
795 const auto signaledTransaction =
796 createTransactionInfo(kApplyToken,
797 {createComposerState(kLayerId, fence(Fence::Status::Signaled),
798 layer_state_t::eBufferChanged)});
Vishnu Nair1523dad2022-09-29 16:05:18 -0700799 setTransactionStates({signaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000800}
801
Ady Abraham9dada822022-02-03 10:26:59 -0800802TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueue) {
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 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700815 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000816}
817
Ady Abraham9dada822022-02-03 10:26:59 -0800818TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueSameLayerId) {
819 const sp<IBinder> kApplyToken =
820 IInterface::asBinder(TransactionCompletedListener::getIInstance());
821 const auto kLayerId = 1;
Ady Abraham9dada822022-02-03 10:26:59 -0800822 const auto kExpectedTransactionsPending = 1u;
823
824 const auto unsignaledTransaction =
825 createTransactionInfo(kApplyToken,
826 {
827 createComposerState(kLayerId,
828 fence(Fence::Status::Unsignaled),
829 layer_state_t::eBufferChanged),
830 createComposerState(kLayerId,
831 fence(Fence::Status::Unsignaled),
832 layer_state_t::eBufferChanged),
833 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700834 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000835}
836
Ady Abraham9dada822022-02-03 10:26:59 -0800837TEST_F(LatchUnsignaledDisabledTest, Flush_KeepsInTheQueueDifferentLayerId) {
838 const sp<IBinder> kApplyToken =
839 IInterface::asBinder(TransactionCompletedListener::getIInstance());
840 const auto kLayerId1 = 1;
841 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800842 const auto kExpectedTransactionsPending = 1u;
843
844 const auto unsignaledTransaction =
845 createTransactionInfo(kApplyToken,
846 {
847 createComposerState(kLayerId1,
848 fence(Fence::Status::Unsignaled),
849 layer_state_t::eBufferChanged),
850 createComposerState(kLayerId2,
851 fence(Fence::Status::Unsignaled),
852 layer_state_t::eBufferChanged),
853 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700854 setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000855}
856
Ady Abraham9dada822022-02-03 10:26:59 -0800857TEST_F(LatchUnsignaledDisabledTest, Flush_RemovesSignaledFromTheQueue_MultipleLayers) {
858 const sp<IBinder> kApplyToken =
859 IInterface::asBinder(TransactionCompletedListener::getIInstance());
860 const auto kLayerId1 = 1;
861 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800862 const auto kExpectedTransactionsPending = 0u;
863
864 const auto signaledTransaction =
865 createTransactionInfo(kApplyToken,
866 {
867 createComposerState(kLayerId1,
868 fence(Fence::Status::Signaled),
869 layer_state_t::eBufferChanged),
870 });
871 const auto signaledTransaction2 =
872 createTransactionInfo(kApplyToken,
873 {
874 createComposerState(kLayerId2,
875 fence(Fence::Status::Signaled),
876 layer_state_t::eBufferChanged),
877 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700878 setTransactionStates({signaledTransaction, signaledTransaction2}, kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000879}
880
Ady Abraham9dada822022-02-03 10:26:59 -0800881TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueDifferentApplyToken) {
882 const sp<IBinder> kApplyToken1 =
883 IInterface::asBinder(TransactionCompletedListener::getIInstance());
884 const sp<IBinder> kApplyToken2 = sp<BBinder>::make();
885 const auto kLayerId1 = 1;
886 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800887 const auto kExpectedTransactionsPending = 1u;
888
889 const auto unsignaledTransaction =
890 createTransactionInfo(kApplyToken1,
891 {
892 createComposerState(kLayerId1,
893 fence(Fence::Status::Unsignaled),
894 layer_state_t::eBufferChanged),
895 });
896 const auto signaledTransaction =
897 createTransactionInfo(kApplyToken2,
898 {
899 createComposerState(kLayerId2,
900 fence(Fence::Status::Signaled),
901 layer_state_t::eBufferChanged),
902 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700903 setTransactionStates({unsignaledTransaction, signaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800904 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000905}
906
Ady Abraham9dada822022-02-03 10:26:59 -0800907TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheQueueSameApplyToken) {
908 const sp<IBinder> kApplyToken =
909 IInterface::asBinder(TransactionCompletedListener::getIInstance());
910 const auto kLayerId1 = 1;
911 const auto kLayerId2 = 2;
Ady Abraham9dada822022-02-03 10:26:59 -0800912 const auto kExpectedTransactionsPending = 1u;
913
914 const auto signaledTransaction =
915 createTransactionInfo(kApplyToken,
916 {
917 createComposerState(kLayerId1,
918 fence(Fence::Status::Signaled),
919 layer_state_t::eBufferChanged),
920 });
921 const auto unsignaledTransaction =
922 createTransactionInfo(kApplyToken,
923 {
924 createComposerState(kLayerId2,
925 fence(Fence::Status::Unsignaled),
926 layer_state_t::eBufferChanged),
927 });
Vishnu Nair1523dad2022-09-29 16:05:18 -0700928 setTransactionStates({signaledTransaction, unsignaledTransaction},
Ady Abraham9dada822022-02-03 10:26:59 -0800929 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000930}
931
Ady Abraham9dada822022-02-03 10:26:59 -0800932TEST_F(LatchUnsignaledDisabledTest, Flush_KeepInTheUnsignaledTheQueue) {
933 const sp<IBinder> kApplyToken =
934 IInterface::asBinder(TransactionCompletedListener::getIInstance());
935 const auto kLayerId1 = 1;
936 const auto kLayerId2 = 2;
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700937 const auto kExpectedTransactionsPending = 2u;
Ady Abraham9dada822022-02-03 10:26:59 -0800938
939 const auto unsignaledTransaction =
940 createTransactionInfo(kApplyToken,
941 {
942 createComposerState(kLayerId1,
943 fence(Fence::Status::Unsignaled),
944 layer_state_t::eBufferChanged),
945 });
946 const auto unsignaledTransaction2 =
947 createTransactionInfo(kApplyToken,
948 {
949 createComposerState(kLayerId2,
950 fence(Fence::Status::Unsignaled),
951 layer_state_t::eBufferChanged),
952 });
953 setTransactionStates({unsignaledTransaction, unsignaledTransaction2},
Vishnu Nair1523dad2022-09-29 16:05:18 -0700954 kExpectedTransactionsPending);
ramindani4d48f902021-09-20 21:07:45 +0000955}
956
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700957TEST(TransactionHandlerTest, QueueTransaction) {
958 TransactionHandler handler;
959 TransactionState transaction;
960 transaction.applyToken = sp<BBinder>::make();
961 transaction.id = 42;
962 handler.queueTransaction(std::move(transaction));
Vishnu Nair4d9cef92023-06-24 22:34:41 +0000963 handler.collectTransactions();
Vishnu Nair59f6d2d2022-10-05 16:59:56 -0700964 std::vector<TransactionState> transactionsReadyToBeApplied = handler.flushTransactions();
965
966 EXPECT_EQ(transactionsReadyToBeApplied.size(), 1u);
967 EXPECT_EQ(transactionsReadyToBeApplied.front().id, 42u);
968}
969
Pablo Gamito23780be2023-04-18 08:30:00 +0000970TEST(TransactionHandlerTest, TransactionsKeepTrackOfDirectMerges) {
971 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3, transaction4;
972
973 uint64_t transaction2Id = transaction2.getId();
974 uint64_t transaction3Id = transaction3.getId();
975 EXPECT_NE(transaction2Id, transaction3Id);
976
977 transaction1.merge(std::move(transaction2));
978 transaction1.merge(std::move(transaction3));
979
980 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 2u);
981 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction3Id);
982 EXPECT_EQ(transaction1.getMergedTransactionIds()[1], transaction2Id);
983}
984
985TEST(TransactionHandlerTest, TransactionsKeepTrackOfIndirectMerges) {
986 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3, transaction4;
987
988 uint64_t transaction2Id = transaction2.getId();
989 uint64_t transaction3Id = transaction3.getId();
990 uint64_t transaction4Id = transaction4.getId();
991 EXPECT_NE(transaction2Id, transaction3Id);
992 EXPECT_NE(transaction2Id, transaction4Id);
993 EXPECT_NE(transaction3Id, transaction4Id);
994
995 transaction4.merge(std::move(transaction2));
996 transaction4.merge(std::move(transaction3));
997
998 EXPECT_EQ(transaction4.getMergedTransactionIds().size(), 2u);
999 EXPECT_EQ(transaction4.getMergedTransactionIds()[0], transaction3Id);
1000 EXPECT_EQ(transaction4.getMergedTransactionIds()[1], transaction2Id);
1001
1002 transaction1.merge(std::move(transaction4));
1003
1004 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 3u);
1005 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction4Id);
1006 EXPECT_EQ(transaction1.getMergedTransactionIds()[1], transaction3Id);
1007 EXPECT_EQ(transaction1.getMergedTransactionIds()[2], transaction2Id);
1008}
1009
1010TEST(TransactionHandlerTest, TransactionMergesAreCleared) {
1011 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3;
1012
1013 transaction1.merge(std::move(transaction2));
1014 transaction1.merge(std::move(transaction3));
1015
1016 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 2u);
1017
1018 transaction1.clear();
1019
1020 EXPECT_EQ(transaction1.getMergedTransactionIds().empty(), true);
1021}
1022
1023TEST(TransactionHandlerTest, TransactionMergesAreCapped) {
1024 SurfaceComposerClient::Transaction transaction;
1025 std::vector<uint64_t> mergedTransactionIds;
1026
1027 for (uint i = 0; i < 20u; i++) {
1028 SurfaceComposerClient::Transaction transactionToMerge;
1029 mergedTransactionIds.push_back(transactionToMerge.getId());
1030 transaction.merge(std::move(transactionToMerge));
1031 }
1032
1033 // Keeps latest 10 merges in order of merge recency
1034 EXPECT_EQ(transaction.getMergedTransactionIds().size(), 10u);
1035 for (uint i = 0; i < 10u; i++) {
1036 EXPECT_EQ(transaction.getMergedTransactionIds()[i],
1037 mergedTransactionIds[mergedTransactionIds.size() - 1 - i]);
1038 }
1039}
1040
1041TEST(TransactionHandlerTest, KeepsMergesFromMoreRecentMerge) {
1042 SurfaceComposerClient::Transaction transaction1, transaction2, transaction3;
1043 std::vector<uint64_t> mergedTransactionIds1, mergedTransactionIds2, mergedTransactionIds3;
1044 uint64_t transaction2Id = transaction2.getId();
1045 uint64_t transaction3Id = transaction3.getId();
1046
1047 for (uint i = 0; i < 20u; i++) {
1048 SurfaceComposerClient::Transaction transactionToMerge;
1049 mergedTransactionIds1.push_back(transactionToMerge.getId());
1050 transaction1.merge(std::move(transactionToMerge));
1051 }
1052
1053 for (uint i = 0; i < 5u; i++) {
1054 SurfaceComposerClient::Transaction transactionToMerge;
1055 mergedTransactionIds2.push_back(transactionToMerge.getId());
1056 transaction2.merge(std::move(transactionToMerge));
1057 }
1058
1059 transaction1.merge(std::move(transaction2));
1060 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1061 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction2Id);
1062 for (uint i = 0; i < 5u; i++) {
1063 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 1u],
1064 mergedTransactionIds2[mergedTransactionIds2.size() - 1 - i]);
1065 }
1066 for (uint i = 0; i < 4u; i++) {
1067 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 6u],
1068 mergedTransactionIds1[mergedTransactionIds1.size() - 1 - i]);
1069 }
1070
1071 for (uint i = 0; i < 20u; i++) {
1072 SurfaceComposerClient::Transaction transactionToMerge;
1073 mergedTransactionIds3.push_back(transactionToMerge.getId());
1074 transaction3.merge(std::move(transactionToMerge));
1075 }
1076
1077 transaction1.merge(std::move(transaction3));
1078 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1079 EXPECT_EQ(transaction1.getMergedTransactionIds()[0], transaction3Id);
1080 for (uint i = 0; i < 9u; i++) {
1081 EXPECT_EQ(transaction1.getMergedTransactionIds()[i + 1],
1082 mergedTransactionIds3[mergedTransactionIds3.size() - 1 - i]);
1083 }
1084}
1085
1086TEST(TransactionHandlerTest, CanAddTransactionWithFullMergedIds) {
1087 SurfaceComposerClient::Transaction transaction1, transaction2;
1088 for (uint i = 0; i < 20u; i++) {
1089 SurfaceComposerClient::Transaction transactionToMerge;
1090 transaction1.merge(std::move(transactionToMerge));
1091 }
1092
1093 EXPECT_EQ(transaction1.getMergedTransactionIds().size(), 10u);
1094
1095 auto transaction1Id = transaction1.getId();
1096 transaction2.merge(std::move(transaction1));
1097 EXPECT_EQ(transaction2.getMergedTransactionIds().size(), 10u);
1098 auto mergedTransactionIds = transaction2.getMergedTransactionIds();
1099 EXPECT_TRUE(std::count(mergedTransactionIds.begin(), mergedTransactionIds.end(),
1100 transaction1Id) > 0);
1101}
1102
Valerie Haud251afb2019-03-29 14:19:02 -07001103} // namespace android