1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #undef LOG_TAG
18*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "LayerTracing"
19*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include "LayerTracing.h"
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include "LayerDataSource.h"
24*38e8c45fSAndroid Build Coastguard Worker #include "Tracing/tools/LayerTraceGenerator.h"
25*38e8c45fSAndroid Build Coastguard Worker #include "TransactionTracing.h"
26*38e8c45fSAndroid Build Coastguard Worker
27*38e8c45fSAndroid Build Coastguard Worker #include <common/trace.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <log/log.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <perfetto/tracing.h>
30*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h>
31*38e8c45fSAndroid Build Coastguard Worker
32*38e8c45fSAndroid Build Coastguard Worker namespace android {
33*38e8c45fSAndroid Build Coastguard Worker
LayerTracing()34*38e8c45fSAndroid Build Coastguard Worker LayerTracing::LayerTracing() {
35*38e8c45fSAndroid Build Coastguard Worker mTakeLayersSnapshotProto = [](uint32_t, const OnLayersSnapshotCallback&) {};
36*38e8c45fSAndroid Build Coastguard Worker LayerDataSource::Initialize(*this);
37*38e8c45fSAndroid Build Coastguard Worker }
38*38e8c45fSAndroid Build Coastguard Worker
LayerTracing(std::ostream & outStream)39*38e8c45fSAndroid Build Coastguard Worker LayerTracing::LayerTracing(std::ostream& outStream) : LayerTracing() {
40*38e8c45fSAndroid Build Coastguard Worker mOutStream = std::ref(outStream);
41*38e8c45fSAndroid Build Coastguard Worker }
42*38e8c45fSAndroid Build Coastguard Worker
~LayerTracing()43*38e8c45fSAndroid Build Coastguard Worker LayerTracing::~LayerTracing() {
44*38e8c45fSAndroid Build Coastguard Worker LayerDataSource::UnregisterLayerTracing();
45*38e8c45fSAndroid Build Coastguard Worker }
46*38e8c45fSAndroid Build Coastguard Worker
setTakeLayersSnapshotProtoFunction(const std::function<void (uint32_t,const OnLayersSnapshotCallback &)> & callback)47*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::setTakeLayersSnapshotProtoFunction(
48*38e8c45fSAndroid Build Coastguard Worker const std::function<void(uint32_t, const OnLayersSnapshotCallback&)>& callback) {
49*38e8c45fSAndroid Build Coastguard Worker mTakeLayersSnapshotProto = callback;
50*38e8c45fSAndroid Build Coastguard Worker }
51*38e8c45fSAndroid Build Coastguard Worker
setTransactionTracing(TransactionTracing & transactionTracing)52*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
53*38e8c45fSAndroid Build Coastguard Worker mTransactionTracing = &transactionTracing;
54*38e8c45fSAndroid Build Coastguard Worker }
55*38e8c45fSAndroid Build Coastguard Worker
onStart(Mode mode,uint32_t flags)56*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::onStart(Mode mode, uint32_t flags) {
57*38e8c45fSAndroid Build Coastguard Worker switch (mode) {
58*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_ACTIVE: {
59*38e8c45fSAndroid Build Coastguard Worker mActiveTracingFlags.store(flags);
60*38e8c45fSAndroid Build Coastguard Worker mIsActiveTracingStarted.store(true);
61*38e8c45fSAndroid Build Coastguard Worker ALOGV("Starting active tracing (waiting for initial snapshot)");
62*38e8c45fSAndroid Build Coastguard Worker // It might take a while before a layers change occurs and a "spontaneous" snapshot is
63*38e8c45fSAndroid Build Coastguard Worker // taken. Let's manually take a snapshot, so that the trace's first entry will contain
64*38e8c45fSAndroid Build Coastguard Worker // the current layers state.
65*38e8c45fSAndroid Build Coastguard Worker auto onLayersSnapshot = [this](perfetto::protos::LayersSnapshotProto&& snapshot) {
66*38e8c45fSAndroid Build Coastguard Worker addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_ACTIVE);
67*38e8c45fSAndroid Build Coastguard Worker };
68*38e8c45fSAndroid Build Coastguard Worker mTakeLayersSnapshotProto(flags, onLayersSnapshot);
69*38e8c45fSAndroid Build Coastguard Worker ALOGD("Started active tracing (traced initial snapshot)");
70*38e8c45fSAndroid Build Coastguard Worker break;
71*38e8c45fSAndroid Build Coastguard Worker }
72*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_GENERATED: {
73*38e8c45fSAndroid Build Coastguard Worker // This tracing mode processes the buffer of transactions (owned by TransactionTracing),
74*38e8c45fSAndroid Build Coastguard Worker // generates layers snapshots and writes them to perfetto. This happens every time an
75*38e8c45fSAndroid Build Coastguard Worker // OnFlush event is received.
76*38e8c45fSAndroid Build Coastguard Worker ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
77*38e8c45fSAndroid Build Coastguard Worker break;
78*38e8c45fSAndroid Build Coastguard Worker }
79*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_GENERATED_BUGREPORT_ONLY: {
80*38e8c45fSAndroid Build Coastguard Worker // Same as MODE_GENERATED, but only when the received OnFlush event is due to a
81*38e8c45fSAndroid Build Coastguard Worker // bugreport being taken. This mode exists because the generated layers trace is very
82*38e8c45fSAndroid Build Coastguard Worker // large (hundreds of MB), hence we want to include it only in bugreports and not in
83*38e8c45fSAndroid Build Coastguard Worker // field uploads.
84*38e8c45fSAndroid Build Coastguard Worker //
85*38e8c45fSAndroid Build Coastguard Worker // Note that perfetto communicates only whether the OnFlush event is due to a bugreport
86*38e8c45fSAndroid Build Coastguard Worker // or not, hence we need an additional "bugreport only" tracing mode.
87*38e8c45fSAndroid Build Coastguard Worker // If perfetto had communicated when the OnFlush is due to a field upload, then we could
88*38e8c45fSAndroid Build Coastguard Worker // have had a single "generated" tracing mode that would have been a noop in case of
89*38e8c45fSAndroid Build Coastguard Worker // field uploads.
90*38e8c45fSAndroid Build Coastguard Worker ALOGD("Started 'generated bugreport only' tracing"
91*38e8c45fSAndroid Build Coastguard Worker " (waiting for bugreport's OnFlush event to generate layers)");
92*38e8c45fSAndroid Build Coastguard Worker break;
93*38e8c45fSAndroid Build Coastguard Worker }
94*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_DUMP: {
95*38e8c45fSAndroid Build Coastguard Worker ALOGD("Started dump tracing");
96*38e8c45fSAndroid Build Coastguard Worker break;
97*38e8c45fSAndroid Build Coastguard Worker }
98*38e8c45fSAndroid Build Coastguard Worker default: {
99*38e8c45fSAndroid Build Coastguard Worker ALOGE("Started unknown tracing mode (0x%02x)", mode);
100*38e8c45fSAndroid Build Coastguard Worker }
101*38e8c45fSAndroid Build Coastguard Worker }
102*38e8c45fSAndroid Build Coastguard Worker }
103*38e8c45fSAndroid Build Coastguard Worker
onFlush(Mode mode,uint32_t flags,bool isBugreport)104*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
105*38e8c45fSAndroid Build Coastguard Worker // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
106*38e8c45fSAndroid Build Coastguard Worker // generate layers snapshots and write them to perfetto.
107*38e8c45fSAndroid Build Coastguard Worker if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
108*38e8c45fSAndroid Build Coastguard Worker ALOGD("Skipping layers trace generation (not a 'generated' tracing session)");
109*38e8c45fSAndroid Build Coastguard Worker return;
110*38e8c45fSAndroid Build Coastguard Worker }
111*38e8c45fSAndroid Build Coastguard Worker
112*38e8c45fSAndroid Build Coastguard Worker // In "generated bugreport only" mode skip the layers snapshot generation
113*38e8c45fSAndroid Build Coastguard Worker // if the perfetto's OnFlush event is not due to a bugreport being taken.
114*38e8c45fSAndroid Build Coastguard Worker if (mode == Mode::MODE_GENERATED_BUGREPORT_ONLY && !isBugreport) {
115*38e8c45fSAndroid Build Coastguard Worker ALOGD("Skipping layers trace generation (not a bugreport OnFlush event)");
116*38e8c45fSAndroid Build Coastguard Worker return;
117*38e8c45fSAndroid Build Coastguard Worker }
118*38e8c45fSAndroid Build Coastguard Worker
119*38e8c45fSAndroid Build Coastguard Worker if (!mTransactionTracing) {
120*38e8c45fSAndroid Build Coastguard Worker ALOGD("Skipping layers trace generation (transactions tracing disabled)");
121*38e8c45fSAndroid Build Coastguard Worker return;
122*38e8c45fSAndroid Build Coastguard Worker }
123*38e8c45fSAndroid Build Coastguard Worker
124*38e8c45fSAndroid Build Coastguard Worker auto transactionTrace = mTransactionTracing->writeToProto();
125*38e8c45fSAndroid Build Coastguard Worker LayerTraceGenerator{}.generate(transactionTrace, flags, *this);
126*38e8c45fSAndroid Build Coastguard Worker ALOGD("Flushed generated tracing");
127*38e8c45fSAndroid Build Coastguard Worker }
128*38e8c45fSAndroid Build Coastguard Worker
onStop(Mode mode,uint32_t flags,std::function<void ()> && deferredStopDone)129*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::onStop(Mode mode, uint32_t flags, std::function<void()>&& deferredStopDone) {
130*38e8c45fSAndroid Build Coastguard Worker switch (mode) {
131*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_ACTIVE: {
132*38e8c45fSAndroid Build Coastguard Worker mIsActiveTracingStarted.store(false);
133*38e8c45fSAndroid Build Coastguard Worker deferredStopDone();
134*38e8c45fSAndroid Build Coastguard Worker ALOGD("Stopped active tracing");
135*38e8c45fSAndroid Build Coastguard Worker break;
136*38e8c45fSAndroid Build Coastguard Worker }
137*38e8c45fSAndroid Build Coastguard Worker case Mode::MODE_DUMP: {
138*38e8c45fSAndroid Build Coastguard Worker auto onLayersSnapshot = [this, deferredStopDone = std::move(deferredStopDone)](
139*38e8c45fSAndroid Build Coastguard Worker perfetto::protos::LayersSnapshotProto&& snapshot) {
140*38e8c45fSAndroid Build Coastguard Worker addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
141*38e8c45fSAndroid Build Coastguard Worker deferredStopDone();
142*38e8c45fSAndroid Build Coastguard Worker ALOGD("Stopped dump tracing (written single snapshot)");
143*38e8c45fSAndroid Build Coastguard Worker };
144*38e8c45fSAndroid Build Coastguard Worker mTakeLayersSnapshotProto(flags, onLayersSnapshot);
145*38e8c45fSAndroid Build Coastguard Worker break;
146*38e8c45fSAndroid Build Coastguard Worker }
147*38e8c45fSAndroid Build Coastguard Worker default: {
148*38e8c45fSAndroid Build Coastguard Worker deferredStopDone();
149*38e8c45fSAndroid Build Coastguard Worker }
150*38e8c45fSAndroid Build Coastguard Worker }
151*38e8c45fSAndroid Build Coastguard Worker }
152*38e8c45fSAndroid Build Coastguard Worker
addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto && snapshot,Mode mode)153*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
154*38e8c45fSAndroid Build Coastguard Worker Mode mode) {
155*38e8c45fSAndroid Build Coastguard Worker SFTRACE_CALL();
156*38e8c45fSAndroid Build Coastguard Worker if (mOutStream) {
157*38e8c45fSAndroid Build Coastguard Worker writeSnapshotToStream(std::move(snapshot));
158*38e8c45fSAndroid Build Coastguard Worker } else {
159*38e8c45fSAndroid Build Coastguard Worker writeSnapshotToPerfetto(snapshot, mode);
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker }
162*38e8c45fSAndroid Build Coastguard Worker
isActiveTracingStarted() const163*38e8c45fSAndroid Build Coastguard Worker bool LayerTracing::isActiveTracingStarted() const {
164*38e8c45fSAndroid Build Coastguard Worker return mIsActiveTracingStarted.load();
165*38e8c45fSAndroid Build Coastguard Worker }
166*38e8c45fSAndroid Build Coastguard Worker
getActiveTracingFlags() const167*38e8c45fSAndroid Build Coastguard Worker uint32_t LayerTracing::getActiveTracingFlags() const {
168*38e8c45fSAndroid Build Coastguard Worker return mActiveTracingFlags.load();
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker
isActiveTracingFlagSet(Flag flag) const171*38e8c45fSAndroid Build Coastguard Worker bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
172*38e8c45fSAndroid Build Coastguard Worker return (mActiveTracingFlags.load() & flag) != 0;
173*38e8c45fSAndroid Build Coastguard Worker }
174*38e8c45fSAndroid Build Coastguard Worker
createTraceFileProto()175*38e8c45fSAndroid Build Coastguard Worker perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
176*38e8c45fSAndroid Build Coastguard Worker perfetto::protos::LayersTraceFileProto fileProto;
177*38e8c45fSAndroid Build Coastguard Worker fileProto.set_magic_number(
178*38e8c45fSAndroid Build Coastguard Worker static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
179*38e8c45fSAndroid Build Coastguard Worker << 32 |
180*38e8c45fSAndroid Build Coastguard Worker perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
181*38e8c45fSAndroid Build Coastguard Worker auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
182*38e8c45fSAndroid Build Coastguard Worker systemTime(SYSTEM_TIME_MONOTONIC));
183*38e8c45fSAndroid Build Coastguard Worker fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
184*38e8c45fSAndroid Build Coastguard Worker return fileProto;
185*38e8c45fSAndroid Build Coastguard Worker }
186*38e8c45fSAndroid Build Coastguard Worker
writeSnapshotToStream(perfetto::protos::LayersSnapshotProto && snapshot) const187*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
188*38e8c45fSAndroid Build Coastguard Worker auto fileProto = createTraceFileProto();
189*38e8c45fSAndroid Build Coastguard Worker *fileProto.add_entry() = std::move(snapshot);
190*38e8c45fSAndroid Build Coastguard Worker mOutStream->get() << fileProto.SerializeAsString();
191*38e8c45fSAndroid Build Coastguard Worker }
192*38e8c45fSAndroid Build Coastguard Worker
writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto & snapshot,Mode srcMode)193*38e8c45fSAndroid Build Coastguard Worker void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
194*38e8c45fSAndroid Build Coastguard Worker Mode srcMode) {
195*38e8c45fSAndroid Build Coastguard Worker const auto snapshotBytes = snapshot.SerializeAsString();
196*38e8c45fSAndroid Build Coastguard Worker
197*38e8c45fSAndroid Build Coastguard Worker LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
198*38e8c45fSAndroid Build Coastguard Worker auto dstMode = context.GetCustomTlsState()->mMode;
199*38e8c45fSAndroid Build Coastguard Worker if (srcMode == Mode::MODE_GENERATED) {
200*38e8c45fSAndroid Build Coastguard Worker // Layers snapshots produced by LayerTraceGenerator have srcMode == MODE_GENERATED
201*38e8c45fSAndroid Build Coastguard Worker // and should be written to tracing sessions with MODE_GENERATED
202*38e8c45fSAndroid Build Coastguard Worker // or MODE_GENERATED_BUGREPORT_ONLY.
203*38e8c45fSAndroid Build Coastguard Worker if (dstMode != Mode::MODE_GENERATED && dstMode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
204*38e8c45fSAndroid Build Coastguard Worker return;
205*38e8c45fSAndroid Build Coastguard Worker }
206*38e8c45fSAndroid Build Coastguard Worker } else if (srcMode != dstMode) {
207*38e8c45fSAndroid Build Coastguard Worker return;
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker
210*38e8c45fSAndroid Build Coastguard Worker if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
211*38e8c45fSAndroid Build Coastguard Worker return;
212*38e8c45fSAndroid Build Coastguard Worker }
213*38e8c45fSAndroid Build Coastguard Worker {
214*38e8c45fSAndroid Build Coastguard Worker auto packet = context.NewTracePacket();
215*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
216*38e8c45fSAndroid Build Coastguard Worker packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
217*38e8c45fSAndroid Build Coastguard Worker auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
218*38e8c45fSAndroid Build Coastguard Worker snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
219*38e8c45fSAndroid Build Coastguard Worker }
220*38e8c45fSAndroid Build Coastguard Worker {
221*38e8c45fSAndroid Build Coastguard Worker // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
222*38e8c45fSAndroid Build Coastguard Worker // It is currently needed in order not to lose the last trace entry.
223*38e8c45fSAndroid Build Coastguard Worker context.NewTracePacket();
224*38e8c45fSAndroid Build Coastguard Worker }
225*38e8c45fSAndroid Build Coastguard Worker });
226*38e8c45fSAndroid Build Coastguard Worker }
227*38e8c45fSAndroid Build Coastguard Worker
checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode,std::int64_t vsyncId)228*38e8c45fSAndroid Build Coastguard Worker bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
229*38e8c45fSAndroid Build Coastguard Worker // In some situations (e.g. two bugreports taken shortly one after the other) the generated
230*38e8c45fSAndroid Build Coastguard Worker // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
231*38e8c45fSAndroid Build Coastguard Worker // sure that in generated tracing mode a given snapshot is written only once to perfetto.
232*38e8c45fSAndroid Build Coastguard Worker if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
233*38e8c45fSAndroid Build Coastguard Worker return true;
234*38e8c45fSAndroid Build Coastguard Worker }
235*38e8c45fSAndroid Build Coastguard Worker
236*38e8c45fSAndroid Build Coastguard Worker auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
237*38e8c45fSAndroid Build Coastguard Worker while (lastVsyncId < vsyncId) {
238*38e8c45fSAndroid Build Coastguard Worker if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
239*38e8c45fSAndroid Build Coastguard Worker return true;
240*38e8c45fSAndroid Build Coastguard Worker }
241*38e8c45fSAndroid Build Coastguard Worker }
242*38e8c45fSAndroid Build Coastguard Worker
243*38e8c45fSAndroid Build Coastguard Worker return false;
244*38e8c45fSAndroid Build Coastguard Worker }
245*38e8c45fSAndroid Build Coastguard Worker
246*38e8c45fSAndroid Build Coastguard Worker } // namespace android
247