xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/Tracing/LayerTracing.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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