• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
21 #include <cstdint>
22 #include "Client.h"
23 #include "Layer.h"
24 
25 #include <layerproto/LayerProtoHeader.h>
26 #include "FrontEnd/LayerCreationArgs.h"
27 #include "FrontEnd/Update.h"
28 #include "Tracing/LayerTracing.h"
29 #include "Tracing/TransactionTracing.h"
30 
31 using namespace android::surfaceflinger;
32 
33 namespace android {
34 
35 class TransactionTracingTest : public testing::Test {
36 protected:
37     static constexpr size_t SMALL_BUFFER_SIZE = 1024;
38     TransactionTracing mTracing;
39 
flush()40     void flush() { mTracing.flush(); }
writeToProto()41     perfetto::protos::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); }
42 
bufferFront()43     perfetto::protos::TransactionTraceEntry bufferFront() {
44         std::scoped_lock<std::mutex> lock(mTracing.mTraceLock);
45         perfetto::protos::TransactionTraceEntry entry;
46         entry.ParseFromString(mTracing.mBuffer.front());
47         return entry;
48     }
49 
queueAndCommitTransaction(int64_t vsyncId)50     void queueAndCommitTransaction(int64_t vsyncId) {
51         frontend::Update update;
52         QueuedTransactionState transaction;
53         transaction.id = static_cast<uint64_t>(vsyncId * 3);
54         transaction.originUid = 1;
55         transaction.originPid = 2;
56         mTracing.addQueuedTransaction(transaction);
57         std::vector<QueuedTransactionState> transactions;
58         update.transactions.emplace_back(transaction);
59         mTracing.addCommittedTransactions(vsyncId, 0, update, {}, false);
60         flush();
61     }
62 
verifyEntry(const perfetto::protos::TransactionTraceEntry & actualProto,const std::vector<QueuedTransactionState> & expectedTransactions,int64_t expectedVsyncId)63     void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto,
64                      const std::vector<QueuedTransactionState>& expectedTransactions,
65                      int64_t expectedVsyncId) {
66         EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
67         ASSERT_EQ(actualProto.transactions().size(),
68                   static_cast<int32_t>(expectedTransactions.size()));
69         for (uint32_t i = 0; i < expectedTransactions.size(); i++) {
70             const auto expectedTransaction = expectedTransactions[i];
71             const auto protoTransaction = actualProto.transactions(static_cast<int32_t>(i));
72             EXPECT_EQ(protoTransaction.transaction_id(), expectedTransaction.id);
73             EXPECT_EQ(protoTransaction.pid(), expectedTransaction.originPid);
74             for (uint32_t i = 0; i < expectedTransaction.mergedTransactionIds.size(); i++) {
75                 EXPECT_EQ(protoTransaction.merged_transaction_ids(static_cast<int32_t>(i)),
76                           expectedTransaction.mergedTransactionIds[i]);
77             }
78         }
79     }
80 
getLayerCreationArgs(uint32_t layerId,uint32_t parentId,uint32_t layerIdToMirror,uint32_t flags,bool addToRoot)81     LayerCreationArgs getLayerCreationArgs(uint32_t layerId, uint32_t parentId,
82                                            uint32_t layerIdToMirror, uint32_t flags,
83                                            bool addToRoot) {
84         LayerCreationArgs args;
85         args.sequence = layerId;
86         args.parentId = parentId;
87         args.layerIdToMirror = layerIdToMirror;
88         args.flags = flags;
89         args.addToRoot = addToRoot;
90         return args;
91     }
92 };
93 
TEST_F(TransactionTracingTest,addTransactions)94 TEST_F(TransactionTracingTest, addTransactions) {
95     std::vector<QueuedTransactionState> transactions;
96     transactions.reserve(100);
97     for (uint64_t i = 0; i < 100; i++) {
98         QueuedTransactionState transaction;
99         transaction.id = i;
100         transaction.originPid = static_cast<int32_t>(i);
101         transaction.mergedTransactionIds = std::vector<uint64_t>{i + 100, i + 102};
102         transactions.emplace_back(transaction);
103         mTracing.addQueuedTransaction(transaction);
104     }
105 
106     // Split incoming transactions into two and commit them in reverse order to test out of order
107     // commits.
108     int64_t firstTransactionSetVsyncId = 42;
109     frontend::Update firstUpdate;
110     firstUpdate.transactions =
111             std::vector<QueuedTransactionState>(transactions.begin() + 50, transactions.end());
112     mTracing.addCommittedTransactions(firstTransactionSetVsyncId, 0, firstUpdate, {}, false);
113 
114     int64_t secondTransactionSetVsyncId = 43;
115     frontend::Update secondUpdate;
116     secondUpdate.transactions =
117             std::vector<QueuedTransactionState>(transactions.begin(), transactions.begin() + 50);
118     mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false);
119     flush();
120 
121     perfetto::protos::TransactionTraceFile proto = writeToProto();
122     ASSERT_EQ(proto.entry().size(), 2);
123     verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId);
124     verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId);
125 }
126 
127 class TransactionTracingLayerHandlingTest : public TransactionTracingTest {
128 protected:
SetUp()129     void SetUp() override {
130         mTracing.setBufferSize(SMALL_BUFFER_SIZE);
131 
132         // add layers and add some layer transaction
133         {
134             frontend::Update update;
135             update.layerCreationArgs.emplace_back(
136                     getLayerCreationArgs(mParentLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
137                                          /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
138                                          /*addToRoot=*/true));
139             update.layerCreationArgs.emplace_back(
140                     getLayerCreationArgs(mChildLayerId, mParentLayerId,
141                                          /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/456,
142                                          /*addToRoot=*/true));
143             QueuedTransactionState transaction;
144             transaction.id = 50;
145             ResolvedComposerState layerState;
146             layerState.layerId = mParentLayerId;
147             layerState.state.what = layer_state_t::eLayerChanged;
148             layerState.state.z = 42;
149             transaction.states.emplace_back(layerState);
150             ResolvedComposerState childState;
151             childState.layerId = mChildLayerId;
152             childState.state.what = layer_state_t::eLayerChanged;
153             childState.state.z = 43;
154             transaction.states.emplace_back(childState);
155             mTracing.addQueuedTransaction(transaction);
156 
157             update.transactions.emplace_back(transaction);
158             VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId;
159             mTracing.addCommittedTransactions(VSYNC_ID_FIRST_LAYER_CHANGE, 0, update, {}, false);
160 
161             flush();
162         }
163 
164         // add transactions that modify the layer state further so we can test that layer state
165         // gets merged
166         {
167             QueuedTransactionState transaction;
168             transaction.id = 51;
169             ResolvedComposerState layerState;
170             layerState.layerId = mParentLayerId;
171             layerState.state.what = layer_state_t::eLayerChanged | layer_state_t::ePositionChanged;
172             layerState.state.z = 41;
173             layerState.state.x = 22;
174             transaction.states.emplace_back(layerState);
175             mTracing.addQueuedTransaction(transaction);
176 
177             frontend::Update update;
178             update.transactions.emplace_back(transaction);
179             VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId;
180             mTracing.addCommittedTransactions(VSYNC_ID_SECOND_LAYER_CHANGE, 0, update, {}, false);
181             flush();
182         }
183 
184         // remove child layer
185         mTracing.onLayerRemoved(2);
186         VSYNC_ID_CHILD_LAYER_REMOVED = ++mVsyncId;
187         queueAndCommitTransaction(VSYNC_ID_CHILD_LAYER_REMOVED);
188 
189         // remove layer
190         mTracing.onLayerRemoved(1);
191         queueAndCommitTransaction(++mVsyncId);
192     }
193 
194     uint32_t mParentLayerId = 1;
195     uint32_t mChildLayerId = 2;
196     int64_t mVsyncId = 0;
197     int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
198     int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
199     int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
200 };
201 
TEST_F(TransactionTracingLayerHandlingTest,addStartingState)202 TEST_F(TransactionTracingLayerHandlingTest, addStartingState) {
203     // add transactions until we drop the transaction with the first layer change
204     while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) {
205         queueAndCommitTransaction(++mVsyncId);
206     }
207     perfetto::protos::TransactionTraceFile proto = writeToProto();
208     // verify we can still retrieve the layer change from the first entry containing starting
209     // states.
210     EXPECT_GT(proto.entry().size(), 0);
211     EXPECT_EQ(proto.entry(0).transactions().size(), 1);
212     EXPECT_EQ(proto.entry(0).added_layers().size(), 2);
213     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
214     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
215     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 42);
216     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).layer_id(), mChildLayerId);
217     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
218     EXPECT_TRUE(proto.entry(0).displays_changed());
219 }
220 
TEST_F(TransactionTracingLayerHandlingTest,updateStartingState)221 TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) {
222     // add transactions until we drop the transaction with the second layer change
223     while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
224         queueAndCommitTransaction(++mVsyncId);
225     }
226     perfetto::protos::TransactionTraceFile proto = writeToProto();
227     // verify starting states are updated correctly
228     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41);
229     EXPECT_TRUE(proto.entry(0).displays_changed());
230 }
231 
TEST_F(TransactionTracingLayerHandlingTest,removeStartingState)232 TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) {
233     // add transactions until we drop the transaction which removes the child layer
234     while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
235         queueAndCommitTransaction(++mVsyncId);
236     }
237     perfetto::protos::TransactionTraceFile proto = writeToProto();
238     // verify the child layer has been removed from the trace
239     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
240     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
241     EXPECT_TRUE(proto.entry(0).displays_changed());
242 }
243 
TEST_F(TransactionTracingLayerHandlingTest,startingStateSurvivesBufferFlush)244 TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) {
245     // add transactions until we drop the transaction with the second layer change
246     while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
247         queueAndCommitTransaction(++mVsyncId);
248     }
249     perfetto::protos::TransactionTraceFile proto = writeToProto();
250     // verify we have two starting states
251     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
252 
253     // Continue adding transactions until child layer is removed
254     while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
255         queueAndCommitTransaction(++mVsyncId);
256     }
257     proto = writeToProto();
258     // verify we still have the parent layer state
259     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
260     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
261     EXPECT_TRUE(proto.entry(0).displays_changed());
262 }
263 
264 class TransactionTracingMirrorLayerTest : public TransactionTracingTest {
265 protected:
SetUp()266     void SetUp() override {
267         mTracing.setBufferSize(SMALL_BUFFER_SIZE);
268 
269         // add layers and some layer transaction
270         {
271             frontend::Update update;
272             update.layerCreationArgs.emplace_back(
273                     getLayerCreationArgs(mLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
274                                          /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
275                                          /*addToRoot=*/true));
276             update.layerCreationArgs.emplace_back(
277                     getLayerCreationArgs(mMirrorLayerId, UNASSIGNED_LAYER_ID,
278                                          /*layerIdToMirror=*/mLayerId, /*flags=*/0,
279                                          /*addToRoot=*/false));
280 
281             QueuedTransactionState transaction;
282             transaction.id = 50;
283             ResolvedComposerState layerState;
284             layerState.layerId = mLayerId;
285             layerState.state.what = layer_state_t::eLayerChanged;
286             layerState.state.z = 42;
287             transaction.states.emplace_back(layerState);
288             ResolvedComposerState mirrorState;
289             mirrorState.layerId = mMirrorLayerId;
290             mirrorState.state.what = layer_state_t::eLayerChanged;
291             mirrorState.state.z = 43;
292             transaction.states.emplace_back(mirrorState);
293             mTracing.addQueuedTransaction(transaction);
294 
295             update.transactions.emplace_back(transaction);
296             mTracing.addCommittedTransactions(mVsyncId, 0, update, {}, false);
297             flush();
298         }
299     }
300 
301     uint32_t mLayerId = 5;
302     uint32_t mMirrorLayerId = 55;
303     int64_t mVsyncId = 0;
304     int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
305     int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
306     int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
307 };
308 
TEST_F(TransactionTracingMirrorLayerTest,canAddMirrorLayers)309 TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) {
310     perfetto::protos::TransactionTraceFile proto = writeToProto();
311     // We don't have any starting states since no layer was removed from.
312     EXPECT_EQ(proto.entry().size(), 1);
313 
314     // Verify the mirror layer was added
315     EXPECT_EQ(proto.entry(0).transactions().size(), 1);
316     EXPECT_EQ(proto.entry(0).added_layers().size(), 2);
317     EXPECT_EQ(proto.entry(0).added_layers(1).layer_id(), mMirrorLayerId);
318     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
319     EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
320 }
321 
322 // Verify we can write the layers traces by entry to reduce mem pressure
323 // on the system when generating large traces.
TEST(LayerTraceTest,canStreamLayersTrace)324 TEST(LayerTraceTest, canStreamLayersTrace) {
325     perfetto::protos::LayersTraceFileProto inProto = LayerTracing::createTraceFileProto();
326     inProto.add_entry();
327     inProto.add_entry();
328 
329     std::string output;
330     inProto.SerializeToString(&output);
331     perfetto::protos::LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto();
332     inProto2.add_entry();
333     std::string output2;
334     inProto2.SerializeToString(&output2);
335 
336     perfetto::protos::LayersTraceFileProto outProto;
337     outProto.ParseFromString(output + output2);
338     // magic?
339     EXPECT_EQ(outProto.entry().size(), 3);
340 }
341 } // namespace android
342