blob: 9d6d87eded973dcfe15a13c9a9d058364b47264b [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#undef LOG_TAG
18#define LOG_TAG "TransactionTracing"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include <android-base/stringprintf.h>
22#include <log/log.h>
23#include <utils/SystemClock.h>
24#include <utils/Trace.h>
25
Vishnu Nair81750622023-03-08 15:02:06 -080026#include "Client.h"
27#include "FrontEnd/LayerCreationArgs.h"
Kean Mariotti3e68a202023-04-19 13:41:55 +000028#include "TransactionDataSource.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080029#include "TransactionTracing.h"
30
31namespace android {
Vishnu Naird1f74982023-06-15 20:16:51 -070032ANDROID_SINGLETON_STATIC_INSTANCE(android::TransactionTraceWriter)
Vishnu Nair7891e962021-11-11 12:07:21 -080033
Vishnu Nair685cfef2022-02-02 10:01:25 -080034TransactionTracing::TransactionTracing()
Vishnu Nair81750622023-03-08 15:02:06 -080035 : mProtoParser(std::make_unique<TransactionProtoParser::FlingerDataMapper>()) {
Vishnu Nair7891e962021-11-11 12:07:21 -080036 std::scoped_lock lock(mTraceLock);
Dominik Laskowski46471e62022-01-14 15:34:03 -080037
Kean Mariotti3e68a202023-04-19 13:41:55 +000038 mBuffer.setSize(CONTINUOUS_TRACING_BUFFER_SIZE);
39
Vishnu Nair0cc69e12021-11-18 09:05:49 -080040 mStartingTimestamp = systemTime();
Kean Mariotti3e68a202023-04-19 13:41:55 +000041
Vishnu Nair7891e962021-11-11 12:07:21 -080042 {
43 std::scoped_lock lock(mMainThreadLock);
Vishnu Nair7891e962021-11-11 12:07:21 -080044 mThread = std::thread(&TransactionTracing::loop, this);
45 }
Kean Mariotti3e68a202023-04-19 13:41:55 +000046
47 TransactionDataSource::Initialize(*this);
Vishnu Nair7891e962021-11-11 12:07:21 -080048}
49
Dominik Laskowski46471e62022-01-14 15:34:03 -080050TransactionTracing::~TransactionTracing() {
Kean Mariotti3e68a202023-04-19 13:41:55 +000051 TransactionDataSource::UnregisterTransactionTracing();
Vishnu Nair7891e962021-11-11 12:07:21 -080052 std::thread thread;
53 {
54 std::scoped_lock lock(mMainThreadLock);
55 mDone = true;
56 mTransactionsAvailableCv.notify_all();
57 thread = std::move(mThread);
58 }
59 if (thread.joinable()) {
60 thread.join();
61 }
Kean Mariotti3e68a202023-04-19 13:41:55 +000062}
Vishnu Nair7891e962021-11-11 12:07:21 -080063
Kean Mariotti3e68a202023-04-19 13:41:55 +000064void TransactionTracing::onStart(TransactionTracing::Mode mode) {
65 // In "active" mode write the ring buffer (starting state + following sequence of transactions)
66 // to perfetto when tracing starts (only once).
67 if (mode != Mode::MODE_ACTIVE) {
68 return;
69 }
70
71 writeRingBufferToPerfetto(TransactionTracing::Mode::MODE_ACTIVE);
72
Kean Mariotti8c5abc82023-09-20 09:28:07 +000073 ALOGD("Started active mode tracing (wrote initial transactions ring buffer to perfetto)");
Kean Mariotti3e68a202023-04-19 13:41:55 +000074}
75
76void TransactionTracing::onFlush(TransactionTracing::Mode mode) {
77 // In "continuous" mode write the ring buffer (starting state + following sequence of
78 // transactions) to perfetto when a "flush" event is received (bugreport is taken or tracing is
79 // stopped).
80 if (mode != Mode::MODE_CONTINUOUS) {
81 return;
82 }
83
84 writeRingBufferToPerfetto(TransactionTracing::Mode::MODE_CONTINUOUS);
85
Kean Mariotti8c5abc82023-09-20 09:28:07 +000086 ALOGD("Flushed continuous mode tracing (wrote transactions ring buffer to perfetto");
Kean Mariotti3e68a202023-04-19 13:41:55 +000087}
88
89void TransactionTracing::writeRingBufferToPerfetto(TransactionTracing::Mode mode) {
90 // Write the ring buffer (starting state + following sequence of transactions) to perfetto
91 // tracing sessions with the specified mode.
92 const auto fileProto = writeToProto();
93
94 TransactionDataSource::Trace([&](TransactionDataSource::TraceContext context) {
95 // Write packets only to tracing sessions with specified mode
96 if (context.GetCustomTlsState()->mMode != mode) {
97 return;
98 }
99 for (const auto& entryProto : fileProto.entry()) {
100 const auto entryBytes = entryProto.SerializeAsString();
101
102 auto packet = context.NewTracePacket();
103 packet->set_timestamp(static_cast<uint64_t>(entryProto.elapsed_realtime_nanos()));
104 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
105
106 auto* transactionsProto = packet->set_surfaceflinger_transactions();
107 transactionsProto->AppendRawProtoBytes(entryBytes.data(), entryBytes.size());
108 }
109 {
110 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
111 // It is currently needed in order not to lose the last trace entry.
112 context.NewTracePacket();
113 }
114 });
Vishnu Nair7891e962021-11-11 12:07:21 -0800115}
116
Vishnu Naird1f74982023-06-15 20:16:51 -0700117status_t TransactionTracing::writeToFile(const std::string& filename) {
Kean Mariotti3e68a202023-04-19 13:41:55 +0000118 auto fileProto = writeToProto();
119
120 std::string output;
121 if (!fileProto.SerializeToString(&output)) {
122 ALOGE("Could not serialize proto.");
123 return UNKNOWN_ERROR;
124 }
125
126 // -rw-r--r--
127 const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
128 if (!android::base::WriteStringToFile(output, filename, mode, getuid(), getgid(), true)) {
129 ALOGE("Could not save the proto file %s", filename.c_str());
130 return PERMISSION_DENIED;
131 }
132
133 return NO_ERROR;
134}
135
136perfetto::protos::TransactionTraceFile TransactionTracing::writeToProto() {
137 std::scoped_lock<std::mutex> lock(mTraceLock);
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000138 perfetto::protos::TransactionTraceFile fileProto = createTraceFileProto();
Kean Mariotti3e68a202023-04-19 13:41:55 +0000139 const auto startingStateProto = createStartingStateProtoLocked();
140 if (startingStateProto) {
141 *fileProto.add_entry() = std::move(*startingStateProto);
142 }
143 mBuffer.writeToProto(fileProto);
144 return fileProto;
Vishnu Nair7891e962021-11-11 12:07:21 -0800145}
146
147void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) {
148 std::scoped_lock lock(mTraceLock);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000149 mBuffer.setSize(bufferSizeInBytes);
Vishnu Nair7891e962021-11-11 12:07:21 -0800150}
151
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000152perfetto::protos::TransactionTraceFile TransactionTracing::createTraceFileProto() const {
153 perfetto::protos::TransactionTraceFile proto;
154 proto.set_magic_number(
155 uint64_t(perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 |
156 perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000157 auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
158 systemTime(SYSTEM_TIME_MONOTONIC));
Kean Mariottic44fdaf2022-07-29 14:20:39 +0000159 proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair81750622023-03-08 15:02:06 -0800160 proto.set_version(TRACING_VERSION);
Vishnu Nair7891e962021-11-11 12:07:21 -0800161 return proto;
162}
163
164void TransactionTracing::dump(std::string& result) const {
165 std::scoped_lock lock(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -0800166 base::StringAppendF(&result, " queued transactions=%zu created layers=%zu states=%zu\n",
167 mQueuedTransactions.size(), mCreatedLayers.size(), mStartingStates.size());
Dominik Laskowski46471e62022-01-14 15:34:03 -0800168 mBuffer.dump(result);
Vishnu Nair7891e962021-11-11 12:07:21 -0800169}
170
171void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) {
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000172 perfetto::protos::TransactionState* state =
173 new perfetto::protos::TransactionState(mProtoParser.toProto(transaction));
Robert Carra63d52a2022-03-03 08:03:37 -0800174 mTransactionQueue.push(state);
Vishnu Nair7891e962021-11-11 12:07:21 -0800175}
176
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500177void TransactionTracing::addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime,
178 frontend::Update& newUpdate,
179 const frontend::DisplayInfos& displayInfos,
180 bool displayInfoChanged) {
Vishnu Nair81750622023-03-08 15:02:06 -0800181 CommittedUpdates update;
182 update.vsyncId = vsyncId;
183 update.timestamp = commitTime;
184 update.transactionIds.reserve(newUpdate.transactions.size());
185 for (const auto& transaction : newUpdate.transactions) {
186 update.transactionIds.emplace_back(transaction.id);
Vishnu Nair286f4f92022-06-08 16:37:39 -0700187 }
Vishnu Nair81750622023-03-08 15:02:06 -0800188 update.displayInfoChanged = displayInfoChanged;
189 if (displayInfoChanged) {
190 update.displayInfos = displayInfos;
Vishnu Nair7891e962021-11-11 12:07:21 -0800191 }
Vishnu Nair81750622023-03-08 15:02:06 -0800192 update.createdLayers = std::move(newUpdate.layerCreationArgs);
193 newUpdate.layerCreationArgs.clear();
194 update.destroyedLayerHandles.reserve(newUpdate.destroyedHandles.size());
Vishnu Nair606d9d02023-08-19 14:20:18 -0700195 for (auto& [handle, _] : newUpdate.destroyedHandles) {
Vishnu Nair81750622023-03-08 15:02:06 -0800196 update.destroyedLayerHandles.push_back(handle);
197 }
198 mPendingUpdates.emplace_back(update);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800199 tryPushToTracingThread();
Vishnu Naird1f74982023-06-15 20:16:51 -0700200 mLastUpdatedVsyncId = vsyncId;
Vishnu Nair7891e962021-11-11 12:07:21 -0800201}
202
203void TransactionTracing::loop() {
204 while (true) {
Vishnu Nair81750622023-03-08 15:02:06 -0800205 std::vector<CommittedUpdates> committedUpdates;
206 std::vector<uint32_t> destroyedLayers;
Vishnu Nair7891e962021-11-11 12:07:21 -0800207 {
208 std::unique_lock<std::mutex> lock(mMainThreadLock);
209 base::ScopedLockAssertion assumeLocked(mMainThreadLock);
210 mTransactionsAvailableCv.wait(lock, [&]() REQUIRES(mMainThreadLock) {
Vishnu Nair81750622023-03-08 15:02:06 -0800211 return mDone || !mUpdates.empty();
Vishnu Nair7891e962021-11-11 12:07:21 -0800212 });
213 if (mDone) {
Vishnu Nair81750622023-03-08 15:02:06 -0800214 mUpdates.clear();
215 mDestroyedLayers.clear();
Vishnu Nair7891e962021-11-11 12:07:21 -0800216 break;
217 }
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800218
Vishnu Nair81750622023-03-08 15:02:06 -0800219 destroyedLayers = std::move(mDestroyedLayers);
220 mDestroyedLayers.clear();
221 committedUpdates = std::move(mUpdates);
222 mUpdates.clear();
Vishnu Nair7891e962021-11-11 12:07:21 -0800223 } // unlock mMainThreadLock
224
Vishnu Nair81750622023-03-08 15:02:06 -0800225 if (!committedUpdates.empty() || !destroyedLayers.empty()) {
226 addEntry(committedUpdates, destroyedLayers);
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800227 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800228 }
229}
230
Vishnu Nair81750622023-03-08 15:02:06 -0800231void TransactionTracing::addEntry(const std::vector<CommittedUpdates>& committedUpdates,
232 const std::vector<uint32_t>& destroyedLayers) {
Vishnu Nair7891e962021-11-11 12:07:21 -0800233 ATRACE_CALL();
234 std::scoped_lock lock(mTraceLock);
Vishnu Nair62863552021-12-10 13:34:48 -0800235 std::vector<std::string> removedEntries;
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000236 perfetto::protos::TransactionTraceEntry entryProto;
Robert Carra63d52a2022-03-03 08:03:37 -0800237
238 while (auto incomingTransaction = mTransactionQueue.pop()) {
239 auto transaction = *incomingTransaction;
Robert Carra63d52a2022-03-03 08:03:37 -0800240 mQueuedTransactions[incomingTransaction->transaction_id()] = transaction;
241 delete incomingTransaction;
242 }
Vishnu Nair81750622023-03-08 15:02:06 -0800243 for (const CommittedUpdates& update : committedUpdates) {
244 entryProto.set_elapsed_realtime_nanos(update.timestamp);
245 entryProto.set_vsync_id(update.vsyncId);
Vishnu Nair286f4f92022-06-08 16:37:39 -0700246 entryProto.mutable_added_layers()->Reserve(
Vishnu Nair81750622023-03-08 15:02:06 -0800247 static_cast<int32_t>(update.createdLayers.size()));
Vishnu Nair286f4f92022-06-08 16:37:39 -0700248
Vishnu Nair81750622023-03-08 15:02:06 -0800249 for (const auto& args : update.createdLayers) {
250 entryProto.mutable_added_layers()->Add(std::move(mProtoParser.toProto(args)));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800251 }
Vishnu Nair286f4f92022-06-08 16:37:39 -0700252
Vishnu Nair81750622023-03-08 15:02:06 -0800253 entryProto.mutable_destroyed_layers()->Reserve(
254 static_cast<int32_t>(destroyedLayers.size()));
255 for (auto& destroyedLayer : destroyedLayers) {
256 entryProto.mutable_destroyed_layers()->Add(destroyedLayer);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800257 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800258 entryProto.mutable_transactions()->Reserve(
Vishnu Nair81750622023-03-08 15:02:06 -0800259 static_cast<int32_t>(update.transactionIds.size()));
260 for (const uint64_t& id : update.transactionIds) {
Vishnu Nair7891e962021-11-11 12:07:21 -0800261 auto it = mQueuedTransactions.find(id);
262 if (it != mQueuedTransactions.end()) {
263 entryProto.mutable_transactions()->Add(std::move(it->second));
264 mQueuedTransactions.erase(it);
265 } else {
Vishnu Nair047fb332021-12-09 09:54:36 -0800266 ALOGW("Could not find transaction id %" PRIu64, id);
Vishnu Nair7891e962021-11-11 12:07:21 -0800267 }
268 }
Vishnu Nair62863552021-12-10 13:34:48 -0800269
Vishnu Nair81750622023-03-08 15:02:06 -0800270 entryProto.mutable_destroyed_layer_handles()->Reserve(
271 static_cast<int32_t>(update.destroyedLayerHandles.size()));
272 for (auto layerId : update.destroyedLayerHandles) {
273 entryProto.mutable_destroyed_layer_handles()->Add(layerId);
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700274 }
Vishnu Nair81750622023-03-08 15:02:06 -0800275
276 entryProto.set_displays_changed(update.displayInfoChanged);
277 if (update.displayInfoChanged) {
278 entryProto.mutable_displays()->Reserve(
279 static_cast<int32_t>(update.displayInfos.size()));
280 for (auto& [layerStack, displayInfo] : update.displayInfos) {
281 entryProto.mutable_displays()->Add(
282 std::move(mProtoParser.toProto(displayInfo, layerStack.id)));
283 }
284 }
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700285
Vishnu Nair62863552021-12-10 13:34:48 -0800286 std::string serializedProto;
287 entryProto.SerializeToString(&serializedProto);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000288
289 TransactionDataSource::Trace([&](TransactionDataSource::TraceContext context) {
290 // In "active" mode write each committed transaction to perfetto.
291 // Note: the starting state is written (once) when the perfetto "start" event is
292 // received.
293 if (context.GetCustomTlsState()->mMode != Mode::MODE_ACTIVE) {
294 return;
295 }
296 {
297 auto packet = context.NewTracePacket();
298 packet->set_timestamp(static_cast<uint64_t>(entryProto.elapsed_realtime_nanos()));
299 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
300 auto* transactions = packet->set_surfaceflinger_transactions();
301 transactions->AppendRawProtoBytes(serializedProto.data(), serializedProto.size());
302 }
303 {
304 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
305 // It is currently needed in order not to lose the last trace entry.
306 context.NewTracePacket();
307 }
308 });
309
Dominik Laskowski46471e62022-01-14 15:34:03 -0800310 std::vector<std::string> entries = mBuffer.emplace(std::move(serializedProto));
Vishnu Nair62863552021-12-10 13:34:48 -0800311 removedEntries.reserve(removedEntries.size() + entries.size());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800312 removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
313 std::make_move_iterator(entries.end()));
Kean Mariotti3e68a202023-04-19 13:41:55 +0000314
315 entryProto.Clear();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800316 }
317
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000318 perfetto::protos::TransactionTraceEntry removedEntryProto;
Vishnu Nair62863552021-12-10 13:34:48 -0800319 for (const std::string& removedEntry : removedEntries) {
320 removedEntryProto.ParseFromString(removedEntry);
321 updateStartingStateLocked(removedEntryProto);
322 removedEntryProto.Clear();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800323 }
324 mTransactionsAddedToBufferCv.notify_one();
325}
326
Vishnu Naird1f74982023-06-15 20:16:51 -0700327void TransactionTracing::flush() {
328 {
329 std::scoped_lock lock(mMainThreadLock);
330 // Collect any pending transactions and wait for transactions to be added to
331 mUpdates.insert(mUpdates.end(), std::make_move_iterator(mPendingUpdates.begin()),
332 std::make_move_iterator(mPendingUpdates.end()));
333 mPendingUpdates.clear();
334 mDestroyedLayers.insert(mDestroyedLayers.end(), mPendingDestroyedLayers.begin(),
335 mPendingDestroyedLayers.end());
336 mPendingDestroyedLayers.clear();
337 mTransactionsAvailableCv.notify_one();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800338 }
339 std::unique_lock<std::mutex> lock(mTraceLock);
340 base::ScopedLockAssertion assumeLocked(mTraceLock);
Vishnu Naird1f74982023-06-15 20:16:51 -0700341 mTransactionsAddedToBufferCv.wait_for(lock, std::chrono::milliseconds(100),
342 [&]() REQUIRES(mTraceLock) {
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000343 perfetto::protos::TransactionTraceEntry entry;
Vishnu Naird1f74982023-06-15 20:16:51 -0700344 if (mBuffer.used() > 0) {
345 entry.ParseFromString(mBuffer.back());
346 }
347 return mBuffer.used() > 0 &&
348 entry.vsync_id() >= mLastUpdatedVsyncId;
349 });
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800350}
351
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800352void TransactionTracing::onLayerRemoved(int32_t layerId) {
Vishnu Nair81750622023-03-08 15:02:06 -0800353 mPendingDestroyedLayers.emplace_back(layerId);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800354 tryPushToTracingThread();
355}
356
357void TransactionTracing::tryPushToTracingThread() {
358 // Try to acquire the lock from main thread.
359 if (mMainThreadLock.try_lock()) {
360 // We got the lock! Collect any pending transactions and continue.
Vishnu Nair81750622023-03-08 15:02:06 -0800361 mUpdates.insert(mUpdates.end(), std::make_move_iterator(mPendingUpdates.begin()),
362 std::make_move_iterator(mPendingUpdates.end()));
363 mPendingUpdates.clear();
364 mDestroyedLayers.insert(mDestroyedLayers.end(), mPendingDestroyedLayers.begin(),
365 mPendingDestroyedLayers.end());
366 mPendingDestroyedLayers.clear();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800367 mTransactionsAvailableCv.notify_one();
368 mMainThreadLock.unlock();
369 } else {
370 ALOGV("Couldn't get lock");
Vishnu Nair7891e962021-11-11 12:07:21 -0800371 }
372}
373
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800374void TransactionTracing::updateStartingStateLocked(
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000375 const perfetto::protos::TransactionTraceEntry& removedEntry) {
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800376 mStartingTimestamp = removedEntry.elapsed_realtime_nanos();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800377 // Keep track of layer starting state so we can reconstruct the layer state as we purge
378 // transactions from the buffer.
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000379 for (const perfetto::protos::LayerCreationArgs& addedLayer : removedEntry.added_layers()) {
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800380 TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()];
381 startingState.layerId = addedLayer.layer_id();
Vishnu Nair685cfef2022-02-02 10:01:25 -0800382 mProtoParser.fromProto(addedLayer, startingState.args);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800383 }
384
385 // Merge layer states to starting transaction state.
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000386 for (const perfetto::protos::TransactionState& transaction : removedEntry.transactions()) {
387 for (const perfetto::protos::LayerState& layerState : transaction.layer_changes()) {
Vishnu Nair81750622023-03-08 15:02:06 -0800388 auto it = mStartingStates.find(layerState.layer_id());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800389 if (it == mStartingStates.end()) {
Vishnu Nair20e1f962023-03-29 15:58:34 -0700390 // TODO(b/238781169) make this log fatal when we switch over to using new fe
Vishnu Nair81750622023-03-08 15:02:06 -0800391 ALOGW("Could not find layer id %d", layerState.layer_id());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800392 continue;
393 }
Vishnu Nair685cfef2022-02-02 10:01:25 -0800394 mProtoParser.mergeFromProto(layerState, it->second);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800395 }
396 }
397
Vishnu Nair81750622023-03-08 15:02:06 -0800398 for (const uint32_t destroyedLayerHandleId : removedEntry.destroyed_layer_handles()) {
399 mRemovedLayerHandlesAtStart.insert(destroyedLayerHandleId);
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700400 }
401
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800402 // Clean up stale starting states since the layer has been removed and the buffer does not
403 // contain any references to the layer.
Vishnu Nair81750622023-03-08 15:02:06 -0800404 for (const uint32_t destroyedLayerId : removedEntry.destroyed_layers()) {
405 mStartingStates.erase(destroyedLayerId);
406 mRemovedLayerHandlesAtStart.erase(destroyedLayerId);
407 }
408
409 if (removedEntry.displays_changed()) {
410 mProtoParser.fromProto(removedEntry.displays(), mStartingDisplayInfos);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800411 }
412}
413
Kean Mariotti3e68a202023-04-19 13:41:55 +0000414std::optional<perfetto::protos::TransactionTraceEntry>
415TransactionTracing::createStartingStateProtoLocked() {
416 if (mStartingStates.empty()) {
417 return std::nullopt;
Vishnu Nair84125ac2021-12-02 08:47:48 -0800418 }
419
Kean Mariotti3e68a202023-04-19 13:41:55 +0000420 perfetto::protos::TransactionTraceEntry entryProto;
421 entryProto.set_elapsed_realtime_nanos(mStartingTimestamp);
422 entryProto.set_vsync_id(0);
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800423
Kean Mariotti3e68a202023-04-19 13:41:55 +0000424 entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mStartingStates.size()));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800425 for (auto& [layerId, state] : mStartingStates) {
Kean Mariotti3e68a202023-04-19 13:41:55 +0000426 entryProto.mutable_added_layers()->Add(mProtoParser.toProto(state.args));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800427 }
428
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000429 perfetto::protos::TransactionState transactionProto = mProtoParser.toProto(mStartingStates);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800430 transactionProto.set_vsync_id(0);
431 transactionProto.set_post_time(mStartingTimestamp);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000432 entryProto.mutable_transactions()->Add(std::move(transactionProto));
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700433
Kean Mariotti3e68a202023-04-19 13:41:55 +0000434 entryProto.mutable_destroyed_layer_handles()->Reserve(
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700435 static_cast<int32_t>(mRemovedLayerHandlesAtStart.size()));
Vishnu Nair81750622023-03-08 15:02:06 -0800436 for (const uint32_t destroyedLayerHandleId : mRemovedLayerHandlesAtStart) {
Kean Mariotti3e68a202023-04-19 13:41:55 +0000437 entryProto.mutable_destroyed_layer_handles()->Add(destroyedLayerHandleId);
Vishnu Nair81750622023-03-08 15:02:06 -0800438 }
439
Kean Mariotti3e68a202023-04-19 13:41:55 +0000440 entryProto.mutable_displays()->Reserve(static_cast<int32_t>(mStartingDisplayInfos.size()));
Vishnu Nair81750622023-03-08 15:02:06 -0800441 for (auto& [layerStack, displayInfo] : mStartingDisplayInfos) {
Kean Mariotti3e68a202023-04-19 13:41:55 +0000442 entryProto.mutable_displays()->Add(mProtoParser.toProto(displayInfo, layerStack.id));
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700443 }
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800444
Kean Mariotti3e68a202023-04-19 13:41:55 +0000445 return entryProto;
Vishnu Nair7891e962021-11-11 12:07:21 -0800446}
447
448} // namespace android