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 #undef LOG_TAG
18 #define LOG_TAG "LayerTracing"
19 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21 #include "LayerTracing.h"
22
23 #include "LayerDataSource.h"
24 #include "Tracing/tools/LayerTraceGenerator.h"
25 #include "TransactionTracing.h"
26
27 #include <common/trace.h>
28 #include <log/log.h>
29 #include <perfetto/tracing.h>
30 #include <utils/Timers.h>
31
32 namespace android {
33
LayerTracing()34 LayerTracing::LayerTracing() {
35 mTakeLayersSnapshotProto = [](uint32_t, const OnLayersSnapshotCallback&) {};
36 LayerDataSource::Initialize(*this);
37 }
38
LayerTracing(std::ostream & outStream)39 LayerTracing::LayerTracing(std::ostream& outStream) : LayerTracing() {
40 mOutStream = std::ref(outStream);
41 }
42
~LayerTracing()43 LayerTracing::~LayerTracing() {
44 LayerDataSource::UnregisterLayerTracing();
45 }
46
setTakeLayersSnapshotProtoFunction(const std::function<void (uint32_t,const OnLayersSnapshotCallback &)> & callback)47 void LayerTracing::setTakeLayersSnapshotProtoFunction(
48 const std::function<void(uint32_t, const OnLayersSnapshotCallback&)>& callback) {
49 mTakeLayersSnapshotProto = callback;
50 }
51
setTransactionTracing(TransactionTracing & transactionTracing)52 void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
53 mTransactionTracing = &transactionTracing;
54 }
55
onStart(Mode mode,uint32_t flags)56 void 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.
65 auto onLayersSnapshot = [this](perfetto::protos::LayersSnapshotProto&& snapshot) {
66 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_ACTIVE);
67 };
68 mTakeLayersSnapshotProto(flags, onLayersSnapshot);
69 ALOGD("Started active tracing (traced initial snapshot)");
70 break;
71 }
72 case Mode::MODE_GENERATED: {
73 // 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.
76 ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
77 break;
78 }
79 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 }
94 case Mode::MODE_DUMP: {
95 ALOGD("Started dump tracing");
96 break;
97 }
98 default: {
99 ALOGE("Started unknown tracing mode (0x%02x)", mode);
100 }
101 }
102 }
103
onFlush(Mode mode,uint32_t flags,bool isBugreport)104 void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
105 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
106 // 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)");
116 return;
117 }
118
119 if (!mTransactionTracing) {
120 ALOGD("Skipping layers trace generation (transactions tracing disabled)");
121 return;
122 }
123
124 auto transactionTrace = mTransactionTracing->writeToProto();
125 LayerTraceGenerator{}.generate(transactionTrace, flags, *this);
126 ALOGD("Flushed generated tracing");
127 }
128
onStop(Mode mode,uint32_t flags,std::function<void ()> && deferredStopDone)129 void 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 }
150 }
151 }
152
addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto && snapshot,Mode mode)153 void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
154 Mode mode) {
155 SFTRACE_CALL();
156 if (mOutStream) {
157 writeSnapshotToStream(std::move(snapshot));
158 } else {
159 writeSnapshotToPerfetto(snapshot, mode);
160 }
161 }
162
isActiveTracingStarted() const163 bool LayerTracing::isActiveTracingStarted() const {
164 return mIsActiveTracingStarted.load();
165 }
166
getActiveTracingFlags() const167 uint32_t LayerTracing::getActiveTracingFlags() const {
168 return mActiveTracingFlags.load();
169 }
170
isActiveTracingFlagSet(Flag flag) const171 bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
172 return (mActiveTracingFlags.load() & flag) != 0;
173 }
174
createTraceFileProto()175 perfetto::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));
183 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
184 return fileProto;
185 }
186
writeSnapshotToStream(perfetto::protos::LayersSnapshotProto && snapshot) const187 void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
188 auto fileProto = createTraceFileProto();
189 *fileProto.add_entry() = std::move(snapshot);
190 mOutStream->get() << fileProto.SerializeAsString();
191 }
192
writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto & snapshot,Mode srcMode)193 void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
194 Mode srcMode) {
195 const auto snapshotBytes = snapshot.SerializeAsString();
196
197 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
198 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) {
207 return;
208 }
209
210 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
211 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
checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode,std::int64_t vsyncId)228 bool 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.
232 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
233 return true;
234 }
235
236 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
237 while (lastVsyncId < vsyncId) {
238 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
239 return true;
240 }
241 }
242
243 return false;
244 }
245
246 } // namespace android
247