• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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