blob: d78f9bbbae1170ab7b44090497a6109cb8b2c1df [file] [log] [blame]
Vishnu Nair00b90132021-11-05 14:03:40 -07001/*
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 "LayerTracing"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
Diwas Sharma69758342023-09-01 00:40:19 +000021#include "LayerTracing.h"
Kean Mariotti639b54f2023-04-20 12:06:29 +000022
23#include "LayerDataSource.h"
24#include "Tracing/tools/LayerTraceGenerator.h"
25#include "TransactionTracing.h"
26
Vishnu Nairbe0ad902024-06-27 23:38:43 +000027#include <common/trace.h>
Kean Mariotti639b54f2023-04-20 12:06:29 +000028#include <log/log.h>
29#include <perfetto/tracing.h>
30#include <utils/Timers.h>
Diwas Sharma69758342023-09-01 00:40:19 +000031
Vishnu Nair00b90132021-11-05 14:03:40 -070032namespace android {
33
Kean Mariotti639b54f2023-04-20 12:06:29 +000034LayerTracing::LayerTracing() {
Kean Mariottifc0cd252023-12-07 09:27:40 +000035 mTakeLayersSnapshotProto = [](uint32_t, const OnLayersSnapshotCallback&) {};
Kean Mariotti639b54f2023-04-20 12:06:29 +000036 LayerDataSource::Initialize(*this);
John Reck2a3d29d2023-08-17 17:45:01 -040037}
Vishnu Nair00b90132021-11-05 14:03:40 -070038
Kean Mariotti29aad4e2023-09-20 12:53:33 +000039LayerTracing::LayerTracing(std::ostream& outStream) : LayerTracing() {
40 mOutStream = std::ref(outStream);
41}
42
Kean Mariotti639b54f2023-04-20 12:06:29 +000043LayerTracing::~LayerTracing() {
44 LayerDataSource::UnregisterLayerTracing();
45}
Vishnu Nair00b90132021-11-05 14:03:40 -070046
Kean Mariotti639b54f2023-04-20 12:06:29 +000047void LayerTracing::setTakeLayersSnapshotProtoFunction(
Kean Mariottifc0cd252023-12-07 09:27:40 +000048 const std::function<void(uint32_t, const OnLayersSnapshotCallback&)>& callback) {
Kean Mariotti639b54f2023-04-20 12:06:29 +000049 mTakeLayersSnapshotProto = callback;
50}
51
52void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
53 mTransactionTracing = &transactionTracing;
54}
55
Kean Mariotti639b54f2023-04-20 12:06:29 +000056void LayerTracing::onStart(Mode mode, uint32_t flags) {
57 switch (mode) {
58 case Mode::MODE_ACTIVE: {
59 mActiveTracingFlags.store(flags);
60 mIsActiveTracingStarted.store(true);
61 ALOGV("Starting active tracing (waiting for initial snapshot)");
62 // It might take a while before a layers change occurs and a "spontaneous" snapshot is
63 // taken. Let's manually take a snapshot, so that the trace's first entry will contain
64 // the current layers state.
Kean Mariottifc0cd252023-12-07 09:27:40 +000065 auto onLayersSnapshot = [this](perfetto::protos::LayersSnapshotProto&& snapshot) {
66 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_ACTIVE);
67 };
68 mTakeLayersSnapshotProto(flags, onLayersSnapshot);
Kean Mariotti8c5abc82023-09-20 09:28:07 +000069 ALOGD("Started active tracing (traced initial snapshot)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000070 break;
71 }
72 case Mode::MODE_GENERATED: {
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +000073 // This tracing mode processes the buffer of transactions (owned by TransactionTracing),
74 // generates layers snapshots and writes them to perfetto. This happens every time an
75 // OnFlush event is received.
Kean Mariotti8c5abc82023-09-20 09:28:07 +000076 ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000077 break;
78 }
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +000079 case Mode::MODE_GENERATED_BUGREPORT_ONLY: {
80 // Same as MODE_GENERATED, but only when the received OnFlush event is due to a
81 // bugreport being taken. This mode exists because the generated layers trace is very
82 // large (hundreds of MB), hence we want to include it only in bugreports and not in
83 // field uploads.
84 //
85 // Note that perfetto communicates only whether the OnFlush event is due to a bugreport
86 // or not, hence we need an additional "bugreport only" tracing mode.
87 // If perfetto had communicated when the OnFlush is due to a field upload, then we could
88 // have had a single "generated" tracing mode that would have been a noop in case of
89 // field uploads.
90 ALOGD("Started 'generated bugreport only' tracing"
91 " (waiting for bugreport's OnFlush event to generate layers)");
92 break;
93 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000094 case Mode::MODE_DUMP: {
Kean Mariottifc0cd252023-12-07 09:27:40 +000095 ALOGD("Started dump tracing");
Kean Mariotti639b54f2023-04-20 12:06:29 +000096 break;
97 }
98 default: {
99 ALOGE("Started unknown tracing mode (0x%02x)", mode);
100 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700101 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700102}
103
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000104void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000105 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000106 // generate layers snapshots and write them to perfetto.
107 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
108 ALOGD("Skipping layers trace generation (not a 'generated' tracing session)");
109 return;
110 }
111
112 // In "generated bugreport only" mode skip the layers snapshot generation
113 // if the perfetto's OnFlush event is not due to a bugreport being taken.
114 if (mode == Mode::MODE_GENERATED_BUGREPORT_ONLY && !isBugreport) {
115 ALOGD("Skipping layers trace generation (not a bugreport OnFlush event)");
Kean Mariotti639b54f2023-04-20 12:06:29 +0000116 return;
Vishnu Nair00b90132021-11-05 14:03:40 -0700117 }
Kean Mariotti639b54f2023-04-20 12:06:29 +0000118
119 if (!mTransactionTracing) {
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000120 ALOGD("Skipping layers trace generation (transactions tracing disabled)");
Kean Mariotti639b54f2023-04-20 12:06:29 +0000121 return;
Vishnu Naircb565332023-03-14 21:10:55 -0700122 }
Kean Mariotti639b54f2023-04-20 12:06:29 +0000123
124 auto transactionTrace = mTransactionTracing->writeToProto();
Kean Mariotti29aad4e2023-09-20 12:53:33 +0000125 LayerTraceGenerator{}.generate(transactionTrace, flags, *this);
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000126 ALOGD("Flushed generated tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700127}
128
Kean Mariottifc0cd252023-12-07 09:27:40 +0000129void LayerTracing::onStop(Mode mode, uint32_t flags, std::function<void()>&& deferredStopDone) {
130 switch (mode) {
131 case Mode::MODE_ACTIVE: {
132 mIsActiveTracingStarted.store(false);
133 deferredStopDone();
134 ALOGD("Stopped active tracing");
135 break;
136 }
137 case Mode::MODE_DUMP: {
138 auto onLayersSnapshot = [this, deferredStopDone = std::move(deferredStopDone)](
139 perfetto::protos::LayersSnapshotProto&& snapshot) {
140 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
141 deferredStopDone();
142 ALOGD("Stopped dump tracing (written single snapshot)");
143 };
144 mTakeLayersSnapshotProto(flags, onLayersSnapshot);
145 break;
146 }
147 default: {
148 deferredStopDone();
149 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700150 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700151}
152
Kean Mariotti639b54f2023-04-20 12:06:29 +0000153void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
154 Mode mode) {
Vishnu Nairbe0ad902024-06-27 23:38:43 +0000155 SFTRACE_CALL();
Kean Mariotti639b54f2023-04-20 12:06:29 +0000156 if (mOutStream) {
157 writeSnapshotToStream(std::move(snapshot));
158 } else {
159 writeSnapshotToPerfetto(snapshot, mode);
160 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700161}
162
Kean Mariotti639b54f2023-04-20 12:06:29 +0000163bool LayerTracing::isActiveTracingStarted() const {
164 return mIsActiveTracingStarted.load();
Vishnu Nair00b90132021-11-05 14:03:40 -0700165}
166
Kean Mariotti639b54f2023-04-20 12:06:29 +0000167uint32_t LayerTracing::getActiveTracingFlags() const {
168 return mActiveTracingFlags.load();
Vishnu Nair81750622023-03-08 15:02:06 -0800169}
Vishnu Nair00b90132021-11-05 14:03:40 -0700170
Kean Mariotti639b54f2023-04-20 12:06:29 +0000171bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
172 return (mActiveTracingFlags.load() & flag) != 0;
173}
174
175perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
176 perfetto::protos::LayersTraceFileProto fileProto;
177 fileProto.set_magic_number(
178 static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
179 << 32 |
180 perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
181 auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
182 systemTime(SYSTEM_TIME_MONOTONIC));
Kean Mariottic44fdaf2022-07-29 14:20:39 +0000183 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair00b90132021-11-05 14:03:40 -0700184 return fileProto;
185}
186
Kean Mariotti639b54f2023-04-20 12:06:29 +0000187void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
188 auto fileProto = createTraceFileProto();
189 *fileProto.add_entry() = std::move(snapshot);
190 mOutStream->get() << fileProto.SerializeAsString();
Vishnu Nair00b90132021-11-05 14:03:40 -0700191}
192
Kean Mariotti639b54f2023-04-20 12:06:29 +0000193void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000194 Mode srcMode) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000195 const auto snapshotBytes = snapshot.SerializeAsString();
196
197 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000198 auto dstMode = context.GetCustomTlsState()->mMode;
199 if (srcMode == Mode::MODE_GENERATED) {
200 // Layers snapshots produced by LayerTraceGenerator have srcMode == MODE_GENERATED
201 // and should be written to tracing sessions with MODE_GENERATED
202 // or MODE_GENERATED_BUGREPORT_ONLY.
203 if (dstMode != Mode::MODE_GENERATED && dstMode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
204 return;
205 }
206 } else if (srcMode != dstMode) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000207 return;
208 }
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000209
210 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000211 return;
212 }
213 {
214 auto packet = context.NewTracePacket();
215 packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
216 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
217 auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
218 snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
219 }
220 {
221 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
222 // It is currently needed in order not to lose the last trace entry.
223 context.NewTracePacket();
224 }
225 });
226}
227
228bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
229 // In some situations (e.g. two bugreports taken shortly one after the other) the generated
230 // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
231 // sure that in generated tracing mode a given snapshot is written only once to perfetto.
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000232 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000233 return true;
Vishnu Nair00b90132021-11-05 14:03:40 -0700234 }
235
Kean Mariotti639b54f2023-04-20 12:06:29 +0000236 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
237 while (lastVsyncId < vsyncId) {
238 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
239 return true;
240 }
Vishnu Nairb64a3b42022-01-13 15:29:32 -0800241 }
242
Kean Mariotti639b54f2023-04-20 12:06:29 +0000243 return false;
Vishnu Nair00b90132021-11-05 14:03:40 -0700244}
245
246} // namespace android