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