blob: 632de01bfafda426ccb2d095d7d71b47342cbb09 [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#undef LOG_TAG
18#define LOG_TAG "TransactionTracing"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20
21#include <android-base/stringprintf.h>
22#include <log/log.h>
23#include <utils/SystemClock.h>
24#include <utils/Trace.h>
25
Vishnu Nair81750622023-03-08 15:02:06 -080026#include "Client.h"
27#include "FrontEnd/LayerCreationArgs.h"
Vishnu Nair7891e962021-11-11 12:07:21 -080028#include "TransactionTracing.h"
29
30namespace android {
31
Vishnu Nair685cfef2022-02-02 10:01:25 -080032TransactionTracing::TransactionTracing()
Vishnu Nair81750622023-03-08 15:02:06 -080033 : mProtoParser(std::make_unique<TransactionProtoParser::FlingerDataMapper>()) {
Vishnu Nair7891e962021-11-11 12:07:21 -080034 std::scoped_lock lock(mTraceLock);
Dominik Laskowski46471e62022-01-14 15:34:03 -080035
36 mBuffer.setSize(mBufferSizeInBytes);
Vishnu Nair0cc69e12021-11-18 09:05:49 -080037 mStartingTimestamp = systemTime();
Vishnu Nair7891e962021-11-11 12:07:21 -080038 {
39 std::scoped_lock lock(mMainThreadLock);
Vishnu Nair7891e962021-11-11 12:07:21 -080040 mThread = std::thread(&TransactionTracing::loop, this);
41 }
Vishnu Nair7891e962021-11-11 12:07:21 -080042}
43
Dominik Laskowski46471e62022-01-14 15:34:03 -080044TransactionTracing::~TransactionTracing() {
Vishnu Nair7891e962021-11-11 12:07:21 -080045 std::thread thread;
46 {
47 std::scoped_lock lock(mMainThreadLock);
48 mDone = true;
49 mTransactionsAvailableCv.notify_all();
50 thread = std::move(mThread);
51 }
52 if (thread.joinable()) {
53 thread.join();
54 }
55
Dominik Laskowski46471e62022-01-14 15:34:03 -080056 writeToFile();
Vishnu Nair7891e962021-11-11 12:07:21 -080057}
58
Vishnu Naird8f5e9f2022-02-03 10:23:28 -080059status_t TransactionTracing::writeToFile(std::string filename) {
Vishnu Nair7891e962021-11-11 12:07:21 -080060 std::scoped_lock lock(mTraceLock);
Vishnu Nair7891e962021-11-11 12:07:21 -080061 proto::TransactionTraceFile fileProto = createTraceFileProto();
Vishnu Nair0cc69e12021-11-18 09:05:49 -080062 addStartingStateToProtoLocked(fileProto);
Vishnu Naird8f5e9f2022-02-03 10:23:28 -080063 return mBuffer.writeToFile(fileProto, filename);
Vishnu Nair7891e962021-11-11 12:07:21 -080064}
65
66void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) {
67 std::scoped_lock lock(mTraceLock);
68 mBufferSizeInBytes = bufferSizeInBytes;
Dominik Laskowski46471e62022-01-14 15:34:03 -080069 mBuffer.setSize(mBufferSizeInBytes);
Vishnu Nair7891e962021-11-11 12:07:21 -080070}
71
72proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const {
73 proto::TransactionTraceFile proto;
74 proto.set_magic_number(uint64_t(proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 |
75 proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L);
Kean Mariottic44fdaf2022-07-29 14:20:39 +000076 auto timeOffsetNs = static_cast<std::uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
77 systemTime(SYSTEM_TIME_MONOTONIC));
78 proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
Vishnu Nair81750622023-03-08 15:02:06 -080079 proto.set_version(TRACING_VERSION);
Vishnu Nair7891e962021-11-11 12:07:21 -080080 return proto;
81}
82
83void TransactionTracing::dump(std::string& result) const {
84 std::scoped_lock lock(mTraceLock);
Vishnu Nair81750622023-03-08 15:02:06 -080085 base::StringAppendF(&result, " queued transactions=%zu created layers=%zu states=%zu\n",
86 mQueuedTransactions.size(), mCreatedLayers.size(), mStartingStates.size());
Dominik Laskowski46471e62022-01-14 15:34:03 -080087 mBuffer.dump(result);
Vishnu Nair7891e962021-11-11 12:07:21 -080088}
89
90void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) {
Vishnu Nair81750622023-03-08 15:02:06 -080091 proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction));
Robert Carra63d52a2022-03-03 08:03:37 -080092 mTransactionQueue.push(state);
Vishnu Nair7891e962021-11-11 12:07:21 -080093}
94
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050095void TransactionTracing::addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime,
96 frontend::Update& newUpdate,
97 const frontend::DisplayInfos& displayInfos,
98 bool displayInfoChanged) {
Vishnu Nair81750622023-03-08 15:02:06 -080099 CommittedUpdates update;
100 update.vsyncId = vsyncId;
101 update.timestamp = commitTime;
102 update.transactionIds.reserve(newUpdate.transactions.size());
103 for (const auto& transaction : newUpdate.transactions) {
104 update.transactionIds.emplace_back(transaction.id);
Vishnu Nair286f4f92022-06-08 16:37:39 -0700105 }
Vishnu Nair81750622023-03-08 15:02:06 -0800106 update.displayInfoChanged = displayInfoChanged;
107 if (displayInfoChanged) {
108 update.displayInfos = displayInfos;
Vishnu Nair7891e962021-11-11 12:07:21 -0800109 }
Vishnu Nair81750622023-03-08 15:02:06 -0800110 update.createdLayers = std::move(newUpdate.layerCreationArgs);
111 newUpdate.layerCreationArgs.clear();
112 update.destroyedLayerHandles.reserve(newUpdate.destroyedHandles.size());
113 for (uint32_t handle : newUpdate.destroyedHandles) {
114 update.destroyedLayerHandles.push_back(handle);
115 }
116 mPendingUpdates.emplace_back(update);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800117 tryPushToTracingThread();
Vishnu Nair7891e962021-11-11 12:07:21 -0800118}
119
120void TransactionTracing::loop() {
121 while (true) {
Vishnu Nair81750622023-03-08 15:02:06 -0800122 std::vector<CommittedUpdates> committedUpdates;
123 std::vector<uint32_t> destroyedLayers;
Vishnu Nair7891e962021-11-11 12:07:21 -0800124 {
125 std::unique_lock<std::mutex> lock(mMainThreadLock);
126 base::ScopedLockAssertion assumeLocked(mMainThreadLock);
127 mTransactionsAvailableCv.wait(lock, [&]() REQUIRES(mMainThreadLock) {
Vishnu Nair81750622023-03-08 15:02:06 -0800128 return mDone || !mUpdates.empty();
Vishnu Nair7891e962021-11-11 12:07:21 -0800129 });
130 if (mDone) {
Vishnu Nair81750622023-03-08 15:02:06 -0800131 mUpdates.clear();
132 mDestroyedLayers.clear();
Vishnu Nair7891e962021-11-11 12:07:21 -0800133 break;
134 }
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800135
Vishnu Nair81750622023-03-08 15:02:06 -0800136 destroyedLayers = std::move(mDestroyedLayers);
137 mDestroyedLayers.clear();
138 committedUpdates = std::move(mUpdates);
139 mUpdates.clear();
Vishnu Nair7891e962021-11-11 12:07:21 -0800140 } // unlock mMainThreadLock
141
Vishnu Nair81750622023-03-08 15:02:06 -0800142 if (!committedUpdates.empty() || !destroyedLayers.empty()) {
143 addEntry(committedUpdates, destroyedLayers);
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800144 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800145 }
146}
147
Vishnu Nair81750622023-03-08 15:02:06 -0800148void TransactionTracing::addEntry(const std::vector<CommittedUpdates>& committedUpdates,
149 const std::vector<uint32_t>& destroyedLayers) {
Vishnu Nair7891e962021-11-11 12:07:21 -0800150 ATRACE_CALL();
151 std::scoped_lock lock(mTraceLock);
Vishnu Nair62863552021-12-10 13:34:48 -0800152 std::vector<std::string> removedEntries;
153 proto::TransactionTraceEntry entryProto;
Robert Carra63d52a2022-03-03 08:03:37 -0800154
155 while (auto incomingTransaction = mTransactionQueue.pop()) {
156 auto transaction = *incomingTransaction;
Robert Carra63d52a2022-03-03 08:03:37 -0800157 mQueuedTransactions[incomingTransaction->transaction_id()] = transaction;
158 delete incomingTransaction;
159 }
Vishnu Nair81750622023-03-08 15:02:06 -0800160 for (const CommittedUpdates& update : committedUpdates) {
161 entryProto.set_elapsed_realtime_nanos(update.timestamp);
162 entryProto.set_vsync_id(update.vsyncId);
Vishnu Nair286f4f92022-06-08 16:37:39 -0700163 entryProto.mutable_added_layers()->Reserve(
Vishnu Nair81750622023-03-08 15:02:06 -0800164 static_cast<int32_t>(update.createdLayers.size()));
Vishnu Nair286f4f92022-06-08 16:37:39 -0700165
Vishnu Nair81750622023-03-08 15:02:06 -0800166 for (const auto& args : update.createdLayers) {
167 entryProto.mutable_added_layers()->Add(std::move(mProtoParser.toProto(args)));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800168 }
Vishnu Nair286f4f92022-06-08 16:37:39 -0700169
Vishnu Nair81750622023-03-08 15:02:06 -0800170 entryProto.mutable_destroyed_layers()->Reserve(
171 static_cast<int32_t>(destroyedLayers.size()));
172 for (auto& destroyedLayer : destroyedLayers) {
173 entryProto.mutable_destroyed_layers()->Add(destroyedLayer);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800174 }
Vishnu Nair7891e962021-11-11 12:07:21 -0800175 entryProto.mutable_transactions()->Reserve(
Vishnu Nair81750622023-03-08 15:02:06 -0800176 static_cast<int32_t>(update.transactionIds.size()));
177 for (const uint64_t& id : update.transactionIds) {
Vishnu Nair7891e962021-11-11 12:07:21 -0800178 auto it = mQueuedTransactions.find(id);
179 if (it != mQueuedTransactions.end()) {
180 entryProto.mutable_transactions()->Add(std::move(it->second));
181 mQueuedTransactions.erase(it);
182 } else {
Vishnu Nair047fb332021-12-09 09:54:36 -0800183 ALOGW("Could not find transaction id %" PRIu64, id);
Vishnu Nair7891e962021-11-11 12:07:21 -0800184 }
185 }
Vishnu Nair62863552021-12-10 13:34:48 -0800186
Vishnu Nair81750622023-03-08 15:02:06 -0800187 entryProto.mutable_destroyed_layer_handles()->Reserve(
188 static_cast<int32_t>(update.destroyedLayerHandles.size()));
189 for (auto layerId : update.destroyedLayerHandles) {
190 entryProto.mutable_destroyed_layer_handles()->Add(layerId);
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700191 }
Vishnu Nair81750622023-03-08 15:02:06 -0800192
193 entryProto.set_displays_changed(update.displayInfoChanged);
194 if (update.displayInfoChanged) {
195 entryProto.mutable_displays()->Reserve(
196 static_cast<int32_t>(update.displayInfos.size()));
197 for (auto& [layerStack, displayInfo] : update.displayInfos) {
198 entryProto.mutable_displays()->Add(
199 std::move(mProtoParser.toProto(displayInfo, layerStack.id)));
200 }
201 }
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700202
Vishnu Nair62863552021-12-10 13:34:48 -0800203 std::string serializedProto;
204 entryProto.SerializeToString(&serializedProto);
205 entryProto.Clear();
Dominik Laskowski46471e62022-01-14 15:34:03 -0800206 std::vector<std::string> entries = mBuffer.emplace(std::move(serializedProto));
Vishnu Nair62863552021-12-10 13:34:48 -0800207 removedEntries.reserve(removedEntries.size() + entries.size());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800208 removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
209 std::make_move_iterator(entries.end()));
210 }
211
Vishnu Nair62863552021-12-10 13:34:48 -0800212 proto::TransactionTraceEntry removedEntryProto;
213 for (const std::string& removedEntry : removedEntries) {
214 removedEntryProto.ParseFromString(removedEntry);
215 updateStartingStateLocked(removedEntryProto);
216 removedEntryProto.Clear();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800217 }
218 mTransactionsAddedToBufferCv.notify_one();
219}
220
221void TransactionTracing::flush(int64_t vsyncId) {
Vishnu Nair81750622023-03-08 15:02:06 -0800222 while (!mPendingUpdates.empty() || !mPendingDestroyedLayers.empty()) {
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800223 tryPushToTracingThread();
224 }
225 std::unique_lock<std::mutex> lock(mTraceLock);
226 base::ScopedLockAssertion assumeLocked(mTraceLock);
227 mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) {
Vishnu Nair62863552021-12-10 13:34:48 -0800228 proto::TransactionTraceEntry entry;
Dominik Laskowski46471e62022-01-14 15:34:03 -0800229 if (mBuffer.used() > 0) {
230 entry.ParseFromString(mBuffer.back());
Vishnu Nair62863552021-12-10 13:34:48 -0800231 }
Dominik Laskowski46471e62022-01-14 15:34:03 -0800232 return mBuffer.used() > 0 && entry.vsync_id() >= vsyncId;
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800233 });
234}
235
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800236void TransactionTracing::onLayerRemoved(int32_t layerId) {
Vishnu Nair81750622023-03-08 15:02:06 -0800237 mPendingDestroyedLayers.emplace_back(layerId);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800238 tryPushToTracingThread();
239}
240
241void TransactionTracing::tryPushToTracingThread() {
242 // Try to acquire the lock from main thread.
243 if (mMainThreadLock.try_lock()) {
244 // We got the lock! Collect any pending transactions and continue.
Vishnu Nair81750622023-03-08 15:02:06 -0800245 mUpdates.insert(mUpdates.end(), std::make_move_iterator(mPendingUpdates.begin()),
246 std::make_move_iterator(mPendingUpdates.end()));
247 mPendingUpdates.clear();
248 mDestroyedLayers.insert(mDestroyedLayers.end(), mPendingDestroyedLayers.begin(),
249 mPendingDestroyedLayers.end());
250 mPendingDestroyedLayers.clear();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800251 mTransactionsAvailableCv.notify_one();
252 mMainThreadLock.unlock();
253 } else {
254 ALOGV("Couldn't get lock");
Vishnu Nair7891e962021-11-11 12:07:21 -0800255 }
256}
257
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800258void TransactionTracing::updateStartingStateLocked(
259 const proto::TransactionTraceEntry& removedEntry) {
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800260 mStartingTimestamp = removedEntry.elapsed_realtime_nanos();
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800261 // Keep track of layer starting state so we can reconstruct the layer state as we purge
262 // transactions from the buffer.
263 for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) {
264 TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()];
265 startingState.layerId = addedLayer.layer_id();
Vishnu Nair685cfef2022-02-02 10:01:25 -0800266 mProtoParser.fromProto(addedLayer, startingState.args);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800267 }
268
269 // Merge layer states to starting transaction state.
270 for (const proto::TransactionState& transaction : removedEntry.transactions()) {
271 for (const proto::LayerState& layerState : transaction.layer_changes()) {
Vishnu Nair81750622023-03-08 15:02:06 -0800272 auto it = mStartingStates.find(layerState.layer_id());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800273 if (it == mStartingStates.end()) {
Vishnu Nair20e1f962023-03-29 15:58:34 -0700274 // TODO(b/238781169) make this log fatal when we switch over to using new fe
Vishnu Nair81750622023-03-08 15:02:06 -0800275 ALOGW("Could not find layer id %d", layerState.layer_id());
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800276 continue;
277 }
Vishnu Nair685cfef2022-02-02 10:01:25 -0800278 mProtoParser.mergeFromProto(layerState, it->second);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800279 }
280 }
281
Vishnu Nair81750622023-03-08 15:02:06 -0800282 for (const uint32_t destroyedLayerHandleId : removedEntry.destroyed_layer_handles()) {
283 mRemovedLayerHandlesAtStart.insert(destroyedLayerHandleId);
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700284 }
285
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800286 // Clean up stale starting states since the layer has been removed and the buffer does not
287 // contain any references to the layer.
Vishnu Nair81750622023-03-08 15:02:06 -0800288 for (const uint32_t destroyedLayerId : removedEntry.destroyed_layers()) {
289 mStartingStates.erase(destroyedLayerId);
290 mRemovedLayerHandlesAtStart.erase(destroyedLayerId);
291 }
292
293 if (removedEntry.displays_changed()) {
294 mProtoParser.fromProto(removedEntry.displays(), mStartingDisplayInfos);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800295 }
296}
297
298void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) {
Vishnu Nair84125ac2021-12-02 08:47:48 -0800299 if (mStartingStates.size() == 0) {
300 return;
301 }
302
Vishnu Nairb8f2a2d2022-01-13 08:10:10 -0800303 proto::TransactionTraceEntry* entryProto = proto.add_entry();
304 entryProto->set_elapsed_realtime_nanos(mStartingTimestamp);
305 entryProto->set_vsync_id(0);
306
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800307 entryProto->mutable_added_layers()->Reserve(static_cast<int32_t>(mStartingStates.size()));
308 for (auto& [layerId, state] : mStartingStates) {
Vishnu Nair685cfef2022-02-02 10:01:25 -0800309 entryProto->mutable_added_layers()->Add(mProtoParser.toProto(state.args));
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800310 }
311
Vishnu Nair685cfef2022-02-02 10:01:25 -0800312 proto::TransactionState transactionProto = mProtoParser.toProto(mStartingStates);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800313 transactionProto.set_vsync_id(0);
314 transactionProto.set_post_time(mStartingTimestamp);
315 entryProto->mutable_transactions()->Add(std::move(transactionProto));
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700316
Vishnu Nair81750622023-03-08 15:02:06 -0800317 entryProto->mutable_destroyed_layer_handles()->Reserve(
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700318 static_cast<int32_t>(mRemovedLayerHandlesAtStart.size()));
Vishnu Nair81750622023-03-08 15:02:06 -0800319 for (const uint32_t destroyedLayerHandleId : mRemovedLayerHandlesAtStart) {
320 entryProto->mutable_destroyed_layer_handles()->Add(destroyedLayerHandleId);
321 }
322
323 entryProto->mutable_displays()->Reserve(static_cast<int32_t>(mStartingDisplayInfos.size()));
324 for (auto& [layerStack, displayInfo] : mStartingDisplayInfos) {
325 entryProto->mutable_displays()->Add(mProtoParser.toProto(displayInfo, layerStack.id));
Vishnu Nair3e40cdd2022-06-08 16:50:17 -0700326 }
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800327}
328
329proto::TransactionTraceFile TransactionTracing::writeToProto() {
330 std::scoped_lock<std::mutex> lock(mTraceLock);
331 proto::TransactionTraceFile proto = createTraceFileProto();
332 addStartingStateToProtoLocked(proto);
Dominik Laskowski46471e62022-01-14 15:34:03 -0800333 mBuffer.writeToProto(proto);
Vishnu Nair0cc69e12021-11-18 09:05:49 -0800334 return proto;
Vishnu Nair7891e962021-11-11 12:07:21 -0800335}
336
337} // namespace android