blob: 82aac7e4bfa67f06429e90ba6756ec13064942e5 [file] [log] [blame]
Vishnu Nair7891e962021-11-11 12:07:21 -08001/*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gmock/gmock.h>
18#include <gtest/gtest.h>
19
20#include <gui/SurfaceComposerClient.h>
Vishnu Nair81750622023-03-08 15:02:06 -080021#include <cstdint>
22#include "Client.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080023
Vishnu Naircb565332023-03-14 21:10:55 -070024#include <layerproto/LayerProtoHeader.h>
Vishnu Nair81750622023-03-08 15:02:06 -080025#include "FrontEnd/LayerCreationArgs.h"
26#include "FrontEnd/Update.h"
Vishnu Naircb565332023-03-14 21:10:55 -070027#include "Tracing/LayerTracing.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080028#include "Tracing/RingBuffer.h"
29#include "Tracing/TransactionTracing.h"
30
31using namespace android::surfaceflinger;
32
33namespace android {
34
35class TransactionTracingTest : public testing::Test {
36protected:
Vishnu Nair0cc69e12021-11-18 09:05:49 -080037 static constexpr size_t SMALL_BUFFER_SIZE = 1024;
Dominik Laskowski46471e62022-01-14 15:34:03 -080038 TransactionTracing mTracing;
Vishnu Nair7891e962021-11-11 12:07:21 -080039
Dominik Laskowski46471e62022-01-14 15:34:03 -080040 void flush(int64_t vsyncId) { mTracing.flush(vsyncId); }
41 proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); }
Vishnu Nair7891e962021-11-11 12:07:21 -080042
Dominik Laskowski46471e62022-01-14 15:34:03 -080043 proto::TransactionTraceEntry bufferFront() {
44 std::scoped_lock<std::mutex> lock(mTracing.mTraceLock);
Vishnu Nair62863552021-12-10 13:34:48 -080045 proto::TransactionTraceEntry entry;
Dominik Laskowski46471e62022-01-14 15:34:03 -080046 entry.ParseFromString(mTracing.mBuffer.front());
Vishnu Nair62863552021-12-10 13:34:48 -080047 return entry;
Vishnu Nair7891e962021-11-11 12:07:21 -080048 }
49
Vishnu Nair0cc69e12021-11-18 09:05:49 -080050 void queueAndCommitTransaction(int64_t vsyncId) {
Vishnu Nair81750622023-03-08 15:02:06 -080051 frontend::Update update;
Vishnu Nair0cc69e12021-11-18 09:05:49 -080052 TransactionState transaction;
53 transaction.id = static_cast<uint64_t>(vsyncId * 3);
54 transaction.originUid = 1;
55 transaction.originPid = 2;
Dominik Laskowski46471e62022-01-14 15:34:03 -080056 mTracing.addQueuedTransaction(transaction);
Vishnu Nair0cc69e12021-11-18 09:05:49 -080057 std::vector<TransactionState> transactions;
Vishnu Nair81750622023-03-08 15:02:06 -080058 update.transactions.emplace_back(transaction);
59 mTracing.addCommittedTransactions(vsyncId, 0, update, {}, false);
Vishnu Nair0cc69e12021-11-18 09:05:49 -080060 flush(vsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -080061 }
62
Vishnu Nair7891e962021-11-11 12:07:21 -080063 void verifyEntry(const proto::TransactionTraceEntry& actualProto,
Dominik Laskowski46471e62022-01-14 15:34:03 -080064 const std::vector<TransactionState>& expectedTransactions,
Vishnu Nair7891e962021-11-11 12:07:21 -080065 int64_t expectedVsyncId) {
66 EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
Vishnu Nair81750622023-03-08 15:02:06 -080067 ASSERT_EQ(actualProto.transactions().size(),
Vishnu Nair7891e962021-11-11 12:07:21 -080068 static_cast<int32_t>(expectedTransactions.size()));
69 for (uint32_t i = 0; i < expectedTransactions.size(); i++) {
70 EXPECT_EQ(actualProto.transactions(static_cast<int32_t>(i)).pid(),
71 expectedTransactions[i].originPid);
72 }
73 }
Vishnu Nair81750622023-03-08 15:02:06 -080074
75 LayerCreationArgs getLayerCreationArgs(uint32_t layerId, uint32_t parentId,
76 uint32_t layerIdToMirror, uint32_t flags,
77 bool addToRoot) {
78 LayerCreationArgs args;
79 args.sequence = layerId;
80 args.parentId = parentId;
81 args.layerIdToMirror = layerIdToMirror;
82 args.flags = flags;
83 args.addToRoot = addToRoot;
84 return args;
85 }
Vishnu Nair7891e962021-11-11 12:07:21 -080086};
87
Vishnu Nair7891e962021-11-11 12:07:21 -080088TEST_F(TransactionTracingTest, addTransactions) {
Vishnu Nair7891e962021-11-11 12:07:21 -080089 std::vector<TransactionState> transactions;
90 transactions.reserve(100);
91 for (uint64_t i = 0; i < 100; i++) {
92 TransactionState transaction;
93 transaction.id = i;
94 transaction.originPid = static_cast<int32_t>(i);
95 transactions.emplace_back(transaction);
Dominik Laskowski46471e62022-01-14 15:34:03 -080096 mTracing.addQueuedTransaction(transaction);
Vishnu Nair7891e962021-11-11 12:07:21 -080097 }
98
99 // Split incoming transactions into two and commit them in reverse order to test out of order
100 // commits.
Vishnu Nair7891e962021-11-11 12:07:21 -0800101 int64_t firstTransactionSetVsyncId = 42;
Vishnu Nair81750622023-03-08 15:02:06 -0800102 frontend::Update firstUpdate;
103 firstUpdate.transactions =
104 std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
105 mTracing.addCommittedTransactions(firstTransactionSetVsyncId, 0, firstUpdate, {}, false);
Vishnu Nair7891e962021-11-11 12:07:21 -0800106
107 int64_t secondTransactionSetVsyncId = 43;
Vishnu Nair81750622023-03-08 15:02:06 -0800108 frontend::Update secondUpdate;
109 secondUpdate.transactions =
Vishnu Nair7891e962021-11-11 12:07:21 -0800110 std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50);
Vishnu Nair81750622023-03-08 15:02:06 -0800111 mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800112 flush(secondTransactionSetVsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800113
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800114 proto::TransactionTraceFile proto = writeToProto();
Vishnu Nair81750622023-03-08 15:02:06 -0800115 ASSERT_EQ(proto.entry().size(), 2);
116 verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId);
117 verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800118}
119
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800120class TransactionTracingLayerHandlingTest : public TransactionTracingTest {
121protected:
122 void SetUp() override {
Dominik Laskowski46471e62022-01-14 15:34:03 -0800123 mTracing.setBufferSize(SMALL_BUFFER_SIZE);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800124
Vishnu Nair81750622023-03-08 15:02:06 -0800125 // add layers and add some layer transaction
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800126 {
Vishnu Nair81750622023-03-08 15:02:06 -0800127 frontend::Update update;
128 update.layerCreationArgs.emplace_back(std::move(
129 getLayerCreationArgs(mParentLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
130 /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
131 /*addToRoot=*/true)));
132 update.layerCreationArgs.emplace_back(std::move(
133 getLayerCreationArgs(mChildLayerId, mParentLayerId,
134 /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/456,
135 /*addToRoot=*/true)));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800136 TransactionState transaction;
137 transaction.id = 50;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000138 ResolvedComposerState layerState;
Vishnu Nair81750622023-03-08 15:02:06 -0800139 layerState.layerId = mParentLayerId;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800140 layerState.state.what = layer_state_t::eLayerChanged;
141 layerState.state.z = 42;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000142 transaction.states.emplace_back(layerState);
143 ResolvedComposerState childState;
Vishnu Nair81750622023-03-08 15:02:06 -0800144 childState.layerId = mChildLayerId;
Vishnu Nair473838d2021-12-08 09:46:02 -0800145 childState.state.what = layer_state_t::eLayerChanged;
146 childState.state.z = 43;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000147 transaction.states.emplace_back(childState);
Dominik Laskowski46471e62022-01-14 15:34:03 -0800148 mTracing.addQueuedTransaction(transaction);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800149
Vishnu Nair81750622023-03-08 15:02:06 -0800150 update.transactions.emplace_back(transaction);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800151 VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId;
Vishnu Nair81750622023-03-08 15:02:06 -0800152 mTracing.addCommittedTransactions(VSYNC_ID_FIRST_LAYER_CHANGE, 0, update, {}, false);
153
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800154 flush(VSYNC_ID_FIRST_LAYER_CHANGE);
155 }
156
157 // add transactions that modify the layer state further so we can test that layer state
158 // gets merged
159 {
160 TransactionState transaction;
161 transaction.id = 51;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000162 ResolvedComposerState layerState;
Vishnu Nair81750622023-03-08 15:02:06 -0800163 layerState.layerId = mParentLayerId;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800164 layerState.state.what = layer_state_t::eLayerChanged | layer_state_t::ePositionChanged;
165 layerState.state.z = 41;
166 layerState.state.x = 22;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000167 transaction.states.emplace_back(layerState);
Dominik Laskowski46471e62022-01-14 15:34:03 -0800168 mTracing.addQueuedTransaction(transaction);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800169
Vishnu Nair81750622023-03-08 15:02:06 -0800170 frontend::Update update;
171 update.transactions.emplace_back(transaction);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800172 VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId;
Vishnu Nair81750622023-03-08 15:02:06 -0800173 mTracing.addCommittedTransactions(VSYNC_ID_SECOND_LAYER_CHANGE, 0, update, {}, false);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800174 flush(VSYNC_ID_SECOND_LAYER_CHANGE);
175 }
176
177 // remove child layer
Dominik Laskowski46471e62022-01-14 15:34:03 -0800178 mTracing.onLayerRemoved(2);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800179 VSYNC_ID_CHILD_LAYER_REMOVED = ++mVsyncId;
180 queueAndCommitTransaction(VSYNC_ID_CHILD_LAYER_REMOVED);
181
182 // remove layer
Dominik Laskowski46471e62022-01-14 15:34:03 -0800183 mTracing.onLayerRemoved(1);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800184 queueAndCommitTransaction(++mVsyncId);
185 }
186
Vishnu Nair81750622023-03-08 15:02:06 -0800187 uint32_t mParentLayerId = 1;
188 uint32_t mChildLayerId = 2;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800189 int64_t mVsyncId = 0;
190 int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
191 int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
192 int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
193};
194
195TEST_F(TransactionTracingLayerHandlingTest, addStartingState) {
196 // add transactions until we drop the transaction with the first layer change
197 while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) {
198 queueAndCommitTransaction(++mVsyncId);
199 }
200 proto::TransactionTraceFile proto = writeToProto();
201 // verify we can still retrieve the layer change from the first entry containing starting
202 // states.
203 EXPECT_GT(proto.entry().size(), 0);
Vishnu Nair685cfef2022-02-02 10:01:25 -0800204 EXPECT_EQ(proto.entry(0).transactions().size(), 1);
205 EXPECT_EQ(proto.entry(0).added_layers().size(), 2);
Vishnu Nair473838d2021-12-08 09:46:02 -0800206 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
207 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800208 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 42);
Vishnu Nair473838d2021-12-08 09:46:02 -0800209 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).layer_id(), mChildLayerId);
210 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800211}
212
213TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) {
214 // add transactions until we drop the transaction with the second layer change
215 while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
216 queueAndCommitTransaction(++mVsyncId);
217 }
218 proto::TransactionTraceFile proto = writeToProto();
219 // verify starting states are updated correctly
220 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41);
221}
222
223TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) {
224 // add transactions until we drop the transaction which removes the child layer
225 while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
226 queueAndCommitTransaction(++mVsyncId);
227 }
228 proto::TransactionTraceFile proto = writeToProto();
229 // verify the child layer has been removed from the trace
230 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
231 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
232}
233
234TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) {
235 // add transactions until we drop the transaction with the second layer change
236 while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
237 queueAndCommitTransaction(++mVsyncId);
238 }
239 proto::TransactionTraceFile proto = writeToProto();
240 // verify we have two starting states
241 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
242
243 // Continue adding transactions until child layer is removed
244 while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
245 queueAndCommitTransaction(++mVsyncId);
246 }
247 proto = writeToProto();
248 // verify we still have the parent layer state
249 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
250 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
251}
252
Vishnu Nair84125ac2021-12-02 08:47:48 -0800253class TransactionTracingMirrorLayerTest : public TransactionTracingTest {
254protected:
255 void SetUp() override {
Dominik Laskowski46471e62022-01-14 15:34:03 -0800256 mTracing.setBufferSize(SMALL_BUFFER_SIZE);
Vishnu Nair84125ac2021-12-02 08:47:48 -0800257
Vishnu Nair81750622023-03-08 15:02:06 -0800258 // add layers and some layer transaction
Vishnu Nair84125ac2021-12-02 08:47:48 -0800259 {
Vishnu Nair81750622023-03-08 15:02:06 -0800260 frontend::Update update;
261 update.layerCreationArgs.emplace_back(
262 getLayerCreationArgs(mLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
263 /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
264 /*addToRoot=*/true));
265 update.layerCreationArgs.emplace_back(
266 getLayerCreationArgs(mMirrorLayerId, UNASSIGNED_LAYER_ID,
267 /*layerIdToMirror=*/mLayerId, /*flags=*/0,
268 /*addToRoot=*/false));
269
Vishnu Nair84125ac2021-12-02 08:47:48 -0800270 TransactionState transaction;
271 transaction.id = 50;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000272 ResolvedComposerState layerState;
Vishnu Nair81750622023-03-08 15:02:06 -0800273 layerState.layerId = mLayerId;
Vishnu Nair84125ac2021-12-02 08:47:48 -0800274 layerState.state.what = layer_state_t::eLayerChanged;
275 layerState.state.z = 42;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000276 transaction.states.emplace_back(layerState);
277 ResolvedComposerState mirrorState;
Vishnu Nair81750622023-03-08 15:02:06 -0800278 mirrorState.layerId = mMirrorLayerId;
Vishnu Nair84125ac2021-12-02 08:47:48 -0800279 mirrorState.state.what = layer_state_t::eLayerChanged;
280 mirrorState.state.z = 43;
Vishnu Nair40fff5c2022-11-04 02:46:28 +0000281 transaction.states.emplace_back(mirrorState);
Dominik Laskowski46471e62022-01-14 15:34:03 -0800282 mTracing.addQueuedTransaction(transaction);
Vishnu Nair84125ac2021-12-02 08:47:48 -0800283
Vishnu Nair81750622023-03-08 15:02:06 -0800284 update.transactions.emplace_back(transaction);
285 mTracing.addCommittedTransactions(mVsyncId, 0, update, {}, false);
Vishnu Nair84125ac2021-12-02 08:47:48 -0800286 flush(mVsyncId);
287 }
288 }
289
Vishnu Nair81750622023-03-08 15:02:06 -0800290 uint32_t mLayerId = 5;
291 uint32_t mMirrorLayerId = 55;
Vishnu Nair84125ac2021-12-02 08:47:48 -0800292 int64_t mVsyncId = 0;
293 int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
294 int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
295 int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
296};
297
298TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) {
299 proto::TransactionTraceFile proto = writeToProto();
300 // We don't have any starting states since no layer was removed from.
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800301 EXPECT_EQ(proto.entry().size(), 1);
Vishnu Nair84125ac2021-12-02 08:47:48 -0800302
303 // Verify the mirror layer was added
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800304 EXPECT_EQ(proto.entry(0).transactions().size(), 1);
305 EXPECT_EQ(proto.entry(0).added_layers().size(), 2);
306 EXPECT_EQ(proto.entry(0).added_layers(1).layer_id(), mMirrorLayerId);
307 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
308 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
Vishnu Nair84125ac2021-12-02 08:47:48 -0800309}
Vishnu Naircb565332023-03-14 21:10:55 -0700310
311// Verify we can write the layers traces by entry to reduce mem pressure
312// on the system when generating large traces.
313TEST(LayerTraceTest, canStreamLayersTrace) {
314 LayersTraceFileProto inProto = LayerTracing::createTraceFileProto();
315 inProto.add_entry();
316 inProto.add_entry();
317
318 std::string output;
319 inProto.SerializeToString(&output);
320 LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto();
321 inProto2.add_entry();
322 std::string output2;
323 inProto2.SerializeToString(&output2);
324
325 LayersTraceFileProto outProto;
326 outProto.ParseFromString(output + output2);
327 // magic?
328 EXPECT_EQ(outProto.entry().size(), 3);
329}
Vishnu Nair7891e962021-11-11 12:07:21 -0800330} // namespace android