blob: ddbf3e487366c56f65c50f80cf15ff04701728d0 [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 Mariotti8a5640a2023-04-19 13:41:55 +000026#include <optional>
Vishnu Nair7891e962021-11-11 12:07:21 -080027#include <thread>
28
Vishnu Nair81750622023-03-08 15:02:06 -080029#include "FrontEnd/DisplayInfo.h"
30#include "FrontEnd/LayerCreationArgs.h"
31#include "FrontEnd/Update.h"
Robert Carra63d52a2022-03-03 08:03:37 -080032#include "LocklessStack.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080033#include "TransactionProtoParser.h"
John Reck2a3d29d2023-08-17 17:45:01 -040034#include "TransactionRingBuffer.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080035
36using namespace android::surfaceflinger;
37
38namespace android {
39
Vishnu Nair7891e962021-11-11 12:07:21 -080040class SurfaceFlinger;
41class TransactionTracingTest;
Dominik Laskowski46471e62022-01-14 15:34:03 -080042
Vishnu Nair7891e962021-11-11 12:07:21 -080043/*
Kean Mariotti8a5640a2023-04-19 13:41:55 +000044 * Records all committed transactions into a ring buffer.
Vishnu Nair7891e962021-11-11 12:07:21 -080045 *
46 * Transactions come in via the binder thread. They are serialized to proto
47 * and stored in a map using the transaction id as key. Main thread will
48 * pass the list of transaction ids that are committed every vsync and notify
49 * the tracing thread. The tracing thread will then wake up and add the
50 * committed transactions to the ring buffer.
51 *
Kean Mariotti8a5640a2023-04-19 13:41:55 +000052 * The traced data can then be collected via:
53 * - Perfetto (preferred).
54 * - File system, after triggering the disk write through SF backdoor. This is legacy and is going
55 * to be phased out.
56 *
57 * The Perfetto custom data source TransactionDataSource is registered with perfetto and is used
58 * to listen to perfetto events (setup, start, stop, flush) and to write trace packets to perfetto.
59 *
60 * The user can configure/start/stop tracing via /system/bin/perfetto.
61 *
62 * Tracing can operate in the following modes.
63 *
64 * ACTIVE mode:
65 * The transactions ring buffer (starting state + following committed transactions) is written
66 * (only once) to perfetto when the 'start' event is received.
67 * Transactions are then written to perfetto each time they are committed.
68 * On the receiver side, the data source is to be configured to periodically
69 * flush data to disk providing virtually infinite storage.
70 *
71 * CONTINUOUS mode:
72 * Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
73 * When a 'flush' event is received, the ring buffer of transactions (starting state + following
74 * committed transactions) is written to perfetto. On the receiver side, the data source is to be
75 * configured with a dedicated buffer large enough to store all the flushed data.
76 *
77 *
78 * E.g. start active mode tracing:
79 *
80 adb shell perfetto \
81 -c - --txt \
82 -o /data/misc/perfetto-traces/trace \
83 <<EOF
84 unique_session_name: "surfaceflinger_transactions_active"
85 buffers: {
86 size_kb: 1024
87 fill_policy: RING_BUFFER
88 }
89 data_sources: {
90 config {
91 name: "android.surfaceflinger.transactions"
92 surfaceflinger_transactions_config: {
93 mode: MODE_ACTIVE
94 }
95 }
96 }
97 write_into_file: true
98 file_write_period_ms: 100
99 EOF
100 *
101 *
102 * E.g. start continuous mode tracing:
103 *
104 adb shell perfetto \
105 -c - --txt \
106 -o /data/misc/perfetto-traces/trace \
107 <<EOF
108 unique_session_name: "surfaceflinger_transactions_continuous"
109 buffers: {
110 size_kb: 1024
111 fill_policy: RING_BUFFER
112 }
113 data_sources: {
114 config {
115 name: "android.surfaceflinger.transactions"
116 surfaceflinger_transactions_config: {
117 mode: MODE_CONTINUOUS
118 }
119 }
120 }
121 EOF
Vishnu Nair7891e962021-11-11 12:07:21 -0800122 *
123 */
124class TransactionTracing {
125public:
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000126 using Mode = perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig::Mode;
127
Vishnu Nair7891e962021-11-11 12:07:21 -0800128 TransactionTracing();
129 ~TransactionTracing();
130
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000131 // Start event from perfetto data source
132 void onStart(Mode mode);
133 // Flush event from perfetto data source
134 void onFlush(Mode mode);
135
Vishnu Nair7891e962021-11-11 12:07:21 -0800136 void addQueuedTransaction(const TransactionState&);
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500137 void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update,
138 const frontend::DisplayInfos&, bool displayInfoChanged);
Vishnu Naird1f74982023-06-15 20:16:51 -0700139 status_t writeToFile(const std::string& filename = FILE_PATH);
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000140 // Return buffer contents as trace file proto
141 perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock);
Vishnu Nair7891e962021-11-11 12:07:21 -0800142 void setBufferSize(size_t bufferSizeInBytes);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800143 void onLayerRemoved(int layerId);
Vishnu Nair7891e962021-11-11 12:07:21 -0800144 void dump(std::string&) const;
Vishnu Naird1f74982023-06-15 20:16:51 -0700145 // Wait until all the committed transactions for the specified vsync id are added to the buffer.
146 void flush() EXCLUDES(mMainThreadLock);
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000147
Vishnu Nair7891e962021-11-11 12:07:21 -0800148 static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000149 static constexpr auto LEGACY_ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
Vishnu Nair81750622023-03-08 15:02:06 -0800150 // version 1 - switching to support new frontend
151 static constexpr auto TRACING_VERSION = 1;
Vishnu Nair7891e962021-11-11 12:07:21 -0800152
153private:
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700154 friend class TransactionTraceWriter;
Vishnu Nair7891e962021-11-11 12:07:21 -0800155 friend class TransactionTracingTest;
Vishnu Nair81750622023-03-08 15:02:06 -0800156 friend class SurfaceFlinger;
Vishnu Nair7891e962021-11-11 12:07:21 -0800157
Vishnu Naird1f74982023-06-15 20:16:51 -0700158 static constexpr auto DIR_NAME = "/data/misc/wmtrace/";
Vishnu Nair249fd7f2023-06-22 19:30:24 -0700159 static constexpr auto FILE_NAME = "transactions_trace.winscope";
Vishnu Naird1f74982023-06-15 20:16:51 -0700160 static constexpr auto FILE_PATH = "/data/misc/wmtrace/transactions_trace.winscope";
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700161 static std::string getFilePath(const std::string& prefix) {
162 return DIR_NAME + prefix + FILE_NAME;
163 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800164
165 mutable std::mutex mTraceLock;
Kean Mariottibec51fd2023-04-19 13:31:02 +0000166 TransactionRingBuffer<perfetto::protos::TransactionTraceFile,
167 perfetto::protos::TransactionTraceEntry>
168 mBuffer GUARDED_BY(mTraceLock);
Kean Mariottibec51fd2023-04-19 13:31:02 +0000169 std::unordered_map<uint64_t, perfetto::protos::TransactionState> mQueuedTransactions
Vishnu Nair7891e962021-11-11 12:07:21 -0800170 GUARDED_BY(mTraceLock);
Kean Mariottibec51fd2023-04-19 13:31:02 +0000171 LocklessStack<perfetto::protos::TransactionState> mTransactionQueue;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800172 nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
Kean Mariottibec51fd2023-04-19 13:31:02 +0000173 std::unordered_map<int, perfetto::protos::LayerCreationArgs> mCreatedLayers
174 GUARDED_BY(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -0800175 std::map<uint32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500176 frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -0800177
178 std::set<uint32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock);
179 TransactionProtoParser mProtoParser;
Vishnu Nair7891e962021-11-11 12:07:21 -0800180
181 // We do not want main thread to block so main thread will try to acquire mMainThreadLock,
182 // otherwise will push data to temporary container.
183 std::mutex mMainThreadLock;
184 std::thread mThread GUARDED_BY(mMainThreadLock);
185 bool mDone GUARDED_BY(mMainThreadLock) = false;
186 std::condition_variable mTransactionsAvailableCv;
187 std::condition_variable mTransactionsAddedToBufferCv;
Vishnu Nair81750622023-03-08 15:02:06 -0800188 struct CommittedUpdates {
Vishnu Nair7891e962021-11-11 12:07:21 -0800189 std::vector<uint64_t> transactionIds;
Vishnu Nair81750622023-03-08 15:02:06 -0800190 std::vector<LayerCreationArgs> createdLayers;
191 std::vector<uint32_t> destroyedLayerHandles;
192 bool displayInfoChanged;
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500193 frontend::DisplayInfos displayInfos;
Vishnu Nair7891e962021-11-11 12:07:21 -0800194 int64_t vsyncId;
195 int64_t timestamp;
196 };
Vishnu Nair81750622023-03-08 15:02:06 -0800197 std::vector<CommittedUpdates> mUpdates GUARDED_BY(mMainThreadLock);
198 std::vector<CommittedUpdates> mPendingUpdates; // only accessed by main thread
Vishnu Nair7891e962021-11-11 12:07:21 -0800199
Vishnu Nair81750622023-03-08 15:02:06 -0800200 std::vector<uint32_t /* layerId */> mDestroyedLayers GUARDED_BY(mMainThreadLock);
201 std::vector<uint32_t /* layerId */> mPendingDestroyedLayers; // only accessed by main thread
Vishnu Naird1f74982023-06-15 20:16:51 -0700202 int64_t mLastUpdatedVsyncId = -1;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800203
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000204 void writeRingBufferToPerfetto(TransactionTracing::Mode mode);
Kean Mariottibec51fd2023-04-19 13:31:02 +0000205 perfetto::protos::TransactionTraceFile createTraceFileProto() const;
Vishnu Nair7891e962021-11-11 12:07:21 -0800206 void loop();
Vishnu Nair81750622023-03-08 15:02:06 -0800207 void addEntry(const std::vector<CommittedUpdates>& committedTransactions,
208 const std::vector<uint32_t>& removedLayers) EXCLUDES(mTraceLock);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800209 int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock);
210 void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
Kean Mariotti8a5640a2023-04-19 13:41:55 +0000211 std::optional<perfetto::protos::TransactionTraceEntry> createStartingStateProtoLocked()
Kean Mariottibec51fd2023-04-19 13:31:02 +0000212 REQUIRES(mTraceLock);
213 void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry)
214 REQUIRES(mTraceLock);
Vishnu Nair7891e962021-11-11 12:07:21 -0800215};
216
Vishnu Naird1f74982023-06-15 20:16:51 -0700217class TransactionTraceWriter : public Singleton<TransactionTraceWriter> {
218 friend class Singleton<TransactionTracing>;
219 std::function<void(const std::string& prefix, bool overwrite)> mWriterFunction =
220 [](const std::string&, bool) {};
221
222public:
223 void setWriterFunction(
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700224 std::function<void(const std::string& filename, bool overwrite)> function) {
Vishnu Naird1f74982023-06-15 20:16:51 -0700225 mWriterFunction = std::move(function);
226 }
Vishnu Nair8c5b7002023-08-17 21:03:57 -0700227 void invoke(const std::string& prefix, bool overwrite) {
228 mWriterFunction(TransactionTracing::getFilePath(prefix), overwrite);
229 }
230 /* pass in a complete file path for testing */
231 void invokeForTest(const std::string& filename, bool overwrite) {
232 mWriterFunction(filename, overwrite);
233 }
Vishnu Naird1f74982023-06-15 20:16:51 -0700234};
235
Vishnu Nair7891e962021-11-11 12:07:21 -0800236} // namespace android