blob: e55b4c2ce8c1ec4ce37b9f5c178f9f8b67b35329 [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 Mariotti639b54f2023-04-20 12:06:29 +000039LayerTracing::~LayerTracing() {
40 LayerDataSource::UnregisterLayerTracing();
41}
Vishnu Nair00b90132021-11-05 14:03:40 -070042
Kean Mariotti639b54f2023-04-20 12:06:29 +000043void LayerTracing::setTakeLayersSnapshotProtoFunction(
44 const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& callback) {
45 mTakeLayersSnapshotProto = callback;
46}
47
48void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
49 mTransactionTracing = &transactionTracing;
50}
51
52void LayerTracing::setOutputStream(std::ostream& outStream) {
53 mOutStream = std::ref(outStream);
54}
55
56void 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 ALOGV("Started active tracing (traced initial snapshot)");
67 break;
68 }
69 case Mode::MODE_GENERATED: {
70 ALOGV("Started generated tracing (waiting for OnFlush event to generated layers)");
71 break;
72 }
73 case Mode::MODE_DUMP: {
74 ALOGV("Starting dump tracing (dumping single snapshot)");
75 auto snapshot = mTakeLayersSnapshotProto(flags);
76 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
77 ALOGV("Started dump tracing (dumped single snapshot)");
78 break;
79 }
80 default: {
81 ALOGE("Started unknown tracing mode (0x%02x)", mode);
82 }
Vishnu Nair00b90132021-11-05 14:03:40 -070083 }
Vishnu Nair00b90132021-11-05 14:03:40 -070084}
85
Kean Mariotti639b54f2023-04-20 12:06:29 +000086void LayerTracing::onFlush(Mode mode, uint32_t flags) {
87 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
88 // generate a sequence of layers snapshots and write them to perfetto.
89 if (mode != Mode::MODE_GENERATED) {
90 return;
Vishnu Nair00b90132021-11-05 14:03:40 -070091 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000092
93 if (!mTransactionTracing) {
94 ALOGV("Skipping layers trace generation (transactions tracing disabled)");
95 return;
Vishnu Naircb565332023-03-14 21:10:55 -070096 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000097
98 auto transactionTrace = mTransactionTracing->writeToProto();
99 LayerTraceGenerator{}.generate(transactionTrace, flags);
100 ALOGV("Flushed generated tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700101}
102
Kean Mariotti639b54f2023-04-20 12:06:29 +0000103void LayerTracing::onStop(Mode mode) {
104 if (mode == Mode::MODE_ACTIVE) {
105 mIsActiveTracingStarted.store(false);
106 ALOGV("Stopped active tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700107 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700108}
109
Kean Mariotti639b54f2023-04-20 12:06:29 +0000110void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
111 Mode mode) {
112 ATRACE_CALL();
113 if (mOutStream) {
114 writeSnapshotToStream(std::move(snapshot));
115 } else {
116 writeSnapshotToPerfetto(snapshot, mode);
117 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700118}
119
Kean Mariotti639b54f2023-04-20 12:06:29 +0000120bool LayerTracing::isActiveTracingStarted() const {
121 return mIsActiveTracingStarted.load();
Vishnu Nair00b90132021-11-05 14:03:40 -0700122}
123
Kean Mariotti639b54f2023-04-20 12:06:29 +0000124uint32_t LayerTracing::getActiveTracingFlags() const {
125 return mActiveTracingFlags.load();
Vishnu Nair81750622023-03-08 15:02:06 -0800126}
Vishnu Nair00b90132021-11-05 14:03:40 -0700127
Kean Mariotti639b54f2023-04-20 12:06:29 +0000128bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
129 return (mActiveTracingFlags.load() & flag) != 0;
130}
131
132perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
133 perfetto::protos::LayersTraceFileProto fileProto;
134 fileProto.set_magic_number(
135 static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
136 << 32 |
137 perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
138 auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
139 systemTime(SYSTEM_TIME_MONOTONIC));
Kean Mariottic44fdaf2022-07-29 14:20:39 +0000140 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair00b90132021-11-05 14:03:40 -0700141 return fileProto;
142}
143
Kean Mariotti639b54f2023-04-20 12:06:29 +0000144void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
145 auto fileProto = createTraceFileProto();
146 *fileProto.add_entry() = std::move(snapshot);
147 mOutStream->get() << fileProto.SerializeAsString();
Vishnu Nair00b90132021-11-05 14:03:40 -0700148}
149
Kean Mariotti639b54f2023-04-20 12:06:29 +0000150void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
151 Mode mode) {
152 const auto snapshotBytes = snapshot.SerializeAsString();
153
154 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
155 if (mode != context.GetCustomTlsState()->mMode) {
156 return;
157 }
158 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(mode, snapshot.vsync_id())) {
159 return;
160 }
161 {
162 auto packet = context.NewTracePacket();
163 packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
164 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
165 auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
166 snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
167 }
168 {
169 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
170 // It is currently needed in order not to lose the last trace entry.
171 context.NewTracePacket();
172 }
173 });
174}
175
176bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
177 // In some situations (e.g. two bugreports taken shortly one after the other) the generated
178 // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
179 // sure that in generated tracing mode a given snapshot is written only once to perfetto.
180 if (mode != Mode::MODE_GENERATED) {
181 return true;
Vishnu Nair00b90132021-11-05 14:03:40 -0700182 }
183
Kean Mariotti639b54f2023-04-20 12:06:29 +0000184 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
185 while (lastVsyncId < vsyncId) {
186 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
187 return true;
188 }
Vishnu Nairb64a3b42022-01-13 15:29:32 -0800189 }
190
Kean Mariotti639b54f2023-04-20 12:06:29 +0000191 return false;
Vishnu Nair00b90132021-11-05 14:03:40 -0700192}
193
194} // namespace android