blob: cb96e056800a313f8ab50d5b92a4275048d14e59 [file] [log] [blame]
Vishnu Nair7891e962021-11-11 12:07:21 -08001/*
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#pragma once
18
19#include <android-base/thread_annotations.h>
20#include <layerproto/TransactionProto.h>
21#include <utils/Errors.h>
Vishnu Naird1f74982023-06-15 20:16:51 -070022#include <utils/Singleton.h>
Vishnu Nair7891e962021-11-11 12:07:21 -080023#include <utils/Timers.h>
24
Vishnu Nair7891e962021-11-11 12:07:21 -080025#include <mutex>
Kean Mariotti3e68a202023-04-19 13:41:55 +000026#include <optional>
Krzysztof KosiƄskiea98b272024-03-15 23:22:06 +000027#include <set>
Vishnu Nair7891e962021-11-11 12:07:21 -080028#include <thread>
29
Vishnu Nair81750622023-03-08 15:02:06 -080030#include "FrontEnd/DisplayInfo.h"
31#include "FrontEnd/LayerCreationArgs.h"
32#include "FrontEnd/Update.h"
Robert Carra63d52a2022-03-03 08:03:37 -080033#include "LocklessStack.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080034#include "TransactionProtoParser.h"
John Reck2a3d29d2023-08-17 17:45:01 -040035#include "TransactionRingBuffer.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080036
37using namespace android::surfaceflinger;
38
39namespace android {
40
Vishnu Nair7891e962021-11-11 12:07:21 -080041class SurfaceFlinger;
42class TransactionTracingTest;
Dominik Laskowski46471e62022-01-14 15:34:03 -080043
Vishnu Nair7891e962021-11-11 12:07:21 -080044/*
Kean Mariotti3e68a202023-04-19 13:41:55 +000045 * Records all committed transactions into a ring buffer.
Vishnu Nair7891e962021-11-11 12:07:21 -080046 *
47 * Transactions come in via the binder thread. They are serialized to proto
48 * and stored in a map using the transaction id as key. Main thread will
49 * pass the list of transaction ids that are committed every vsync and notify
50 * the tracing thread. The tracing thread will then wake up and add the
51 * committed transactions to the ring buffer.
52 *
Kean Mariotti3e68a202023-04-19 13:41:55 +000053 * The traced data can then be collected via:
54 * - Perfetto (preferred).
55 * - File system, after triggering the disk write through SF backdoor. This is legacy and is going
56 * to be phased out.
57 *
58 * The Perfetto custom data source TransactionDataSource is registered with perfetto and is used
59 * to listen to perfetto events (setup, start, stop, flush) and to write trace packets to perfetto.
60 *
61 * The user can configure/start/stop tracing via /system/bin/perfetto.
62 *
63 * Tracing can operate in the following modes.
64 *
65 * ACTIVE mode:
66 * The transactions ring buffer (starting state + following committed transactions) is written
67 * (only once) to perfetto when the 'start' event is received.
68 * Transactions are then written to perfetto each time they are committed.
69 * On the receiver side, the data source is to be configured to periodically
70 * flush data to disk providing virtually infinite storage.
71 *
72 * CONTINUOUS mode:
73 * Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
74 * When a 'flush' event is received, the ring buffer of transactions (starting state + following
75 * committed transactions) is written to perfetto. On the receiver side, the data source is to be
76 * configured with a dedicated buffer large enough to store all the flushed data.
77 *
78 *
79 * E.g. start active mode tracing:
80 *
81 adb shell perfetto \
82 -c - --txt \
83 -o /data/misc/perfetto-traces/trace \
84 <<EOF
85 unique_session_name: "surfaceflinger_transactions_active"
86 buffers: {
87 size_kb: 1024
88 fill_policy: RING_BUFFER
89 }
90 data_sources: {
91 config {
92 name: "android.surfaceflinger.transactions"
93 surfaceflinger_transactions_config: {
94 mode: MODE_ACTIVE
95 }
96 }
97 }
98 write_into_file: true
99 file_write_period_ms: 100
100 EOF
101 *
102 *
103 * E.g. start continuous mode tracing:
104 *
105 adb shell perfetto \
106 -c - --txt \
107 -o /data/misc/perfetto-traces/trace \
108 <<EOF
109 unique_session_name: "surfaceflinger_transactions_continuous"
110 buffers: {
111 size_kb: 1024
112 fill_policy: RING_BUFFER
113 }
114 data_sources: {
115 config {
116 name: "android.surfaceflinger.transactions"
117 surfaceflinger_transactions_config: {
118 mode: MODE_CONTINUOUS
119 }
120 }
121 }
122 EOF
Vishnu Nair7891e962021-11-11 12:07:21 -0800123 *
124 */
125class TransactionTracing {
126public:
Kean Mariotti3e68a202023-04-19 13:41:55 +0000127 using Mode = perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig::Mode;
128
Vishnu Nair7891e962021-11-11 12:07:21 -0800129 TransactionTracing();
130 ~TransactionTracing();
131
Kean Mariotti3e68a202023-04-19 13:41:55 +0000132 // Start event from perfetto data source
133 void onStart(Mode mode);
134 // Flush event from perfetto data source
135 void onFlush(Mode mode);
136
Vishnu Nair7891e962021-11-11 12:07:21 -0800137 void addQueuedTransaction(const TransactionState&);
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500138 void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update,
139 const frontend::DisplayInfos&, bool displayInfoChanged);
Vishnu Naird1f74982023-06-15 20:16:51 -0700140 status_t writeToFile(const std::string& filename = FILE_PATH);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000141 // Return buffer contents as trace file proto
142 perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock);
Vishnu Nair7891e962021-11-11 12:07:21 -0800143 void setBufferSize(size_t bufferSizeInBytes);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800144 void onLayerRemoved(int layerId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800145 void dump(std::string&) const;
Vishnu Naird1f74982023-06-15 20:16:51 -0700146 // Wait until all the committed transactions for the specified vsync id are added to the buffer.
147 void flush() EXCLUDES(mMainThreadLock);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000148
Vishnu Nair7891e962021-11-11 12:07:21 -0800149 static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
Kean Mariotti3e68a202023-04-19 13:41:55 +0000150 static constexpr auto LEGACY_ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
Vishnu Nair81750622023-03-08 15:02:06 -0800151 // version 1 - switching to support new frontend
152 static constexpr auto TRACING_VERSION = 1;
Vishnu Nair7891e962021-11-11 12:07:21 -0800153
154private:
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700155 friend class TransactionTraceWriter;
Vishnu Nair7891e962021-11-11 12:07:21 -0800156 friend class TransactionTracingTest;
Vishnu Nair81750622023-03-08 15:02:06 -0800157 friend class SurfaceFlinger;
Vishnu Nair7891e962021-11-11 12:07:21 -0800158
Vishnu Naird1f74982023-06-15 20:16:51 -0700159 static constexpr auto DIR_NAME = "/data/misc/wmtrace/";
Vishnu Nair249fd7f2023-06-22 19:30:24 -0700160 static constexpr auto FILE_NAME = "transactions_trace.winscope";
Vishnu Naird1f74982023-06-15 20:16:51 -0700161 static constexpr auto FILE_PATH = "/data/misc/wmtrace/transactions_trace.winscope";
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700162 static std::string getFilePath(const std::string& prefix) {
163 return DIR_NAME + prefix + FILE_NAME;
164 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800165
166 mutable std::mutex mTraceLock;
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000167 TransactionRingBuffer<perfetto::protos::TransactionTraceFile,
168 perfetto::protos::TransactionTraceEntry>
169 mBuffer GUARDED_BY(mTraceLock);
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000170 std::unordered_map<uint64_t, perfetto::protos::TransactionState> mQueuedTransactions
Vishnu Nair7891e962021-11-11 12:07:21 -0800171 GUARDED_BY(mTraceLock);
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000172 LocklessStack<perfetto::protos::TransactionState> mTransactionQueue;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800173 nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000174 std::unordered_map<int, perfetto::protos::LayerCreationArgs> mCreatedLayers
175 GUARDED_BY(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -0800176 std::map<uint32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500177 frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -0800178
179 std::set<uint32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock);
180 TransactionProtoParser mProtoParser;
Vishnu Nair7891e962021-11-11 12:07:21 -0800181
182 // We do not want main thread to block so main thread will try to acquire mMainThreadLock,
183 // otherwise will push data to temporary container.
184 std::mutex mMainThreadLock;
185 std::thread mThread GUARDED_BY(mMainThreadLock);
186 bool mDone GUARDED_BY(mMainThreadLock) = false;
187 std::condition_variable mTransactionsAvailableCv;
188 std::condition_variable mTransactionsAddedToBufferCv;
Vishnu Nair81750622023-03-08 15:02:06 -0800189 struct CommittedUpdates {
Vishnu Nair7891e962021-11-11 12:07:21 -0800190 std::vector<uint64_t> transactionIds;
Vishnu Nair81750622023-03-08 15:02:06 -0800191 std::vector<LayerCreationArgs> createdLayers;
192 std::vector<uint32_t> destroyedLayerHandles;
193 bool displayInfoChanged;
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500194 frontend::DisplayInfos displayInfos;
Vishnu Nair7891e962021-11-11 12:07:21 -0800195 int64_t vsyncId;
196 int64_t timestamp;
197 };
Vishnu Nair81750622023-03-08 15:02:06 -0800198 std::vector<CommittedUpdates> mUpdates GUARDED_BY(mMainThreadLock);
199 std::vector<CommittedUpdates> mPendingUpdates; // only accessed by main thread
Vishnu Nair7891e962021-11-11 12:07:21 -0800200
Vishnu Nair81750622023-03-08 15:02:06 -0800201 std::vector<uint32_t /* layerId */> mDestroyedLayers GUARDED_BY(mMainThreadLock);
202 std::vector<uint32_t /* layerId */> mPendingDestroyedLayers; // only accessed by main thread
Vishnu Naird1f74982023-06-15 20:16:51 -0700203 int64_t mLastUpdatedVsyncId = -1;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800204
Kean Mariotti3e68a202023-04-19 13:41:55 +0000205 void writeRingBufferToPerfetto(TransactionTracing::Mode mode);
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000206 perfetto::protos::TransactionTraceFile createTraceFileProto() const;
Vishnu Nair7891e962021-11-11 12:07:21 -0800207 void loop();
Vishnu Nair81750622023-03-08 15:02:06 -0800208 void addEntry(const std::vector<CommittedUpdates>& committedTransactions,
209 const std::vector<uint32_t>& removedLayers) EXCLUDES(mTraceLock);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800210 int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock);
211 void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
Kean Mariotti3e68a202023-04-19 13:41:55 +0000212 std::optional<perfetto::protos::TransactionTraceEntry> createStartingStateProtoLocked()
Kean Mariotti4ba343c2023-04-19 13:31:02 +0000213 REQUIRES(mTraceLock);
214 void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry)
215 REQUIRES(mTraceLock);
Vishnu Nair7891e962021-11-11 12:07:21 -0800216};
217
Vishnu Naird1f74982023-06-15 20:16:51 -0700218class TransactionTraceWriter : public Singleton<TransactionTraceWriter> {
219 friend class Singleton<TransactionTracing>;
220 std::function<void(const std::string& prefix, bool overwrite)> mWriterFunction =
221 [](const std::string&, bool) {};
222
223public:
224 void setWriterFunction(
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700225 std::function<void(const std::string& filename, bool overwrite)> function) {
Vishnu Naird1f74982023-06-15 20:16:51 -0700226 mWriterFunction = std::move(function);
227 }
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700228 void invoke(const std::string& prefix, bool overwrite) {
229 mWriterFunction(TransactionTracing::getFilePath(prefix), overwrite);
230 }
231 /* pass in a complete file path for testing */
232 void invokeForTest(const std::string& filename, bool overwrite) {
233 mWriterFunction(filename, overwrite);
234 }
Vishnu Naird1f74982023-06-15 20:16:51 -0700235};
236
Vishnu Nair7891e962021-11-11 12:07:21 -0800237} // namespace android