blob: 71c7bd935fe295de9959ae00e1b03fbbd7a73b23 [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>
21
22#include "Tracing/RingBuffer.h"
23#include "Tracing/TransactionTracing.h"
24
25using namespace android::surfaceflinger;
26
27namespace android {
28
29class TransactionTracingTest : public testing::Test {
30protected:
Vishnu Nair0cc69e12021-11-18 09:05:49 -080031 static constexpr size_t SMALL_BUFFER_SIZE = 1024;
Vishnu Nair7891e962021-11-11 12:07:21 -080032 std::unique_ptr<android::TransactionTracing> mTracing;
Vishnu Nair7891e962021-11-11 12:07:21 -080033 void SetUp() override { mTracing = std::make_unique<android::TransactionTracing>(); }
34
Vishnu Nair0cc69e12021-11-18 09:05:49 -080035 void TearDown() override {
36 mTracing->disable();
37 mTracing.reset();
38 }
Vishnu Nair7891e962021-11-11 12:07:21 -080039
40 auto getCommittedTransactions() {
41 std::scoped_lock<std::mutex> lock(mTracing->mMainThreadLock);
42 return mTracing->mCommittedTransactions;
43 }
44
45 auto getQueuedTransactions() {
46 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
47 return mTracing->mQueuedTransactions;
48 }
49
50 auto getUsedBufferSize() {
51 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
52 return mTracing->mBuffer->used();
53 }
54
Vishnu Nair0cc69e12021-11-18 09:05:49 -080055 auto flush(int64_t vsyncId) { return mTracing->flush(vsyncId); }
Vishnu Nair7891e962021-11-11 12:07:21 -080056
57 auto bufferFront() {
58 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
59 return mTracing->mBuffer->front();
60 }
61
62 bool threadIsJoinable() {
63 std::scoped_lock lock(mTracing->mMainThreadLock);
64 return mTracing->mThread.joinable();
65 }
66
Vishnu Nair0cc69e12021-11-18 09:05:49 -080067 proto::TransactionTraceFile writeToProto() { return mTracing->writeToProto(); }
68
69 auto getCreatedLayers() {
Vishnu Nair7891e962021-11-11 12:07:21 -080070 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
Vishnu Nair0cc69e12021-11-18 09:05:49 -080071 return mTracing->mCreatedLayers;
72 }
73
74 auto getStartingStates() {
75 std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
76 return mTracing->mStartingStates;
77 }
78
79 void queueAndCommitTransaction(int64_t vsyncId) {
80 TransactionState transaction;
81 transaction.id = static_cast<uint64_t>(vsyncId * 3);
82 transaction.originUid = 1;
83 transaction.originPid = 2;
84 mTracing->addQueuedTransaction(transaction);
85 std::vector<TransactionState> transactions;
86 transactions.emplace_back(transaction);
87 mTracing->addCommittedTransactions(transactions, vsyncId);
88 flush(vsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -080089 }
90
91 // Test that we clean up the tracing thread and free any memory allocated.
92 void verifyDisabledTracingState() {
93 EXPECT_FALSE(mTracing->isEnabled());
94 EXPECT_FALSE(threadIsJoinable());
95 EXPECT_EQ(getCommittedTransactions().size(), 0u);
96 EXPECT_EQ(getQueuedTransactions().size(), 0u);
97 EXPECT_EQ(getUsedBufferSize(), 0u);
Vishnu Nair0cc69e12021-11-18 09:05:49 -080098 EXPECT_EQ(getStartingStates().size(), 0u);
Vishnu Nair7891e962021-11-11 12:07:21 -080099 }
100
101 void verifyEntry(const proto::TransactionTraceEntry& actualProto,
102 const std::vector<TransactionState> expectedTransactions,
103 int64_t expectedVsyncId) {
104 EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
105 EXPECT_EQ(actualProto.transactions().size(),
106 static_cast<int32_t>(expectedTransactions.size()));
107 for (uint32_t i = 0; i < expectedTransactions.size(); i++) {
108 EXPECT_EQ(actualProto.transactions(static_cast<int32_t>(i)).pid(),
109 expectedTransactions[i].originPid);
110 }
111 }
112};
113
114TEST_F(TransactionTracingTest, enable) {
115 EXPECT_FALSE(mTracing->isEnabled());
116 mTracing->enable();
117 EXPECT_TRUE(mTracing->isEnabled());
118 mTracing->disable();
119 verifyDisabledTracingState();
120}
121
122TEST_F(TransactionTracingTest, addTransactions) {
123 mTracing->enable();
124 std::vector<TransactionState> transactions;
125 transactions.reserve(100);
126 for (uint64_t i = 0; i < 100; i++) {
127 TransactionState transaction;
128 transaction.id = i;
129 transaction.originPid = static_cast<int32_t>(i);
130 transactions.emplace_back(transaction);
131 mTracing->addQueuedTransaction(transaction);
132 }
133
134 // Split incoming transactions into two and commit them in reverse order to test out of order
135 // commits.
136 std::vector<TransactionState> firstTransactionSet =
137 std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
138 int64_t firstTransactionSetVsyncId = 42;
139 mTracing->addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId);
140
141 int64_t secondTransactionSetVsyncId = 43;
142 std::vector<TransactionState> secondTransactionSet =
143 std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50);
144 mTracing->addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800145 flush(secondTransactionSetVsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800146
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800147 proto::TransactionTraceFile proto = writeToProto();
148 EXPECT_EQ(proto.entry().size(), 3);
149 // skip starting entry
150 verifyEntry(proto.entry(1), firstTransactionSet, firstTransactionSetVsyncId);
151 verifyEntry(proto.entry(2), secondTransactionSet, secondTransactionSetVsyncId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800152
153 mTracing->disable();
154 verifyDisabledTracingState();
155}
156
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800157class TransactionTracingLayerHandlingTest : public TransactionTracingTest {
158protected:
159 void SetUp() override {
160 TransactionTracingTest::SetUp();
161 mTracing->enable();
162 // add layers
163 mTracing->setBufferSize(SMALL_BUFFER_SIZE);
164 const sp<IBinder> fakeLayerHandle = new BBinder();
165 mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent",
166 123 /* flags */, -1 /* parentId */);
167 const sp<IBinder> fakeChildLayerHandle = new BBinder();
Vishnu Nair473838d2021-12-08 09:46:02 -0800168 mTracing->onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child",
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800169 456 /* flags */, mParentLayerId);
170
171 // add some layer transaction
172 {
173 TransactionState transaction;
174 transaction.id = 50;
175 ComposerState layerState;
176 layerState.state.surface = fakeLayerHandle;
177 layerState.state.what = layer_state_t::eLayerChanged;
178 layerState.state.z = 42;
179 transaction.states.add(layerState);
180 ComposerState childState;
181 childState.state.surface = fakeChildLayerHandle;
Vishnu Nair473838d2021-12-08 09:46:02 -0800182 childState.state.what = layer_state_t::eLayerChanged;
183 childState.state.z = 43;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800184 transaction.states.add(childState);
185 mTracing->addQueuedTransaction(transaction);
186
187 std::vector<TransactionState> transactions;
188 transactions.emplace_back(transaction);
189 VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId;
190 mTracing->addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE);
191 flush(VSYNC_ID_FIRST_LAYER_CHANGE);
192 }
193
194 // add transactions that modify the layer state further so we can test that layer state
195 // gets merged
196 {
197 TransactionState transaction;
198 transaction.id = 51;
199 ComposerState layerState;
200 layerState.state.surface = fakeLayerHandle;
201 layerState.state.what = layer_state_t::eLayerChanged | layer_state_t::ePositionChanged;
202 layerState.state.z = 41;
203 layerState.state.x = 22;
204 transaction.states.add(layerState);
205 mTracing->addQueuedTransaction(transaction);
206
207 std::vector<TransactionState> transactions;
208 transactions.emplace_back(transaction);
209 VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId;
210 mTracing->addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE);
211 flush(VSYNC_ID_SECOND_LAYER_CHANGE);
212 }
213
214 // remove child layer
215 mTracing->onLayerRemoved(2);
216 VSYNC_ID_CHILD_LAYER_REMOVED = ++mVsyncId;
217 queueAndCommitTransaction(VSYNC_ID_CHILD_LAYER_REMOVED);
218
219 // remove layer
220 mTracing->onLayerRemoved(1);
221 queueAndCommitTransaction(++mVsyncId);
222 }
223
224 void TearDown() override {
225 mTracing->disable();
226 verifyDisabledTracingState();
227 TransactionTracingTest::TearDown();
228 }
229
230 int mParentLayerId = 1;
Vishnu Nair473838d2021-12-08 09:46:02 -0800231 int mChildLayerId = 2;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800232 int64_t mVsyncId = 0;
233 int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
234 int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
235 int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
236};
237
238TEST_F(TransactionTracingLayerHandlingTest, addStartingState) {
239 // add transactions until we drop the transaction with the first layer change
240 while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) {
241 queueAndCommitTransaction(++mVsyncId);
242 }
243 proto::TransactionTraceFile proto = writeToProto();
244 // verify we can still retrieve the layer change from the first entry containing starting
245 // states.
246 EXPECT_GT(proto.entry().size(), 0);
247 EXPECT_GT(proto.entry(0).transactions().size(), 0);
248 EXPECT_GT(proto.entry(0).added_layers().size(), 0);
Vishnu Nair473838d2021-12-08 09:46:02 -0800249 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
250 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800251 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 42);
Vishnu Nair473838d2021-12-08 09:46:02 -0800252 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).layer_id(), mChildLayerId);
253 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(1).z(), 43);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800254}
255
256TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) {
257 // add transactions until we drop the transaction with the second layer change
258 while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
259 queueAndCommitTransaction(++mVsyncId);
260 }
261 proto::TransactionTraceFile proto = writeToProto();
262 // verify starting states are updated correctly
263 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41);
264}
265
266TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) {
267 // add transactions until we drop the transaction which removes the child layer
268 while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
269 queueAndCommitTransaction(++mVsyncId);
270 }
271 proto::TransactionTraceFile proto = writeToProto();
272 // verify the child layer has been removed from the trace
273 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
274 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
275}
276
277TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) {
278 // add transactions until we drop the transaction with the second layer change
279 while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
280 queueAndCommitTransaction(++mVsyncId);
281 }
282 proto::TransactionTraceFile proto = writeToProto();
283 // verify we have two starting states
284 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
285
286 // Continue adding transactions until child layer is removed
287 while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
288 queueAndCommitTransaction(++mVsyncId);
289 }
290 proto = writeToProto();
291 // verify we still have the parent layer state
292 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
293 EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
294}
295
Vishnu Nair84125ac2021-12-02 08:47:48 -0800296class TransactionTracingMirrorLayerTest : public TransactionTracingTest {
297protected:
298 void SetUp() override {
299 TransactionTracingTest::SetUp();
300 mTracing->enable();
301 // add layers
302 mTracing->setBufferSize(SMALL_BUFFER_SIZE);
303 const sp<IBinder> fakeLayerHandle = new BBinder();
304 mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer",
305 123 /* flags */, -1 /* parentId */);
306 const sp<IBinder> fakeMirrorLayerHandle = new BBinder();
307 mTracing->onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror",
308 mLayerId);
309
310 // add some layer transaction
311 {
312 TransactionState transaction;
313 transaction.id = 50;
314 ComposerState layerState;
315 layerState.state.surface = fakeLayerHandle;
316 layerState.state.what = layer_state_t::eLayerChanged;
317 layerState.state.z = 42;
318 transaction.states.add(layerState);
319 ComposerState mirrorState;
320 mirrorState.state.surface = fakeMirrorLayerHandle;
321 mirrorState.state.what = layer_state_t::eLayerChanged;
322 mirrorState.state.z = 43;
323 transaction.states.add(mirrorState);
324 mTracing->addQueuedTransaction(transaction);
325
326 std::vector<TransactionState> transactions;
327 transactions.emplace_back(transaction);
328 mTracing->addCommittedTransactions(transactions, ++mVsyncId);
329 flush(mVsyncId);
330 }
331 }
332
333 void TearDown() override {
334 mTracing->disable();
335 verifyDisabledTracingState();
336 TransactionTracingTest::TearDown();
337 }
338
339 int mLayerId = 5;
340 int mMirrorLayerId = 55;
341 int64_t mVsyncId = 0;
342 int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
343 int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
344 int64_t VSYNC_ID_CHILD_LAYER_REMOVED;
345};
346
347TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) {
348 proto::TransactionTraceFile proto = writeToProto();
349 // We don't have any starting states since no layer was removed from.
350 EXPECT_EQ(proto.entry().size(), 2);
351 EXPECT_EQ(proto.entry(0).transactions().size(), 0);
352 EXPECT_EQ(proto.entry(0).added_layers().size(), 0);
353
354 // Verify the mirror layer was added
355 EXPECT_EQ(proto.entry(1).transactions().size(), 1);
356 EXPECT_EQ(proto.entry(1).added_layers().size(), 2);
357 EXPECT_EQ(proto.entry(1).added_layers(1).layer_id(), mMirrorLayerId);
358 EXPECT_EQ(proto.entry(1).transactions(0).layer_changes().size(), 2);
359 EXPECT_EQ(proto.entry(1).transactions(0).layer_changes(1).z(), 43);
360}
Vishnu Nair7891e962021-11-11 12:07:21 -0800361} // namespace android