blob: 41bcdf05c352d1d2375399963247fa4faddfd0a5 [file] [log] [blame]
Vishnu Nair00b90132021-11-05 14:03:40 -07001/*
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
Diwas Sharma69758342023-09-01 00:40:19 +000021#include "LayerTracing.h"
Kean Mariotti639b54f2023-04-20 12:06:29 +000022
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>
Diwas Sharma69758342023-09-01 00:40:19 +000031
Vishnu Nair00b90132021-11-05 14:03:40 -070032namespace android {
33
Kean Mariotti639b54f2023-04-20 12:06:29 +000034LayerTracing::LayerTracing() {
35 mTakeLayersSnapshotProto = [](uint32_t) { return perfetto::protos::LayersSnapshotProto{}; };
36 LayerDataSource::Initialize(*this);
John Reck2a3d29d2023-08-17 17:45:01 -040037}
Vishnu Nair00b90132021-11-05 14:03:40 -070038
Kean Mariotti29aad4e2023-09-20 12:53:33 +000039LayerTracing::LayerTracing(std::ostream& outStream) : LayerTracing() {
40 mOutStream = std::ref(outStream);
41}
42
Kean Mariotti639b54f2023-04-20 12:06:29 +000043LayerTracing::~LayerTracing() {
44 LayerDataSource::UnregisterLayerTracing();
45}
Vishnu Nair00b90132021-11-05 14:03:40 -070046
Kean Mariotti639b54f2023-04-20 12:06:29 +000047void LayerTracing::setTakeLayersSnapshotProtoFunction(
48 const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& callback) {
49 mTakeLayersSnapshotProto = callback;
50}
51
52void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
53 mTransactionTracing = &transactionTracing;
54}
55
Kean Mariotti639b54f2023-04-20 12:06:29 +000056void 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);
Kean Mariotti8c5abc82023-09-20 09:28:07 +000066 ALOGD("Started active tracing (traced initial snapshot)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000067 break;
68 }
69 case Mode::MODE_GENERATED: {
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +000070 // 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.
Kean Mariotti8c5abc82023-09-20 09:28:07 +000073 ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000074 break;
75 }
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +000076 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 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000091 case Mode::MODE_DUMP: {
Kean Mariotti639b54f2023-04-20 12:06:29 +000092 auto snapshot = mTakeLayersSnapshotProto(flags);
93 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
Kean Mariotti8c5abc82023-09-20 09:28:07 +000094 ALOGD("Started dump tracing (dumped single snapshot)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000095 break;
96 }
97 default: {
98 ALOGE("Started unknown tracing mode (0x%02x)", mode);
99 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700100 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700101}
102
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000103void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000104 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000105 // 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)");
Kean Mariotti639b54f2023-04-20 12:06:29 +0000115 return;
Vishnu Nair00b90132021-11-05 14:03:40 -0700116 }
Kean Mariotti639b54f2023-04-20 12:06:29 +0000117
118 if (!mTransactionTracing) {
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000119 ALOGD("Skipping layers trace generation (transactions tracing disabled)");
Kean Mariotti639b54f2023-04-20 12:06:29 +0000120 return;
Vishnu Naircb565332023-03-14 21:10:55 -0700121 }
Kean Mariotti639b54f2023-04-20 12:06:29 +0000122
123 auto transactionTrace = mTransactionTracing->writeToProto();
Kean Mariotti29aad4e2023-09-20 12:53:33 +0000124 LayerTraceGenerator{}.generate(transactionTrace, flags, *this);
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000125 ALOGD("Flushed generated tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700126}
127
Kean Mariotti639b54f2023-04-20 12:06:29 +0000128void LayerTracing::onStop(Mode mode) {
129 if (mode == Mode::MODE_ACTIVE) {
130 mIsActiveTracingStarted.store(false);
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000131 ALOGD("Stopped active tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700132 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700133}
134
Kean Mariotti639b54f2023-04-20 12:06:29 +0000135void 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 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700143}
144
Kean Mariotti639b54f2023-04-20 12:06:29 +0000145bool LayerTracing::isActiveTracingStarted() const {
146 return mIsActiveTracingStarted.load();
Vishnu Nair00b90132021-11-05 14:03:40 -0700147}
148
Kean Mariotti639b54f2023-04-20 12:06:29 +0000149uint32_t LayerTracing::getActiveTracingFlags() const {
150 return mActiveTracingFlags.load();
Vishnu Nair81750622023-03-08 15:02:06 -0800151}
Vishnu Nair00b90132021-11-05 14:03:40 -0700152
Kean Mariotti639b54f2023-04-20 12:06:29 +0000153bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
154 return (mActiveTracingFlags.load() & flag) != 0;
155}
156
157perfetto::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));
Kean Mariottic44fdaf2022-07-29 14:20:39 +0000165 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair00b90132021-11-05 14:03:40 -0700166 return fileProto;
167}
168
Kean Mariotti639b54f2023-04-20 12:06:29 +0000169void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
170 auto fileProto = createTraceFileProto();
171 *fileProto.add_entry() = std::move(snapshot);
172 mOutStream->get() << fileProto.SerializeAsString();
Vishnu Nair00b90132021-11-05 14:03:40 -0700173}
174
Kean Mariotti639b54f2023-04-20 12:06:29 +0000175void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000176 Mode srcMode) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000177 const auto snapshotBytes = snapshot.SerializeAsString();
178
179 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000180 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) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000189 return;
190 }
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000191
192 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000193 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
210bool 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.
Kean Mariotti8b5c6bd2023-09-20 06:50:41 +0000214 if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
Kean Mariotti639b54f2023-04-20 12:06:29 +0000215 return true;
Vishnu Nair00b90132021-11-05 14:03:40 -0700216 }
217
Kean Mariotti639b54f2023-04-20 12:06:29 +0000218 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
219 while (lastVsyncId < vsyncId) {
220 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
221 return true;
222 }
Vishnu Nairb64a3b42022-01-13 15:29:32 -0800223 }
224
Kean Mariotti639b54f2023-04-20 12:06:29 +0000225 return false;
Vishnu Nair00b90132021-11-05 14:03:40 -0700226}
227
228} // namespace android