diff options
| author | 2023-08-17 21:03:57 -0700 | |
|---|---|---|
| committer | 2023-08-21 07:33:19 -0700 | |
| commit | 8c5b700a85f70b69e844545d23193a0eac622732 (patch) | |
| tree | a65ab88cfca4b989d01a805ee63f285ae7c6d494 | |
| parent | 3e7eb31b766ddc40bea9ce9b3d839187bceb9290 (diff) | |
[sf] Add TransactionTraceWriterTests
Bug: 238781169, 294989213
Test: presubmit
Change-Id: Ibeb4118b08424ae28f4f48442f977a433aeff18e
6 files changed, 123 insertions, 24 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1ef381c417..d8b920e750 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -863,30 +863,32 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { ALOGE("Run StartPropertySetThread failed!"); } - if (mTransactionTracing) { - TransactionTraceWriter::getInstance().setWriterFunction([&](const std::string& prefix, - bool overwrite) { - auto writeFn = [&]() { - const std::string filename = - TransactionTracing::DIR_NAME + prefix + TransactionTracing::FILE_NAME; - if (!overwrite && access(filename.c_str(), F_OK) == 0) { - ALOGD("TransactionTraceWriter: file=%s already exists", filename.c_str()); - return; - } - mTransactionTracing->flush(); - mTransactionTracing->writeToFile(filename); - }; - if (std::this_thread::get_id() == mMainThreadId) { - writeFn(); - } else { - mScheduler->schedule(writeFn).get(); - } - }); - } - + initTransactionTraceWriter(); ALOGV("Done initializing"); } +void SurfaceFlinger::initTransactionTraceWriter() { + if (!mTransactionTracing) { + return; + } + TransactionTraceWriter::getInstance().setWriterFunction( + [&](const std::string& filename, bool overwrite) { + auto writeFn = [&]() { + if (!overwrite && access(filename.c_str(), F_OK) == 0) { + ALOGD("TransactionTraceWriter: file=%s already exists", filename.c_str()); + return; + } + mTransactionTracing->flush(); + mTransactionTracing->writeToFile(filename); + }; + if (std::this_thread::get_id() == mMainThreadId) { + writeFn(); + } else { + mScheduler->schedule(writeFn).get(); + } + }); +} + void SurfaceFlinger::readPersistentProperties() { Mutex::Autolock _l(mStateLock); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 4d17fa7d2a..175209fad4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1134,7 +1134,7 @@ private: ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const REQUIRES(mStateLock); void traverseLegacyLayers(const LayerVector::Visitor& visitor) const; - + void initTransactionTraceWriter(); sp<StartPropertySetThread> mStartPropertySetThread; surfaceflinger::Factory& mFactory; pid_t mPid; diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h index 31bca5fc66..422b5f3689 100644 --- a/services/surfaceflinger/Tracing/TransactionTracing.h +++ b/services/surfaceflinger/Tracing/TransactionTracing.h @@ -73,12 +73,16 @@ public: static constexpr auto TRACING_VERSION = 1; private: + friend class TransactionTraceWriter; friend class TransactionTracingTest; friend class SurfaceFlinger; static constexpr auto DIR_NAME = "/data/misc/wmtrace/"; static constexpr auto FILE_NAME = "transactions_trace.winscope"; static constexpr auto FILE_PATH = "/data/misc/wmtrace/transactions_trace.winscope"; + static std::string getFilePath(const std::string& prefix) { + return DIR_NAME + prefix + FILE_NAME; + } mutable std::mutex mTraceLock; TransactionRingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer @@ -138,10 +142,16 @@ class TransactionTraceWriter : public Singleton<TransactionTraceWriter> { public: void setWriterFunction( - std::function<void(const std::string& prefix, bool overwrite)> function) { + std::function<void(const std::string& filename, bool overwrite)> function) { mWriterFunction = std::move(function); } - void invoke(const std::string& prefix, bool overwrite) { mWriterFunction(prefix, overwrite); } + void invoke(const std::string& prefix, bool overwrite) { + mWriterFunction(TransactionTracing::getFilePath(prefix), overwrite); + } + /* pass in a complete file path for testing */ + void invokeForTest(const std::string& filename, bool overwrite) { + mWriterFunction(filename, overwrite); + } }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 3dd33b9957..7d8796f71c 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -66,6 +66,7 @@ cc_test { // option to false temporarily. address: true, }, + static_libs: ["libc++fs"], srcs: [ ":libsurfaceflinger_mock_sources", ":libsurfaceflinger_sources", @@ -128,6 +129,7 @@ cc_test { "TransactionFrameTracerTest.cpp", "TransactionProtoParserTest.cpp", "TransactionSurfaceFrameTest.cpp", + "TransactionTraceWriterTest.cpp", "TransactionTracingTest.cpp", "TunnelModeEnabledReporterTest.cpp", "StrongTypingTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 02fa4153ed..8458aa3ce0 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -651,6 +651,11 @@ public: auto fromHandle(const sp<IBinder>& handle) { return LayerHandle::getLayer(handle); } + auto initTransactionTraceWriter() { + mFlinger->mTransactionTracing.emplace(); + return mFlinger->initTransactionTraceWriter(); + } + ~TestableSurfaceFlinger() { // All these pointer and container clears help ensure that GMock does // not report a leaked object, since the SurfaceFlinger instance may @@ -664,6 +669,7 @@ public: mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); mFlinger->mRenderEngine = std::unique_ptr<renderengine::RenderEngine>(); mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); + mFlinger->mTransactionTracing.reset(); } /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp new file mode 100644 index 0000000000..379135e270 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TransactionTraceWriterTest.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "TransactionTraceWriterTest" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <log/log.h> +#include <filesystem> + +#include "TestableSurfaceFlinger.h" + +namespace android { + +class TransactionTraceWriterTest : public testing::Test { +protected: + std::string mFilename = "/data/local/tmp/testfile_transaction_trace.winscope"; + + void SetUp() { mFlinger.initTransactionTraceWriter(); } + void TearDown() { std::filesystem::remove(mFilename); } + + void verifyTraceFile() { + std::fstream file(mFilename, std::ios::in); + ASSERT_TRUE(file.is_open()); + std::string line; + char magicNumber[8]; + file.read(magicNumber, 8); + EXPECT_EQ("\tTNXTRAC", std::string(magicNumber, magicNumber + 8)); + } + + TestableSurfaceFlinger mFlinger; +}; + +TEST_F(TransactionTraceWriterTest, canWriteToFile) { + TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ true); + EXPECT_EQ(access(mFilename.c_str(), F_OK), 0); + verifyTraceFile(); +} + +TEST_F(TransactionTraceWriterTest, canOverwriteFile) { + std::string testLine = "test"; + { + std::ofstream file(mFilename, std::ios::out); + file << testLine; + } + TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ true); + verifyTraceFile(); +} + +TEST_F(TransactionTraceWriterTest, doNotOverwriteFile) { + std::string testLine = "test"; + { + std::ofstream file(mFilename, std::ios::out); + file << testLine; + } + TransactionTraceWriter::getInstance().invokeForTest(mFilename, /* overwrite */ false); + { + std::fstream file(mFilename, std::ios::in); + ASSERT_TRUE(file.is_open()); + std::string line; + std::getline(file, line); + EXPECT_EQ(line, testLine); + } +} +} // namespace android
\ No newline at end of file |