Loading services/surfaceflinger/SurfaceFlinger.cpp +39 −31 Original line number Diff line number Diff line Loading @@ -505,10 +505,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI enableLatchUnsignaledConfig = getLatchUnsignaledConfig(); mTransactionTracingEnabled = !mIsUserBuild && property_get_bool("debug.sf.enable_transaction_tracing", true); if (mTransactionTracingEnabled) { mTransactionTracing.enable(); if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) { mTransactionTracing.emplace(); } } Loading Loading @@ -3770,8 +3768,8 @@ bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactio } } if (mTransactionTracingEnabled) { mTransactionTracing.addCommittedTransactions(transactions, vsyncId); if (mTransactionTracing) { mTransactionTracing->addCommittedTransactions(transactions, vsyncId); } return needsTraversal; } Loading Loading @@ -4031,8 +4029,8 @@ status_t SurfaceFlinger::setTransactionState( mBufferCountTracker.increment(state.surface->localBinder()); }); if (mTransactionTracingEnabled) { mTransactionTracing.addQueuedTransaction(state); if (mTransactionTracing) { mTransactionTracing->addQueuedTransaction(state); } queueTransaction(state); Loading Loading @@ -4568,8 +4566,8 @@ status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args, } *outLayerId = mirrorLayer->sequence; if (mTransactionTracingEnabled) { mTransactionTracing.onMirrorLayerAdded((*outHandle)->localBinder(), mirrorLayer->sequence, if (mTransactionTracing) { mTransactionTracing->onMirrorLayerAdded((*outHandle)->localBinder(), mirrorLayer->sequence, args.name, mirrorFrom->sequence); } return addClientLayer(args.client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */, Loading Loading @@ -4630,8 +4628,8 @@ status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHa if (parentSp != nullptr) { parentId = parentSp->getSequence(); } if (mTransactionTracingEnabled) { mTransactionTracing.onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name, if (mTransactionTracing) { mTransactionTracing->onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name, args.flags, parentId); } Loading Loading @@ -4722,8 +4720,8 @@ void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer) { markLayerPendingRemovalLocked(layer); mBufferCountTracker.remove(handle); layer.clear(); if (mTransactionTracingEnabled) { mTransactionTracing.onHandleRemoved(handle); if (mTransactionTracing) { mTransactionTracing->onHandleRemoved(handle); } } Loading Loading @@ -4958,7 +4956,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { if (asProto) { mLayerTracing.writeToFile(); mTransactionTracing.writeToFile(); if (mTransactionTracing) { mTransactionTracing->writeToFile(); } } return doDump(fd, DumpArgs(), asProto); Loading Loading @@ -5355,9 +5355,15 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co * Tracing state */ mLayerTracing.dump(result); result.append("\n"); mTransactionTracing.dump(result); result.append("\n"); result.append("\nTransaction tracing: "); if (mTransactionTracing) { result.append("enabled\n"); mTransactionTracing->dump(result); } else { result.append("disabled\n"); } result.push_back('\n'); /* * HWC layer minidump Loading Loading @@ -6037,15 +6043,17 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1041: { // Transaction tracing if (mTransactionTracing) { if (data.readInt32()) { // Transaction tracing is always running but allow the user to temporarily // increase the buffer when actively debugging. mTransactionTracing.setBufferSize( mTransactionTracing->setBufferSize( TransactionTracing::ACTIVE_TRACING_BUFFER_SIZE); } else { mTransactionTracing.setBufferSize( mTransactionTracing->setBufferSize( TransactionTracing::CONTINUOUS_TRACING_BUFFER_SIZE); mTransactionTracing.writeToFile(); mTransactionTracing->writeToFile(); } } reply->writeInt32(NO_ERROR); return NO_ERROR; Loading Loading @@ -6887,8 +6895,8 @@ void SurfaceFlinger::onLayerDestroyed(Layer* layer) { if (!layer->isRemovedFromCurrentState()) { mScheduler->deregisterLayer(layer); } if (mTransactionTracingEnabled) { mTransactionTracing.onLayerRemoved(layer->getSequence()); if (mTransactionTracing) { mTransactionTracing->onLayerRemoved(layer->getSequence()); } } Loading services/surfaceflinger/SurfaceFlinger.h +1 −2 Original line number Diff line number Diff line Loading @@ -1197,8 +1197,7 @@ private: LayerTracing mLayerTracing{*this}; bool mLayerTracingEnabled = false; TransactionTracing mTransactionTracing; bool mTransactionTracingEnabled = false; std::optional<TransactionTracing> mTransactionTracing; std::atomic<bool> mTracingEnabledChanged = false; const std::shared_ptr<TimeStats> mTimeStats; Loading services/surfaceflinger/Tracing/TransactionTracing.cpp +12 −53 Original line number Diff line number Diff line Loading @@ -23,35 +23,22 @@ #include <utils/SystemClock.h> #include <utils/Trace.h> #include "RingBuffer.h" #include "TransactionTracing.h" namespace android { TransactionTracing::TransactionTracing() { mBuffer = std::make_unique< RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry>>(); } TransactionTracing::~TransactionTracing() = default; bool TransactionTracing::enable() { std::scoped_lock lock(mTraceLock); if (mEnabled) { return false; } mBuffer->setSize(mBufferSizeInBytes); mBuffer.setSize(mBufferSizeInBytes); mStartingTimestamp = systemTime(); mEnabled = true; { std::scoped_lock lock(mMainThreadLock); mDone = false; mThread = std::thread(&TransactionTracing::loop, this); } return true; } bool TransactionTracing::disable() { TransactionTracing::~TransactionTracing() { std::thread thread; { std::scoped_lock lock(mMainThreadLock); Loading @@ -63,43 +50,20 @@ bool TransactionTracing::disable() { thread.join(); } std::scoped_lock lock(mTraceLock); if (!mEnabled) { return false; } mEnabled = false; writeToFileLocked(); mBuffer->reset(); mQueuedTransactions.clear(); mStartingStates.clear(); mLayerHandles.clear(); return true; } bool TransactionTracing::isEnabled() const { std::scoped_lock lock(mTraceLock); return mEnabled; writeToFile(); } status_t TransactionTracing::writeToFile() { std::scoped_lock lock(mTraceLock); if (!mEnabled) { return STATUS_OK; } return writeToFileLocked(); } status_t TransactionTracing::writeToFileLocked() { proto::TransactionTraceFile fileProto = createTraceFileProto(); addStartingStateToProtoLocked(fileProto); return mBuffer->writeToFile(fileProto, FILE_NAME); return mBuffer.writeToFile(fileProto, FILE_NAME); } void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) { std::scoped_lock lock(mTraceLock); mBufferSizeInBytes = bufferSizeInBytes; mBuffer->setSize(mBufferSizeInBytes); mBuffer.setSize(mBufferSizeInBytes); } proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { Loading @@ -111,21 +75,16 @@ proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { void TransactionTracing::dump(std::string& result) const { std::scoped_lock lock(mTraceLock); base::StringAppendF(&result, "Transaction tracing state: %s\n", mEnabled ? "enabled" : "disabled"); base::StringAppendF(&result, " queued transactions=%zu created layers=%zu handles=%zu states=%zu\n", mQueuedTransactions.size(), mCreatedLayers.size(), mLayerHandles.size(), mStartingStates.size()); mBuffer->dump(result); mBuffer.dump(result); } void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { std::scoped_lock lock(mTraceLock); ATRACE_CALL(); if (!mEnabled) { return; } mQueuedTransactions[transaction.id] = TransactionProtoParser::toProto(transaction, std::bind(&TransactionTracing::getLayerIdLocked, this, Loading Loading @@ -206,7 +165,7 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm std::string serializedProto; entryProto.SerializeToString(&serializedProto); entryProto.Clear(); std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto)); std::vector<std::string> entries = mBuffer.emplace(std::move(serializedProto)); removedEntries.reserve(removedEntries.size() + entries.size()); removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()), std::make_move_iterator(entries.end())); Loading @@ -229,10 +188,10 @@ void TransactionTracing::flush(int64_t vsyncId) { base::ScopedLockAssertion assumeLocked(mTraceLock); mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) { proto::TransactionTraceEntry entry; if (mBuffer->used() > 0) { entry.ParseFromString(mBuffer->back()); if (mBuffer.used() > 0) { entry.ParseFromString(mBuffer.back()); } return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId; return mBuffer.used() > 0 && entry.vsync_id() >= vsyncId; }); } Loading Loading @@ -352,7 +311,7 @@ proto::TransactionTraceFile TransactionTracing::writeToProto() { std::scoped_lock<std::mutex> lock(mTraceLock); proto::TransactionTraceFile proto = createTraceFileProto(); addStartingStateToProtoLocked(proto); mBuffer->writeToProto(proto); mBuffer.writeToProto(proto); return proto; } Loading services/surfaceflinger/Tracing/TransactionTracing.h +3 −10 Original line number Diff line number Diff line Loading @@ -25,17 +25,16 @@ #include <mutex> #include <thread> #include "RingBuffer.h" #include "TransactionProtoParser.h" using namespace android::surfaceflinger; namespace android { template <typename FileProto, typename EntryProto> class RingBuffer; class SurfaceFlinger; class TransactionTracingTest; /* * Records all committed transactions into a ring bufffer. * Loading @@ -54,10 +53,6 @@ public: TransactionTracing(); ~TransactionTracing(); bool enable(); bool disable(); bool isEnabled() const; void addQueuedTransaction(const TransactionState&); void addCommittedTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId); status_t writeToFile(); Loading @@ -78,8 +73,7 @@ private: static constexpr auto FILE_NAME = "/data/misc/wmtrace/transactions_trace.winscope"; mutable std::mutex mTraceLock; bool mEnabled GUARDED_BY(mTraceLock) = false; std::unique_ptr<RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry>> mBuffer RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer GUARDED_BY(mTraceLock); size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions Loading Loading @@ -116,7 +110,6 @@ private: void tryPushToTracingThread() EXCLUDES(mMainThreadLock); void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); status_t writeToFileLocked() REQUIRES(mTraceLock); // TEST // Wait until all the committed transactions for the specified vsync id are added to the buffer. Loading services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +30 −105 Original line number Diff line number Diff line Loading @@ -29,79 +29,32 @@ namespace android { class TransactionTracingTest : public testing::Test { protected: static constexpr size_t SMALL_BUFFER_SIZE = 1024; std::unique_ptr<android::TransactionTracing> mTracing; void SetUp() override { mTracing = std::make_unique<android::TransactionTracing>(); } TransactionTracing mTracing; void TearDown() override { mTracing->disable(); mTracing.reset(); } auto getCommittedTransactions() { std::scoped_lock<std::mutex> lock(mTracing->mMainThreadLock); return mTracing->mCommittedTransactions; } auto getQueuedTransactions() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mQueuedTransactions; } auto getUsedBufferSize() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mBuffer->used(); } auto flush(int64_t vsyncId) { return mTracing->flush(vsyncId); } void flush(int64_t vsyncId) { mTracing.flush(vsyncId); } proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } auto bufferFront() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); proto::TransactionTraceEntry bufferFront() { std::scoped_lock<std::mutex> lock(mTracing.mTraceLock); proto::TransactionTraceEntry entry; entry.ParseFromString(mTracing->mBuffer->front()); entry.ParseFromString(mTracing.mBuffer.front()); return entry; } bool threadIsJoinable() { std::scoped_lock lock(mTracing->mMainThreadLock); return mTracing->mThread.joinable(); } proto::TransactionTraceFile writeToProto() { return mTracing->writeToProto(); } auto getCreatedLayers() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mCreatedLayers; } auto getStartingStates() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mStartingStates; } void queueAndCommitTransaction(int64_t vsyncId) { TransactionState transaction; transaction.id = static_cast<uint64_t>(vsyncId * 3); transaction.originUid = 1; transaction.originPid = 2; mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); mTracing->addCommittedTransactions(transactions, vsyncId); mTracing.addCommittedTransactions(transactions, vsyncId); flush(vsyncId); } // Test that we clean up the tracing thread and free any memory allocated. void verifyDisabledTracingState() { EXPECT_FALSE(mTracing->isEnabled()); EXPECT_FALSE(threadIsJoinable()); EXPECT_EQ(getCommittedTransactions().size(), 0u); EXPECT_EQ(getQueuedTransactions().size(), 0u); EXPECT_EQ(getUsedBufferSize(), 0u); EXPECT_EQ(getStartingStates().size(), 0u); } void verifyEntry(const proto::TransactionTraceEntry& actualProto, const std::vector<TransactionState> expectedTransactions, const std::vector<TransactionState>& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); EXPECT_EQ(actualProto.transactions().size(), Loading @@ -113,16 +66,7 @@ protected: } }; TEST_F(TransactionTracingTest, enable) { EXPECT_FALSE(mTracing->isEnabled()); mTracing->enable(); EXPECT_TRUE(mTracing->isEnabled()); mTracing->disable(); verifyDisabledTracingState(); } TEST_F(TransactionTracingTest, addTransactions) { mTracing->enable(); std::vector<TransactionState> transactions; transactions.reserve(100); for (uint64_t i = 0; i < 100; i++) { Loading @@ -130,7 +74,7 @@ TEST_F(TransactionTracingTest, addTransactions) { transaction.id = i; transaction.originPid = static_cast<int32_t>(i); transactions.emplace_back(transaction); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); } // Split incoming transactions into two and commit them in reverse order to test out of order Loading @@ -138,12 +82,12 @@ TEST_F(TransactionTracingTest, addTransactions) { std::vector<TransactionState> firstTransactionSet = std::vector<TransactionState>(transactions.begin() + 50, transactions.end()); int64_t firstTransactionSetVsyncId = 42; mTracing->addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId); mTracing.addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId); int64_t secondTransactionSetVsyncId = 43; std::vector<TransactionState> secondTransactionSet = std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50); mTracing->addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId); mTracing.addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId); flush(secondTransactionSetVsyncId); proto::TransactionTraceFile proto = writeToProto(); Loading @@ -151,23 +95,18 @@ TEST_F(TransactionTracingTest, addTransactions) { // skip starting entry verifyEntry(proto.entry(1), firstTransactionSet, firstTransactionSetVsyncId); verifyEntry(proto.entry(2), secondTransactionSet, secondTransactionSetVsyncId); mTracing->disable(); verifyDisabledTracingState(); } class TransactionTracingLayerHandlingTest : public TransactionTracingTest { protected: void SetUp() override { TransactionTracingTest::SetUp(); mTracing->enable(); // add layers mTracing->setBufferSize(SMALL_BUFFER_SIZE); mTracing.setBufferSize(SMALL_BUFFER_SIZE); const sp<IBinder> fakeLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent", mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent", 123 /* flags */, -1 /* parentId */); const sp<IBinder> fakeChildLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child", mTracing.onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child", 456 /* flags */, mParentLayerId); // add some layer transaction Loading @@ -184,12 +123,12 @@ protected: childState.state.what = layer_state_t::eLayerChanged; childState.state.z = 43; transaction.states.add(childState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId; mTracing->addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE); mTracing.addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE); flush(VSYNC_ID_FIRST_LAYER_CHANGE); } Loading @@ -204,31 +143,25 @@ protected: layerState.state.z = 41; layerState.state.x = 22; transaction.states.add(layerState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId; mTracing->addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE); mTracing.addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE); flush(VSYNC_ID_SECOND_LAYER_CHANGE); } // remove child layer mTracing->onLayerRemoved(2); mTracing.onLayerRemoved(2); VSYNC_ID_CHILD_LAYER_REMOVED = ++mVsyncId; queueAndCommitTransaction(VSYNC_ID_CHILD_LAYER_REMOVED); // remove layer mTracing->onLayerRemoved(1); mTracing.onLayerRemoved(1); queueAndCommitTransaction(++mVsyncId); } void TearDown() override { mTracing->disable(); verifyDisabledTracingState(); TransactionTracingTest::TearDown(); } int mParentLayerId = 1; int mChildLayerId = 2; int64_t mVsyncId = 0; Loading Loading @@ -298,15 +231,13 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { class TransactionTracingMirrorLayerTest : public TransactionTracingTest { protected: void SetUp() override { TransactionTracingTest::SetUp(); mTracing->enable(); // add layers mTracing->setBufferSize(SMALL_BUFFER_SIZE); mTracing.setBufferSize(SMALL_BUFFER_SIZE); const sp<IBinder> fakeLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer", mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer", 123 /* flags */, -1 /* parentId */); const sp<IBinder> fakeMirrorLayerHandle = new BBinder(); mTracing->onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror", mTracing.onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror", mLayerId); // add some layer transaction Loading @@ -323,21 +254,15 @@ protected: mirrorState.state.what = layer_state_t::eLayerChanged; mirrorState.state.z = 43; transaction.states.add(mirrorState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); mTracing->addCommittedTransactions(transactions, ++mVsyncId); mTracing.addCommittedTransactions(transactions, ++mVsyncId); flush(mVsyncId); } } void TearDown() override { mTracing->disable(); verifyDisabledTracingState(); TransactionTracingTest::TearDown(); } int mLayerId = 5; int mMirrorLayerId = 55; int64_t mVsyncId = 0; Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +39 −31 Original line number Diff line number Diff line Loading @@ -505,10 +505,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI enableLatchUnsignaledConfig = getLatchUnsignaledConfig(); mTransactionTracingEnabled = !mIsUserBuild && property_get_bool("debug.sf.enable_transaction_tracing", true); if (mTransactionTracingEnabled) { mTransactionTracing.enable(); if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) { mTransactionTracing.emplace(); } } Loading Loading @@ -3770,8 +3768,8 @@ bool SurfaceFlinger::applyTransactions(std::vector<TransactionState>& transactio } } if (mTransactionTracingEnabled) { mTransactionTracing.addCommittedTransactions(transactions, vsyncId); if (mTransactionTracing) { mTransactionTracing->addCommittedTransactions(transactions, vsyncId); } return needsTraversal; } Loading Loading @@ -4031,8 +4029,8 @@ status_t SurfaceFlinger::setTransactionState( mBufferCountTracker.increment(state.surface->localBinder()); }); if (mTransactionTracingEnabled) { mTransactionTracing.addQueuedTransaction(state); if (mTransactionTracing) { mTransactionTracing->addQueuedTransaction(state); } queueTransaction(state); Loading Loading @@ -4568,8 +4566,8 @@ status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args, } *outLayerId = mirrorLayer->sequence; if (mTransactionTracingEnabled) { mTransactionTracing.onMirrorLayerAdded((*outHandle)->localBinder(), mirrorLayer->sequence, if (mTransactionTracing) { mTransactionTracing->onMirrorLayerAdded((*outHandle)->localBinder(), mirrorLayer->sequence, args.name, mirrorFrom->sequence); } return addClientLayer(args.client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */, Loading Loading @@ -4630,8 +4628,8 @@ status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHa if (parentSp != nullptr) { parentId = parentSp->getSequence(); } if (mTransactionTracingEnabled) { mTransactionTracing.onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name, if (mTransactionTracing) { mTransactionTracing->onLayerAdded((*outHandle)->localBinder(), layer->sequence, args.name, args.flags, parentId); } Loading Loading @@ -4722,8 +4720,8 @@ void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer) { markLayerPendingRemovalLocked(layer); mBufferCountTracker.remove(handle); layer.clear(); if (mTransactionTracingEnabled) { mTransactionTracing.onHandleRemoved(handle); if (mTransactionTracing) { mTransactionTracing->onHandleRemoved(handle); } } Loading Loading @@ -4958,7 +4956,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { if (asProto) { mLayerTracing.writeToFile(); mTransactionTracing.writeToFile(); if (mTransactionTracing) { mTransactionTracing->writeToFile(); } } return doDump(fd, DumpArgs(), asProto); Loading Loading @@ -5355,9 +5355,15 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co * Tracing state */ mLayerTracing.dump(result); result.append("\n"); mTransactionTracing.dump(result); result.append("\n"); result.append("\nTransaction tracing: "); if (mTransactionTracing) { result.append("enabled\n"); mTransactionTracing->dump(result); } else { result.append("disabled\n"); } result.push_back('\n'); /* * HWC layer minidump Loading Loading @@ -6037,15 +6043,17 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1041: { // Transaction tracing if (mTransactionTracing) { if (data.readInt32()) { // Transaction tracing is always running but allow the user to temporarily // increase the buffer when actively debugging. mTransactionTracing.setBufferSize( mTransactionTracing->setBufferSize( TransactionTracing::ACTIVE_TRACING_BUFFER_SIZE); } else { mTransactionTracing.setBufferSize( mTransactionTracing->setBufferSize( TransactionTracing::CONTINUOUS_TRACING_BUFFER_SIZE); mTransactionTracing.writeToFile(); mTransactionTracing->writeToFile(); } } reply->writeInt32(NO_ERROR); return NO_ERROR; Loading Loading @@ -6887,8 +6895,8 @@ void SurfaceFlinger::onLayerDestroyed(Layer* layer) { if (!layer->isRemovedFromCurrentState()) { mScheduler->deregisterLayer(layer); } if (mTransactionTracingEnabled) { mTransactionTracing.onLayerRemoved(layer->getSequence()); if (mTransactionTracing) { mTransactionTracing->onLayerRemoved(layer->getSequence()); } } Loading
services/surfaceflinger/SurfaceFlinger.h +1 −2 Original line number Diff line number Diff line Loading @@ -1197,8 +1197,7 @@ private: LayerTracing mLayerTracing{*this}; bool mLayerTracingEnabled = false; TransactionTracing mTransactionTracing; bool mTransactionTracingEnabled = false; std::optional<TransactionTracing> mTransactionTracing; std::atomic<bool> mTracingEnabledChanged = false; const std::shared_ptr<TimeStats> mTimeStats; Loading
services/surfaceflinger/Tracing/TransactionTracing.cpp +12 −53 Original line number Diff line number Diff line Loading @@ -23,35 +23,22 @@ #include <utils/SystemClock.h> #include <utils/Trace.h> #include "RingBuffer.h" #include "TransactionTracing.h" namespace android { TransactionTracing::TransactionTracing() { mBuffer = std::make_unique< RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry>>(); } TransactionTracing::~TransactionTracing() = default; bool TransactionTracing::enable() { std::scoped_lock lock(mTraceLock); if (mEnabled) { return false; } mBuffer->setSize(mBufferSizeInBytes); mBuffer.setSize(mBufferSizeInBytes); mStartingTimestamp = systemTime(); mEnabled = true; { std::scoped_lock lock(mMainThreadLock); mDone = false; mThread = std::thread(&TransactionTracing::loop, this); } return true; } bool TransactionTracing::disable() { TransactionTracing::~TransactionTracing() { std::thread thread; { std::scoped_lock lock(mMainThreadLock); Loading @@ -63,43 +50,20 @@ bool TransactionTracing::disable() { thread.join(); } std::scoped_lock lock(mTraceLock); if (!mEnabled) { return false; } mEnabled = false; writeToFileLocked(); mBuffer->reset(); mQueuedTransactions.clear(); mStartingStates.clear(); mLayerHandles.clear(); return true; } bool TransactionTracing::isEnabled() const { std::scoped_lock lock(mTraceLock); return mEnabled; writeToFile(); } status_t TransactionTracing::writeToFile() { std::scoped_lock lock(mTraceLock); if (!mEnabled) { return STATUS_OK; } return writeToFileLocked(); } status_t TransactionTracing::writeToFileLocked() { proto::TransactionTraceFile fileProto = createTraceFileProto(); addStartingStateToProtoLocked(fileProto); return mBuffer->writeToFile(fileProto, FILE_NAME); return mBuffer.writeToFile(fileProto, FILE_NAME); } void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) { std::scoped_lock lock(mTraceLock); mBufferSizeInBytes = bufferSizeInBytes; mBuffer->setSize(mBufferSizeInBytes); mBuffer.setSize(mBufferSizeInBytes); } proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { Loading @@ -111,21 +75,16 @@ proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const { void TransactionTracing::dump(std::string& result) const { std::scoped_lock lock(mTraceLock); base::StringAppendF(&result, "Transaction tracing state: %s\n", mEnabled ? "enabled" : "disabled"); base::StringAppendF(&result, " queued transactions=%zu created layers=%zu handles=%zu states=%zu\n", mQueuedTransactions.size(), mCreatedLayers.size(), mLayerHandles.size(), mStartingStates.size()); mBuffer->dump(result); mBuffer.dump(result); } void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) { std::scoped_lock lock(mTraceLock); ATRACE_CALL(); if (!mEnabled) { return; } mQueuedTransactions[transaction.id] = TransactionProtoParser::toProto(transaction, std::bind(&TransactionTracing::getLayerIdLocked, this, Loading Loading @@ -206,7 +165,7 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm std::string serializedProto; entryProto.SerializeToString(&serializedProto); entryProto.Clear(); std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto)); std::vector<std::string> entries = mBuffer.emplace(std::move(serializedProto)); removedEntries.reserve(removedEntries.size() + entries.size()); removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()), std::make_move_iterator(entries.end())); Loading @@ -229,10 +188,10 @@ void TransactionTracing::flush(int64_t vsyncId) { base::ScopedLockAssertion assumeLocked(mTraceLock); mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) { proto::TransactionTraceEntry entry; if (mBuffer->used() > 0) { entry.ParseFromString(mBuffer->back()); if (mBuffer.used() > 0) { entry.ParseFromString(mBuffer.back()); } return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId; return mBuffer.used() > 0 && entry.vsync_id() >= vsyncId; }); } Loading Loading @@ -352,7 +311,7 @@ proto::TransactionTraceFile TransactionTracing::writeToProto() { std::scoped_lock<std::mutex> lock(mTraceLock); proto::TransactionTraceFile proto = createTraceFileProto(); addStartingStateToProtoLocked(proto); mBuffer->writeToProto(proto); mBuffer.writeToProto(proto); return proto; } Loading
services/surfaceflinger/Tracing/TransactionTracing.h +3 −10 Original line number Diff line number Diff line Loading @@ -25,17 +25,16 @@ #include <mutex> #include <thread> #include "RingBuffer.h" #include "TransactionProtoParser.h" using namespace android::surfaceflinger; namespace android { template <typename FileProto, typename EntryProto> class RingBuffer; class SurfaceFlinger; class TransactionTracingTest; /* * Records all committed transactions into a ring bufffer. * Loading @@ -54,10 +53,6 @@ public: TransactionTracing(); ~TransactionTracing(); bool enable(); bool disable(); bool isEnabled() const; void addQueuedTransaction(const TransactionState&); void addCommittedTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId); status_t writeToFile(); Loading @@ -78,8 +73,7 @@ private: static constexpr auto FILE_NAME = "/data/misc/wmtrace/transactions_trace.winscope"; mutable std::mutex mTraceLock; bool mEnabled GUARDED_BY(mTraceLock) = false; std::unique_ptr<RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry>> mBuffer RingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer GUARDED_BY(mTraceLock); size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions Loading Loading @@ -116,7 +110,6 @@ private: void tryPushToTracingThread() EXCLUDES(mMainThreadLock); void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock); void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock); status_t writeToFileLocked() REQUIRES(mTraceLock); // TEST // Wait until all the committed transactions for the specified vsync id are added to the buffer. Loading
services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +30 −105 Original line number Diff line number Diff line Loading @@ -29,79 +29,32 @@ namespace android { class TransactionTracingTest : public testing::Test { protected: static constexpr size_t SMALL_BUFFER_SIZE = 1024; std::unique_ptr<android::TransactionTracing> mTracing; void SetUp() override { mTracing = std::make_unique<android::TransactionTracing>(); } TransactionTracing mTracing; void TearDown() override { mTracing->disable(); mTracing.reset(); } auto getCommittedTransactions() { std::scoped_lock<std::mutex> lock(mTracing->mMainThreadLock); return mTracing->mCommittedTransactions; } auto getQueuedTransactions() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mQueuedTransactions; } auto getUsedBufferSize() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mBuffer->used(); } auto flush(int64_t vsyncId) { return mTracing->flush(vsyncId); } void flush(int64_t vsyncId) { mTracing.flush(vsyncId); } proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); } auto bufferFront() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); proto::TransactionTraceEntry bufferFront() { std::scoped_lock<std::mutex> lock(mTracing.mTraceLock); proto::TransactionTraceEntry entry; entry.ParseFromString(mTracing->mBuffer->front()); entry.ParseFromString(mTracing.mBuffer.front()); return entry; } bool threadIsJoinable() { std::scoped_lock lock(mTracing->mMainThreadLock); return mTracing->mThread.joinable(); } proto::TransactionTraceFile writeToProto() { return mTracing->writeToProto(); } auto getCreatedLayers() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mCreatedLayers; } auto getStartingStates() { std::scoped_lock<std::mutex> lock(mTracing->mTraceLock); return mTracing->mStartingStates; } void queueAndCommitTransaction(int64_t vsyncId) { TransactionState transaction; transaction.id = static_cast<uint64_t>(vsyncId * 3); transaction.originUid = 1; transaction.originPid = 2; mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); mTracing->addCommittedTransactions(transactions, vsyncId); mTracing.addCommittedTransactions(transactions, vsyncId); flush(vsyncId); } // Test that we clean up the tracing thread and free any memory allocated. void verifyDisabledTracingState() { EXPECT_FALSE(mTracing->isEnabled()); EXPECT_FALSE(threadIsJoinable()); EXPECT_EQ(getCommittedTransactions().size(), 0u); EXPECT_EQ(getQueuedTransactions().size(), 0u); EXPECT_EQ(getUsedBufferSize(), 0u); EXPECT_EQ(getStartingStates().size(), 0u); } void verifyEntry(const proto::TransactionTraceEntry& actualProto, const std::vector<TransactionState> expectedTransactions, const std::vector<TransactionState>& expectedTransactions, int64_t expectedVsyncId) { EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId); EXPECT_EQ(actualProto.transactions().size(), Loading @@ -113,16 +66,7 @@ protected: } }; TEST_F(TransactionTracingTest, enable) { EXPECT_FALSE(mTracing->isEnabled()); mTracing->enable(); EXPECT_TRUE(mTracing->isEnabled()); mTracing->disable(); verifyDisabledTracingState(); } TEST_F(TransactionTracingTest, addTransactions) { mTracing->enable(); std::vector<TransactionState> transactions; transactions.reserve(100); for (uint64_t i = 0; i < 100; i++) { Loading @@ -130,7 +74,7 @@ TEST_F(TransactionTracingTest, addTransactions) { transaction.id = i; transaction.originPid = static_cast<int32_t>(i); transactions.emplace_back(transaction); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); } // Split incoming transactions into two and commit them in reverse order to test out of order Loading @@ -138,12 +82,12 @@ TEST_F(TransactionTracingTest, addTransactions) { std::vector<TransactionState> firstTransactionSet = std::vector<TransactionState>(transactions.begin() + 50, transactions.end()); int64_t firstTransactionSetVsyncId = 42; mTracing->addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId); mTracing.addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId); int64_t secondTransactionSetVsyncId = 43; std::vector<TransactionState> secondTransactionSet = std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50); mTracing->addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId); mTracing.addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId); flush(secondTransactionSetVsyncId); proto::TransactionTraceFile proto = writeToProto(); Loading @@ -151,23 +95,18 @@ TEST_F(TransactionTracingTest, addTransactions) { // skip starting entry verifyEntry(proto.entry(1), firstTransactionSet, firstTransactionSetVsyncId); verifyEntry(proto.entry(2), secondTransactionSet, secondTransactionSetVsyncId); mTracing->disable(); verifyDisabledTracingState(); } class TransactionTracingLayerHandlingTest : public TransactionTracingTest { protected: void SetUp() override { TransactionTracingTest::SetUp(); mTracing->enable(); // add layers mTracing->setBufferSize(SMALL_BUFFER_SIZE); mTracing.setBufferSize(SMALL_BUFFER_SIZE); const sp<IBinder> fakeLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent", mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent", 123 /* flags */, -1 /* parentId */); const sp<IBinder> fakeChildLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child", mTracing.onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child", 456 /* flags */, mParentLayerId); // add some layer transaction Loading @@ -184,12 +123,12 @@ protected: childState.state.what = layer_state_t::eLayerChanged; childState.state.z = 43; transaction.states.add(childState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId; mTracing->addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE); mTracing.addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE); flush(VSYNC_ID_FIRST_LAYER_CHANGE); } Loading @@ -204,31 +143,25 @@ protected: layerState.state.z = 41; layerState.state.x = 22; transaction.states.add(layerState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId; mTracing->addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE); mTracing.addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE); flush(VSYNC_ID_SECOND_LAYER_CHANGE); } // remove child layer mTracing->onLayerRemoved(2); mTracing.onLayerRemoved(2); VSYNC_ID_CHILD_LAYER_REMOVED = ++mVsyncId; queueAndCommitTransaction(VSYNC_ID_CHILD_LAYER_REMOVED); // remove layer mTracing->onLayerRemoved(1); mTracing.onLayerRemoved(1); queueAndCommitTransaction(++mVsyncId); } void TearDown() override { mTracing->disable(); verifyDisabledTracingState(); TransactionTracingTest::TearDown(); } int mParentLayerId = 1; int mChildLayerId = 2; int64_t mVsyncId = 0; Loading Loading @@ -298,15 +231,13 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { class TransactionTracingMirrorLayerTest : public TransactionTracingTest { protected: void SetUp() override { TransactionTracingTest::SetUp(); mTracing->enable(); // add layers mTracing->setBufferSize(SMALL_BUFFER_SIZE); mTracing.setBufferSize(SMALL_BUFFER_SIZE); const sp<IBinder> fakeLayerHandle = new BBinder(); mTracing->onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer", mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer", 123 /* flags */, -1 /* parentId */); const sp<IBinder> fakeMirrorLayerHandle = new BBinder(); mTracing->onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror", mTracing.onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror", mLayerId); // add some layer transaction Loading @@ -323,21 +254,15 @@ protected: mirrorState.state.what = layer_state_t::eLayerChanged; mirrorState.state.z = 43; transaction.states.add(mirrorState); mTracing->addQueuedTransaction(transaction); mTracing.addQueuedTransaction(transaction); std::vector<TransactionState> transactions; transactions.emplace_back(transaction); mTracing->addCommittedTransactions(transactions, ++mVsyncId); mTracing.addCommittedTransactions(transactions, ++mVsyncId); flush(mVsyncId); } } void TearDown() override { mTracing->disable(); verifyDisabledTracingState(); TransactionTracingTest::TearDown(); } int mLayerId = 5; int mMirrorLayerId = 55; int64_t mVsyncId = 0; Loading