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 <log/log.h>
28 #include <perfetto/tracing.h>
29 #include <utils/Timers.h>
30 #include <utils/Trace.h>
31
32 namespace android {
33
LayerTracing()34 LayerTracing::LayerTracing() {
35 mTakeLayersSnapshotProto = [](uint32_t) { return perfetto::protos::LayersSnapshotProto{}; };
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<perfetto::protos::LayersSnapshotProto (uint32_t)> & callback)47 void LayerTracing::setTakeLayersSnapshotProtoFunction(
48 const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& 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 addProtoSnapshotToOstream(mTakeLayersSnapshotProto(flags), Mode::MODE_ACTIVE);
66 ALOGD("Started active tracing (traced initial snapshot)");
67 break;
68 }
69 case Mode::MODE_GENERATED: {
70 // This tracing mode processes the buffer of transactions (owned by TransactionTracing),
71 // generates layers snapshots and writes them to perfetto. This happens every time an
72 // OnFlush event is received.
73 ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
74 break;
75 }
76 case Mode::MODE_GENERATED_BUGREPORT_ONLY: {
77 // Same as MODE_GENERATED, but only when the received OnFlush event is due to a
78 // bugreport being taken. This mode exists because the generated layers trace is very
79 // large (hundreds of MB), hence we want to include it only in bugreports and not in
80 // field uploads.
81 //
82 // Note that perfetto communicates only whether the OnFlush event is due to a bugreport
83 // or not, hence we need an additional "bugreport only" tracing mode.
84 // If perfetto had communicated when the OnFlush is due to a field upload, then we could
85 // have had a single "generated" tracing mode that would have been a noop in case of
86 // field uploads.
87 ALOGD("Started 'generated bugreport only' tracing"
88 " (waiting for bugreport's OnFlush event to generate layers)");
89 break;
90 }
91 case Mode::MODE_DUMP: {
92 auto snapshot = mTakeLayersSnapshotProto(flags);
93 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
94 ALOGD("Started dump tracing (dumped single snapshot)");
95 break;
96 }
97 default: {
98 ALOGE("Started unknown tracing mode (0x%02x)", mode);
99 }
100 }
101 }
102
onFlush(Mode mode,uint32_t flags,bool isBugreport)103 void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
104 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
105 // generate layers snapshots and write them to perfetto.
106 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
107 ALOGD("Skipping layers trace generation (not a 'generated' tracing session)");
108 return;
109 }
110
111 // In "generated bugreport only" mode skip the layers snapshot generation
112 // if the perfetto's OnFlush event is not due to a bugreport being taken.
113 if (mode == Mode::MODE_GENERATED_BUGREPORT_ONLY && !isBugreport) {
114 ALOGD("Skipping layers trace generation (not a bugreport OnFlush event)");
115 return;
116 }
117
118 if (!mTransactionTracing) {
119 ALOGD("Skipping layers trace generation (transactions tracing disabled)");
120 return;
121 }
122
123 auto transactionTrace = mTransactionTracing->writeToProto();
124 LayerTraceGenerator{}.generate(transactionTrace, flags, *this);
125 ALOGD("Flushed generated tracing");
126 }
127
onStop(Mode mode)128 void LayerTracing::onStop(Mode mode) {
129 if (mode == Mode::MODE_ACTIVE) {
130 mIsActiveTracingStarted.store(false);
131 ALOGD("Stopped active tracing");
132 }
133 }
134
addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto && snapshot,Mode mode)135 void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
136 Mode mode) {
137 ATRACE_CALL();
138 if (mOutStream) {
139 writeSnapshotToStream(std::move(snapshot));
140 } else {
141 writeSnapshotToPerfetto(snapshot, mode);
142 }
143 }
144
isActiveTracingStarted() const145 bool LayerTracing::isActiveTracingStarted() const {
146 return mIsActiveTracingStarted.load();
147 }
148
getActiveTracingFlags() const149 uint32_t LayerTracing::getActiveTracingFlags() const {
150 return mActiveTracingFlags.load();
151 }
152
isActiveTracingFlagSet(Flag flag) const153 bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
154 return (mActiveTracingFlags.load() & flag) != 0;
155 }
156
createTraceFileProto()157 perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
158 perfetto::protos::LayersTraceFileProto fileProto;
159 fileProto.set_magic_number(
160 static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
161 << 32 |
162 perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
163 auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
164 systemTime(SYSTEM_TIME_MONOTONIC));
165 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
166 return fileProto;
167 }
168
writeSnapshotToStream(perfetto::protos::LayersSnapshotProto && snapshot) const169 void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
170 auto fileProto = createTraceFileProto();
171 *fileProto.add_entry() = std::move(snapshot);
172 mOutStream->get() << fileProto.SerializeAsString();
173 }
174
writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto & snapshot,Mode srcMode)175 void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
176 Mode srcMode) {
177 const auto snapshotBytes = snapshot.SerializeAsString();
178
179 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
180 auto dstMode = context.GetCustomTlsState()->mMode;
181 if (srcMode == Mode::MODE_GENERATED) {
182 // Layers snapshots produced by LayerTraceGenerator have srcMode == MODE_GENERATED
183 // and should be written to tracing sessions with MODE_GENERATED
184 // or MODE_GENERATED_BUGREPORT_ONLY.
185 if (dstMode != Mode::MODE_GENERATED && dstMode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
186 return;
187 }
188 } else if (srcMode != dstMode) {
189 return;
190 }
191
192 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
193 return;
194 }
195 {
196 auto packet = context.NewTracePacket();
197 packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
198 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
199 auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
200 snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
201 }
202 {
203 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
204 // It is currently needed in order not to lose the last trace entry.
205 context.NewTracePacket();
206 }
207 });
208 }
209
checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode,std::int64_t vsyncId)210 bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
211 // In some situations (e.g. two bugreports taken shortly one after the other) the generated
212 // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
213 // sure that in generated tracing mode a given snapshot is written only once to perfetto.
214 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
215 return true;
216 }
217
218 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
219 while (lastVsyncId < vsyncId) {
220 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
221 return true;
222 }
223 }
224
225 return false;
226 }
227
228 } // namespace android
229