blob: 657df16f048f6f1cb7f30a49f17d73bdbf29a065 [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);
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 Mariotti8c5abc82023-09-20 09:28:07 +000070 ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000071 break;
72 }
73 case Mode::MODE_DUMP: {
Kean Mariotti639b54f2023-04-20 12:06:29 +000074 auto snapshot = mTakeLayersSnapshotProto(flags);
75 addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
Kean Mariotti8c5abc82023-09-20 09:28:07 +000076 ALOGD("Started dump tracing (dumped single snapshot)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000077 break;
78 }
79 default: {
80 ALOGE("Started unknown tracing mode (0x%02x)", mode);
81 }
Vishnu Nair00b90132021-11-05 14:03:40 -070082 }
Vishnu Nair00b90132021-11-05 14:03:40 -070083}
84
Kean Mariotti639b54f2023-04-20 12:06:29 +000085void LayerTracing::onFlush(Mode mode, uint32_t flags) {
86 // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
87 // generate a sequence of layers snapshots and write them to perfetto.
88 if (mode != Mode::MODE_GENERATED) {
89 return;
Vishnu Nair00b90132021-11-05 14:03:40 -070090 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000091
92 if (!mTransactionTracing) {
Kean Mariotti8c5abc82023-09-20 09:28:07 +000093 ALOGD("Skipping layers trace generation (transactions tracing disabled)");
Kean Mariotti639b54f2023-04-20 12:06:29 +000094 return;
Vishnu Naircb565332023-03-14 21:10:55 -070095 }
Kean Mariotti639b54f2023-04-20 12:06:29 +000096
97 auto transactionTrace = mTransactionTracing->writeToProto();
98 LayerTraceGenerator{}.generate(transactionTrace, flags);
Kean Mariotti8c5abc82023-09-20 09:28:07 +000099 ALOGD("Flushed generated tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700100}
101
Kean Mariotti639b54f2023-04-20 12:06:29 +0000102void LayerTracing::onStop(Mode mode) {
103 if (mode == Mode::MODE_ACTIVE) {
104 mIsActiveTracingStarted.store(false);
Kean Mariotti8c5abc82023-09-20 09:28:07 +0000105 ALOGD("Stopped active tracing");
Vishnu Nair00b90132021-11-05 14:03:40 -0700106 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700107}
108
Kean Mariotti639b54f2023-04-20 12:06:29 +0000109void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
110 Mode mode) {
111 ATRACE_CALL();
112 if (mOutStream) {
113 writeSnapshotToStream(std::move(snapshot));
114 } else {
115 writeSnapshotToPerfetto(snapshot, mode);
116 }
Vishnu Nair00b90132021-11-05 14:03:40 -0700117}
118
Kean Mariotti639b54f2023-04-20 12:06:29 +0000119bool LayerTracing::isActiveTracingStarted() const {
120 return mIsActiveTracingStarted.load();
Vishnu Nair00b90132021-11-05 14:03:40 -0700121}
122
Kean Mariotti639b54f2023-04-20 12:06:29 +0000123uint32_t LayerTracing::getActiveTracingFlags() const {
124 return mActiveTracingFlags.load();
Vishnu Nair81750622023-03-08 15:02:06 -0800125}
Vishnu Nair00b90132021-11-05 14:03:40 -0700126
Kean Mariotti639b54f2023-04-20 12:06:29 +0000127bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
128 return (mActiveTracingFlags.load() & flag) != 0;
129}
130
131perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
132 perfetto::protos::LayersTraceFileProto fileProto;
133 fileProto.set_magic_number(
134 static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
135 << 32 |
136 perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
137 auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
138 systemTime(SYSTEM_TIME_MONOTONIC));
Kean Mariottic44fdaf2022-07-29 14:20:39 +0000139 fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair00b90132021-11-05 14:03:40 -0700140 return fileProto;
141}
142
Kean Mariotti639b54f2023-04-20 12:06:29 +0000143void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
144 auto fileProto = createTraceFileProto();
145 *fileProto.add_entry() = std::move(snapshot);
146 mOutStream->get() << fileProto.SerializeAsString();
Vishnu Nair00b90132021-11-05 14:03:40 -0700147}
148
Kean Mariotti639b54f2023-04-20 12:06:29 +0000149void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
150 Mode mode) {
151 const auto snapshotBytes = snapshot.SerializeAsString();
152
153 LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
154 if (mode != context.GetCustomTlsState()->mMode) {
155 return;
156 }
157 if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(mode, snapshot.vsync_id())) {
158 return;
159 }
160 {
161 auto packet = context.NewTracePacket();
162 packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
163 packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
164 auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
165 snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
166 }
167 {
168 // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
169 // It is currently needed in order not to lose the last trace entry.
170 context.NewTracePacket();
171 }
172 });
173}
174
175bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
176 // In some situations (e.g. two bugreports taken shortly one after the other) the generated
177 // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
178 // sure that in generated tracing mode a given snapshot is written only once to perfetto.
179 if (mode != Mode::MODE_GENERATED) {
180 return true;
Vishnu Nair00b90132021-11-05 14:03:40 -0700181 }
182
Kean Mariotti639b54f2023-04-20 12:06:29 +0000183 auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
184 while (lastVsyncId < vsyncId) {
185 if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
186 return true;
187 }
Vishnu Nairb64a3b42022-01-13 15:29:32 -0800188 }
189
Kean Mariotti639b54f2023-04-20 12:06:29 +0000190 return false;
Vishnu Nair00b90132021-11-05 14:03:40 -0700191}
192
193} // namespace android