Integrate layer tracing with perfetto

Define the perfetto custom data source LayerDataSource.
LayerDataSource is registered with perfetto. The data source
is used to listen to perfetto events (setup, start, stop, flush)
and to write trace packets to perfetto.

The user can configure/start/stop tracing via /system/bin/perfetto.

Tracing can operate in the following modes.

ACTIVE mode:
A layers snapshot is taken and written to perfetto for each vsyncid commit.

GENERATED mode:
Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
When a 'flush' event is received, the ring buffer of transactions (hold by TransactionTracing)
is processed by LayerTraceGenerator, a sequence of layers snapshots is generated
and written to perfetto.

DUMP mode:
When the 'start' event is received a single layers snapshot is taken
and written to perfetto.

Bug: b/284424784
Test: atest libsurfaceflinger_unittest && atest transactiontrace_testsuite
Change-Id: I8baaae9c512284a0d4fc926094dd8ed6eb23a43f
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0101c17..3ceda8f 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -197,9 +197,11 @@
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
         "SurfaceFlingerDefaultFactory.cpp",
+        "Tracing/LayerDataSource.cpp",
         "Tracing/LayerTracing.cpp",
         "Tracing/TransactionTracing.cpp",
         "Tracing/TransactionProtoParser.cpp",
+        "Tracing/tools/LayerTraceGenerator.cpp",
         "TransactionCallbackInvoker.cpp",
         "TunnelModeEnabledReporter.cpp",
     ],
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f61b4de..65d56a8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -320,8 +320,6 @@
 
 const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
 
-static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB
-
 // ---------------------------------------------------------------------------
 int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
 bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -483,6 +481,7 @@
 
     if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
         mTransactionTracing.emplace();
+        mLayerTracing.setTransactionTracing(*mTransactionTracing);
     }
 
     mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false);
@@ -827,6 +826,17 @@
     initScheduler(display);
     dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
 
+    mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) {
+        auto snapshot = perfetto::protos::LayersSnapshotProto{};
+        mScheduler
+                ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
+                    snapshot = takeLayersSnapshotProto(traceFlags, TimePoint::now(),
+                                                       mLastCommittedVsyncId, true);
+                })
+                .wait();
+        return snapshot;
+    });
+
     // Commit secondary display(s).
     processDisplayChangesLocked();
 
@@ -2367,11 +2377,6 @@
         mTimeStats->incrementMissedFrames();
     }
 
-    if (mTracingEnabledChanged) {
-        mLayerTracingEnabled = mLayerTracing.isEnabled();
-        mTracingEnabledChanged = false;
-    }
-
     // If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
     if (std::any_of(frameTargets.begin(), frameTargets.end(),
                     [this](const auto& pair) FTL_FAKE_GUARD(mStateLock)
@@ -2498,11 +2503,9 @@
     if (!mustComposite) {
         updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime());
     }
+    doActiveLayersTracingIfNeeded(false, mVisibleRegionsDirty,
+                                  pacesetterFrameTarget.frameBeginTime(), vsyncId);
 
-    if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
-        // This will block and tracing should only be enabled for debugging.
-        addToLayerTracing(mVisibleRegionsDirty, pacesetterFrameTarget.frameBeginTime(), vsyncId);
-    }
     mLastCommittedVsyncId = vsyncId;
 
     persistDisplayBrightness(mustComposite);
@@ -2719,10 +2722,8 @@
 
     mLayersWithQueuedFrames.clear();
     mLayersIdsWithQueuedFrames.clear();
-    if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
-        // This will block and should only be used for debugging.
-        addToLayerTracing(mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(), vsyncId);
-    }
+    doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
+                                  vsyncId);
 
     updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
 
@@ -6336,11 +6337,6 @@
 
     StringAppendF(&result, "  transaction time: %f us\n", inTransactionDuration / 1000.0);
 
-    /*
-     * Tracing state
-     */
-    mLayerTracing.dump(result);
-
     result.append("\nTransaction tracing: ");
     if (mTransactionTracing) {
         result.append("enabled\n");
@@ -6699,42 +6695,13 @@
             case 1024: {
                 return NAME_NOT_FOUND;
             }
-            case 1025: { // Set layer tracing
-                n = data.readInt32();
-                bool tracingEnabledChanged;
-                if (n == 1) {
-                    int64_t fixedStartingTime = data.readInt64();
-                    ALOGD("LayerTracing enabled");
-                    tracingEnabledChanged = mLayerTracing.enable();
-                    if (tracingEnabledChanged) {
-                        const TimePoint startingTime = fixedStartingTime
-                                ? TimePoint::fromNs(fixedStartingTime)
-                                : TimePoint::now();
-
-                        mScheduler
-                                ->schedule([this, startingTime]() FTL_FAKE_GUARD(
-                                                   mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
-                                    constexpr bool kVisibleRegionDirty = true;
-                                    addToLayerTracing(kVisibleRegionDirty, startingTime,
-                                                      mLastCommittedVsyncId);
-                                })
-                                .wait();
-                    }
-                } else if (n == 2) {
-                    std::string filename = std::string(data.readCString());
-                    ALOGD("LayerTracing disabled. Trace wrote to %s", filename.c_str());
-                    tracingEnabledChanged = mLayerTracing.disable(filename.c_str());
-                } else {
-                    ALOGD("LayerTracing disabled");
-                    tracingEnabledChanged = mLayerTracing.disable();
-                }
-                mTracingEnabledChanged = tracingEnabledChanged;
-                reply->writeInt32(NO_ERROR);
-                return NO_ERROR;
+            // Deprecated, use perfetto to start/stop the layer tracing
+            case 1025: {
+                return NAME_NOT_FOUND;
             }
-            case 1026: { // Get layer tracing status
-                reply->writeBool(mLayerTracing.isEnabled());
-                return NO_ERROR;
+            // Deprecated, execute "adb shell perfetto --query" to see the ongoing tracing sessions
+            case 1026: {
+                return NAME_NOT_FOUND;
             }
             // Is a DisplayColorSetting supported?
             case 1027: {
@@ -6762,19 +6729,9 @@
             case 1028: { // Unused.
                 return NAME_NOT_FOUND;
             }
-            // Set buffer size for SF tracing (value in KB)
+            // Deprecated, use perfetto to set the active layer tracing buffer size
             case 1029: {
-                n = data.readInt32();
-                if (n <= 0 || n > MAX_TRACING_MEMORY) {
-                    ALOGW("Invalid buffer size: %d KB", n);
-                    reply->writeInt32(BAD_VALUE);
-                    return BAD_VALUE;
-                }
-
-                ALOGD("Updating trace buffer to %d KB", n);
-                mLayerTracing.setBufferSize(n * 1024);
-                reply->writeInt32(NO_ERROR);
-                return NO_ERROR;
+                return NAME_NOT_FOUND;
             }
             // Is device color managed?
             case 1030: {
@@ -6814,13 +6771,9 @@
                 }
                 return NO_ERROR;
             }
-            // Set trace flags
+            // Deprecated, use perfetto to set layer trace flags
             case 1033: {
-                n = data.readUint32();
-                ALOGD("Updating trace flags to 0x%x", n);
-                mLayerTracing.setTraceFlags(n);
-                reply->writeInt32(NO_ERROR);
-                return NO_ERROR;
+                return NAME_NOT_FOUND;
             }
             case 1034: {
                 auto future = mScheduler->schedule(
@@ -6985,9 +6938,6 @@
                 if (mTransactionTracing) {
                     mTransactionTracing->writeToFile();
                 }
-                if (mLayerTracingEnabled) {
-                    mLayerTracing.writeToFile();
-                }
                 reply->writeInt32(NO_ERROR);
                 return NO_ERROR;
             }
@@ -8748,19 +8698,50 @@
     return update;
 }
 
-void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, TimePoint time, VsyncId vsyncId) {
-    const uint32_t tracingFlags = mLayerTracing.getFlags();
-    perfetto::protos::LayersProto layers(dumpDrawingStateProto(tracingFlags));
-    if (tracingFlags & LayerTracing::TRACE_EXTRA) {
+void SurfaceFlinger::doActiveLayersTracingIfNeeded(bool isCompositionComputed,
+                                                   bool visibleRegionDirty, TimePoint time,
+                                                   VsyncId vsyncId) {
+    if (!mLayerTracing.isActiveTracingStarted()) {
+        return;
+    }
+    if (isCompositionComputed !=
+        mLayerTracing.isActiveTracingFlagSet(LayerTracing::Flag::TRACE_COMPOSITION)) {
+        return;
+    }
+    if (!visibleRegionDirty &&
+        !mLayerTracing.isActiveTracingFlagSet(LayerTracing::Flag::TRACE_BUFFERS)) {
+        return;
+    }
+    auto snapshot = takeLayersSnapshotProto(mLayerTracing.getActiveTracingFlags(), time, vsyncId,
+                                            visibleRegionDirty);
+    mLayerTracing.addProtoSnapshotToOstream(std::move(snapshot), LayerTracing::Mode::MODE_ACTIVE);
+}
+
+perfetto::protos::LayersSnapshotProto SurfaceFlinger::takeLayersSnapshotProto(
+        uint32_t traceFlags, TimePoint time, VsyncId vsyncId, bool visibleRegionDirty) {
+    ATRACE_CALL();
+    perfetto::protos::LayersSnapshotProto snapshot;
+    snapshot.set_elapsed_realtime_nanos(time.ns());
+    snapshot.set_vsync_id(ftl::to_underlying(vsyncId));
+    snapshot.set_where(visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched");
+    snapshot.set_excludes_composition_state((traceFlags & LayerTracing::Flag::TRACE_COMPOSITION) ==
+                                            0);
+
+    auto layers = dumpDrawingStateProto(traceFlags);
+    if (traceFlags & LayerTracing::Flag::TRACE_EXTRA) {
         dumpOffscreenLayersProto(layers);
     }
-    std::string hwcDump;
-    if (tracingFlags & LayerTracing::TRACE_HWC) {
+    *snapshot.mutable_layers() = std::move(layers);
+
+    if (traceFlags & LayerTracing::Flag::TRACE_HWC) {
+        std::string hwcDump;
         dumpHwc(hwcDump);
+        snapshot.set_hwc_blob(std::move(hwcDump));
     }
-    auto displays = dumpDisplayProto();
-    mLayerTracing.notify(visibleRegionDirty, time.ns(), ftl::to_underlying(vsyncId), &layers,
-                         std::move(hwcDump), &displays);
+
+    *snapshot.mutable_displays() = dumpDisplayProto();
+
+    return snapshot;
 }
 
 // gui::ISurfaceComposer
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 21b7faf..0e305a5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -368,7 +368,6 @@
     friend class RefreshRateOverlay;
     friend class RegionSamplingThread;
     friend class LayerRenderArea;
-    friend class LayerTracing;
     friend class SurfaceComposerAIDL;
     friend class DisplayRenderArea;
 
@@ -1092,7 +1091,10 @@
     void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto,
                                   uint32_t traceFlags = LayerTracing::TRACE_ALL) const;
     google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto> dumpDisplayProto() const;
-    void addToLayerTracing(bool visibleRegionDirty, TimePoint, VsyncId)
+    void doActiveLayersTracingIfNeeded(bool isCompositionComputed, bool visibleRegionDirty,
+                                       TimePoint, VsyncId) REQUIRES(kMainThreadContext);
+    perfetto::protos::LayersSnapshotProto takeLayersSnapshotProto(uint32_t flags, TimePoint,
+                                                                  VsyncId, bool visibleRegionDirty)
             REQUIRES(kMainThreadContext);
 
     // Dumps state from HW Composer
@@ -1257,10 +1259,7 @@
     bool mBackpressureGpuComposition = false;
 
     LayerTracing mLayerTracing;
-    bool mLayerTracingEnabled = false;
-
     std::optional<TransactionTracing> mTransactionTracing;
-    std::atomic<bool> mTracingEnabledChanged = false;
 
     const std::shared_ptr<TimeStats> mTimeStats;
     const std::unique_ptr<FrameTracer> mFrameTracer;
diff --git a/services/surfaceflinger/Tracing/LayerDataSource.cpp b/services/surfaceflinger/Tracing/LayerDataSource.cpp
new file mode 100644
index 0000000..474fef8
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerDataSource.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 "LayerTracing"
+
+#include "LayerDataSource.h"
+
+#include <log/log.h>
+#include <perfetto/config/android/surfaceflinger_layers_config.pbzero.h>
+
+namespace android {
+
+void LayerDataSource::Initialize(LayerTracing& layerTracing) {
+    mLayerTracing.store(&layerTracing);
+
+    auto args = perfetto::TracingInitArgs{};
+    args.backends = perfetto::kSystemBackend;
+    // We are tracing ~50kb/entry and the default shmem buffer size (256kb) could be overrun.
+    // A shmem buffer overrun typically just stalls layer tracing, however when the stall
+    // lasts for too long perfetto assumes there is a deadlock and aborts surfaceflinger.
+    args.shmem_size_hint_kb = 1024;
+    perfetto::Tracing::Initialize(args);
+
+    perfetto::DataSourceDescriptor descriptor;
+    descriptor.set_name(android::LayerDataSource::kName);
+    LayerDataSource::Register(descriptor);
+}
+
+void LayerDataSource::UnregisterLayerTracing() {
+    mLayerTracing.store(nullptr);
+}
+
+void LayerDataSource::OnSetup(const LayerDataSource::SetupArgs& args) {
+    const auto configRaw = args.config->surfaceflinger_layers_config_raw();
+    const auto config = perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Decoder{configRaw};
+
+    if (config.has_mode() && config.mode() != LayerTracing::Mode::MODE_UNSPECIFIED) {
+        mMode = static_cast<LayerTracing::Mode>(config.mode());
+    } else {
+        mMode = LayerTracing::Mode::MODE_GENERATED;
+        ALOGV("Received config with unspecified 'mode'. Using 'GENERATED' as default");
+    }
+
+    mFlags = 0;
+    for (auto it = config.trace_flags(); it; ++it) {
+        mFlags |= static_cast<uint32_t>(*it);
+    }
+}
+
+void LayerDataSource::OnStart(const LayerDataSource::StartArgs&) {
+    ALOGV("Received OnStart event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+    if (auto* p = mLayerTracing.load()) {
+        p->onStart(mMode, mFlags);
+    }
+}
+
+void LayerDataSource::OnFlush(const LayerDataSource::FlushArgs&) {
+    ALOGV("Received OnFlush event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+    if (auto* p = mLayerTracing.load()) {
+        p->onFlush(mMode, mFlags);
+    }
+}
+
+void LayerDataSource::OnStop(const LayerDataSource::StopArgs&) {
+    ALOGV("Received OnStop event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+    if (auto* p = mLayerTracing.load()) {
+        p->onStop(mMode);
+    }
+}
+
+LayerTracing::Mode LayerDataSource::GetMode() const {
+    return mMode;
+}
+
+std::atomic<LayerTracing*> LayerDataSource::mLayerTracing = nullptr;
+
+} // namespace android
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::LayerDataSource);
diff --git a/services/surfaceflinger/Tracing/LayerDataSource.h b/services/surfaceflinger/Tracing/LayerDataSource.h
new file mode 100644
index 0000000..7944092
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerDataSource.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "LayerTracing.h"
+
+#include <perfetto/tracing.h>
+
+#include <atomic>
+
+namespace android {
+
+/*
+ * Thread local storage used for fast (lock free) read of data source's properties.
+ *
+ */
+struct LayerDataSourceTlsState {
+    template <typename TraceContext>
+    explicit LayerDataSourceTlsState(const TraceContext& trace_context) {
+        auto dataSource = trace_context.GetDataSourceLocked();
+        mMode = dataSource.valid()
+                ? dataSource->GetMode()
+                : perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Mode::MODE_GENERATED;
+    }
+
+    LayerTracing::Mode mMode;
+};
+
+struct LayerDataSourceTraits : public perfetto::DefaultDataSourceTraits {
+    using TlsStateType = LayerDataSourceTlsState;
+};
+
+/*
+ * Defines the Perfetto custom data source 'android.surfaceflinger.layers'.
+ *
+ * Registers the data source with Perfetto, listens to Perfetto events (setup/start/flush/stop)
+ * and writes trace packets to Perfetto.
+ *
+ */
+class LayerDataSource : public perfetto::DataSource<LayerDataSource, LayerDataSourceTraits> {
+public:
+    static void Initialize(LayerTracing&);
+    static void UnregisterLayerTracing();
+    void OnSetup(const SetupArgs&) override;
+    void OnStart(const StartArgs&) override;
+    void OnFlush(const FlushArgs&) override;
+    void OnStop(const StopArgs&) override;
+    LayerTracing::Mode GetMode() const;
+
+    static constexpr auto* kName = "android.surfaceflinger.layers";
+    static constexpr perfetto::BufferExhaustedPolicy kBufferExhaustedPolicy =
+            perfetto::BufferExhaustedPolicy::kStall;
+    static constexpr bool kRequiresCallbacksUnderLock = false;
+
+private:
+    static std::atomic<LayerTracing*> mLayerTracing;
+    LayerTracing::Mode mMode;
+    std::uint32_t mFlags;
+};
+
+} // namespace android
+
+PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(android::LayerDataSource);
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
index b92d50b..e55b4c2 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.cpp
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -18,131 +18,177 @@
 #define LOG_TAG "LayerTracing"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <filesystem>
-
-#include <SurfaceFlinger.h>
-#include <android-base/stringprintf.h>
-#include <log/log.h>
-#include <utils/SystemClock.h>
-#include <utils/Trace.h>
-
 #include "LayerTracing.h"
-#include "TransactionRingBuffer.h"
+
+#include "LayerDataSource.h"
+#include "Tracing/tools/LayerTraceGenerator.h"
+#include "TransactionTracing.h"
+
+#include <log/log.h>
+#include <perfetto/tracing.h>
+#include <utils/Timers.h>
+#include <utils/Trace.h>
 
 namespace android {
 
-LayerTracing::LayerTracing()
-      : mBuffer(std::make_unique<TransactionRingBuffer<LayersTraceFileProto, LayersTraceProto>>()) {
+LayerTracing::LayerTracing() {
+    mTakeLayersSnapshotProto = [](uint32_t) { return perfetto::protos::LayersSnapshotProto{}; };
+    LayerDataSource::Initialize(*this);
 }
 
-LayerTracing::~LayerTracing() = default;
+LayerTracing::~LayerTracing() {
+    LayerDataSource::UnregisterLayerTracing();
+}
 
-bool LayerTracing::enable() {
-    std::scoped_lock lock(mTraceLock);
-    if (mEnabled) {
-        return false;
+void LayerTracing::setTakeLayersSnapshotProtoFunction(
+        const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& callback) {
+    mTakeLayersSnapshotProto = callback;
+}
+
+void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
+    mTransactionTracing = &transactionTracing;
+}
+
+void LayerTracing::setOutputStream(std::ostream& outStream) {
+    mOutStream = std::ref(outStream);
+}
+
+void LayerTracing::onStart(Mode mode, uint32_t flags) {
+    switch (mode) {
+        case Mode::MODE_ACTIVE: {
+            mActiveTracingFlags.store(flags);
+            mIsActiveTracingStarted.store(true);
+            ALOGV("Starting active tracing (waiting for initial snapshot)");
+            // It might take a while before a layers change occurs and a "spontaneous" snapshot is
+            // taken. Let's manually take a snapshot, so that the trace's first entry will contain
+            // the current layers state.
+            addProtoSnapshotToOstream(mTakeLayersSnapshotProto(flags), Mode::MODE_ACTIVE);
+            ALOGV("Started active tracing (traced initial snapshot)");
+            break;
+        }
+        case Mode::MODE_GENERATED: {
+            ALOGV("Started generated tracing (waiting for OnFlush event to generated layers)");
+            break;
+        }
+        case Mode::MODE_DUMP: {
+            ALOGV("Starting dump tracing (dumping single snapshot)");
+            auto snapshot = mTakeLayersSnapshotProto(flags);
+            addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
+            ALOGV("Started dump tracing (dumped single snapshot)");
+            break;
+        }
+        default: {
+            ALOGE("Started unknown tracing mode (0x%02x)", mode);
+        }
     }
-    mBuffer->setSize(mBufferSizeInBytes);
-    mEnabled = true;
-    return true;
 }
 
-bool LayerTracing::disable(std::string filename, bool writeToFile) {
-    std::scoped_lock lock(mTraceLock);
-    if (!mEnabled) {
-        return false;
+void LayerTracing::onFlush(Mode mode, uint32_t flags) {
+    // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
+    // generate a sequence of layers snapshots and write them to perfetto.
+    if (mode != Mode::MODE_GENERATED) {
+        return;
     }
-    mEnabled = false;
-    if (writeToFile) {
-        LayersTraceFileProto fileProto = createTraceFileProto();
-        mBuffer->writeToFile(fileProto, filename);
+
+    if (!mTransactionTracing) {
+        ALOGV("Skipping layers trace generation (transactions tracing disabled)");
+        return;
     }
-    mBuffer->reset();
-    return true;
+
+    auto transactionTrace = mTransactionTracing->writeToProto();
+    LayerTraceGenerator{}.generate(transactionTrace, flags);
+    ALOGV("Flushed generated tracing");
 }
 
-void LayerTracing::appendToStream(std::ofstream& out) {
-    std::scoped_lock lock(mTraceLock);
-    LayersTraceFileProto fileProto = createTraceFileProto();
-    mBuffer->appendToStream(fileProto, out);
-    mBuffer->reset();
-}
-
-bool LayerTracing::isEnabled() const {
-    std::scoped_lock lock(mTraceLock);
-    return mEnabled;
-}
-
-status_t LayerTracing::writeToFile(std::string filename) {
-    std::scoped_lock lock(mTraceLock);
-    if (!mEnabled) {
-        return STATUS_OK;
+void LayerTracing::onStop(Mode mode) {
+    if (mode == Mode::MODE_ACTIVE) {
+        mIsActiveTracingStarted.store(false);
+        ALOGV("Stopped active tracing");
     }
-    LayersTraceFileProto fileProto = createTraceFileProto();
-    return mBuffer->writeToFile(fileProto, filename);
 }
 
-void LayerTracing::setTraceFlags(uint32_t flags) {
-    std::scoped_lock lock(mTraceLock);
-    mFlags = flags;
+void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
+                                             Mode mode) {
+    ATRACE_CALL();
+    if (mOutStream) {
+        writeSnapshotToStream(std::move(snapshot));
+    } else {
+        writeSnapshotToPerfetto(snapshot, mode);
+    }
 }
 
-void LayerTracing::setBufferSize(size_t bufferSizeInBytes) {
-    std::scoped_lock lock(mTraceLock);
-    mBufferSizeInBytes = bufferSizeInBytes;
+bool LayerTracing::isActiveTracingStarted() const {
+    return mIsActiveTracingStarted.load();
 }
 
-bool LayerTracing::flagIsSet(uint32_t flags) const {
-    return (mFlags & flags) == flags;
-}
-uint32_t LayerTracing::getFlags() const {
-    return mFlags;
+uint32_t LayerTracing::getActiveTracingFlags() const {
+    return mActiveTracingFlags.load();
 }
 
-LayersTraceFileProto LayerTracing::createTraceFileProto() {
-    LayersTraceFileProto fileProto;
-    fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
-                               LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
-    auto timeOffsetNs = static_cast<std::uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
-                                                   systemTime(SYSTEM_TIME_MONOTONIC));
+bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
+    return (mActiveTracingFlags.load() & flag) != 0;
+}
+
+perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
+    perfetto::protos::LayersTraceFileProto fileProto;
+    fileProto.set_magic_number(
+            static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
+                    << 32 |
+            perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+    auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
+                                              systemTime(SYSTEM_TIME_MONOTONIC));
     fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
     return fileProto;
 }
 
-void LayerTracing::dump(std::string& result) const {
-    std::scoped_lock lock(mTraceLock);
-    base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
-    mBuffer->dump(result);
+void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
+    auto fileProto = createTraceFileProto();
+    *fileProto.add_entry() = std::move(snapshot);
+    mOutStream->get() << fileProto.SerializeAsString();
 }
 
-void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId,
-                          LayersProto* layers, std::string hwcDump,
-                          google::protobuf::RepeatedPtrField<DisplayProto>* displays) {
-    std::scoped_lock lock(mTraceLock);
-    if (!mEnabled) {
-        return;
+void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
+                                           Mode mode) {
+    const auto snapshotBytes = snapshot.SerializeAsString();
+
+    LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
+        if (mode != context.GetCustomTlsState()->mMode) {
+            return;
+        }
+        if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(mode, snapshot.vsync_id())) {
+            return;
+        }
+        {
+            auto packet = context.NewTracePacket();
+            packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
+            packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+            auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
+            snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
+        }
+        {
+            // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
+            //  It is currently needed in order not to lose the last trace entry.
+            context.NewTracePacket();
+        }
+    });
+}
+
+bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
+    // In some situations (e.g. two bugreports taken shortly one after the other) the generated
+    // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
+    // sure that in generated tracing mode a given snapshot is written only once to perfetto.
+    if (mode != Mode::MODE_GENERATED) {
+        return true;
     }
 
-    if (!visibleRegionDirty && !flagIsSet(LayerTracing::TRACE_BUFFERS)) {
-        return;
+    auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
+    while (lastVsyncId < vsyncId) {
+        if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
+            return true;
+        }
     }
 
-    ATRACE_CALL();
-    LayersTraceProto entry;
-    entry.set_elapsed_realtime_nanos(time);
-    const char* where = visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched";
-    entry.set_where(where);
-    entry.mutable_layers()->Swap(layers);
-
-    if (flagIsSet(LayerTracing::TRACE_HWC)) {
-        entry.set_hwc_blob(hwcDump);
-    }
-    if (!flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
-        entry.set_excludes_composition_state(true);
-    }
-    entry.mutable_displays()->Swap(displays);
-    entry.set_vsync_id(vsyncId);
-    mBuffer->emplace(std::move(entry));
+    return false;
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
index 7c0d23d..349cc40 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.h
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -16,42 +16,77 @@
 
 #pragma once
 
-#include <android-base/thread_annotations.h>
 #include <layerproto/LayerProtoHeader.h>
-#include <utils/Errors.h>
-#include <utils/StrongPointer.h>
-#include <utils/Timers.h>
 
-#include <memory>
-#include <mutex>
-
-using namespace android::surfaceflinger;
+#include <atomic>
+#include <functional>
+#include <optional>
+#include <ostream>
 
 namespace android {
 
-template <typename FileProto, typename EntryProto>
-class TransactionRingBuffer;
-
-class SurfaceFlinger;
+class TransactionTracing;
 
 /*
  * LayerTracing records layer states during surface flinging. Manages tracing state and
  * configuration.
+ *
+ * The traced data can then be collected with Perfetto.
+ *
+ * The Perfetto custom data source LayerDataSource is registered with perfetto. The data source
+ * is used to listen to perfetto events (setup, start, stop, flush) and to write trace packets
+ * to perfetto.
+ *
+ * The user can configure/start/stop tracing via /system/bin/perfetto.
+ *
+ * Tracing can operate in the following modes.
+ *
+ * ACTIVE mode:
+ * A layers snapshot is taken and written to perfetto for each vsyncid commit.
+ *
+ * GENERATED mode:
+ * Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
+ * When a 'flush' event is received, the ring buffer of transactions (hold by TransactionTracing)
+ * is processed by LayerTraceGenerator, a sequence of layers snapshots is generated
+ * and written to perfetto.
+ *
+ * DUMP mode:
+ * When the 'start' event is received a single layers snapshot is taken
+ * and written to perfetto.
+ *
+ *
+ * E.g. start active mode tracing:
+ *
+   adb shell -t perfetto \
+     -c - --txt \
+     -o /data/misc/perfetto-traces/trace \
+   <<EOF
+   unique_session_name: "surfaceflinger_layers_active"
+   buffers: {
+       size_kb: 63488
+       fill_policy: RING_BUFFER
+   }
+   data_sources: {
+       config {
+           name: "android.surfaceflinger.layers"
+           surfaceflinger_layers_config: {
+               mode: MODE_ACTIVE
+               trace_flags: TRACE_FLAG_INPUT
+               trace_flags: TRACE_FLAG_COMPOSITION
+               trace_flags: TRACE_FLAG_HWC
+               trace_flags: TRACE_FLAG_BUFFERS
+               trace_flags: TRACE_FLAG_VIRTUAL_DISPLAYS
+           }
+       }
+   }
+   EOF
+ *
  */
 class LayerTracing {
 public:
-    LayerTracing();
-    ~LayerTracing();
-    bool enable();
-    bool disable(std::string filename = FILE_NAME, bool writeToFile = true);
-    void appendToStream(std::ofstream& out);
-    bool isEnabled() const;
-    status_t writeToFile(std::string filename = FILE_NAME);
-    static LayersTraceFileProto createTraceFileProto();
-    void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId, LayersProto* layers,
-                std::string hwcDump, google::protobuf::RepeatedPtrField<DisplayProto>* displays);
+    using Mode = perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Mode;
 
-    enum : uint32_t {
+    enum Flag : uint32_t {
         TRACE_INPUT = 1 << 1,
         TRACE_COMPOSITION = 1 << 2,
         TRACE_EXTRA = 1 << 3,
@@ -60,20 +95,39 @@
         TRACE_VIRTUAL_DISPLAYS = 1 << 6,
         TRACE_ALL = TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA,
     };
-    void setTraceFlags(uint32_t flags);
-    bool flagIsSet(uint32_t flags) const;
-    uint32_t getFlags() const;
-    void setBufferSize(size_t bufferSizeInBytes);
-    void dump(std::string&) const;
+
+    LayerTracing();
+    ~LayerTracing();
+    void setTakeLayersSnapshotProtoFunction(
+            const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>&);
+    void setTransactionTracing(TransactionTracing&);
+    void setOutputStream(std::ostream&);
+
+    // Start event from perfetto data source
+    void onStart(Mode mode, uint32_t flags);
+    // Flush event from perfetto data source
+    void onFlush(Mode mode, uint32_t flags);
+    // Stop event from perfetto data source
+    void onStop(Mode mode);
+
+    void addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot, Mode mode);
+    bool isActiveTracingStarted() const;
+    uint32_t getActiveTracingFlags() const;
+    bool isActiveTracingFlagSet(Flag flag) const;
+    static perfetto::protos::LayersTraceFileProto createTraceFileProto();
 
 private:
-    static constexpr auto FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
-    uint32_t mFlags = TRACE_INPUT;
-    mutable std::mutex mTraceLock;
-    bool mEnabled GUARDED_BY(mTraceLock) = false;
-    std::unique_ptr<TransactionRingBuffer<LayersTraceFileProto, LayersTraceProto>> mBuffer
-            GUARDED_BY(mTraceLock);
-    size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = 20 * 1024 * 1024;
+    void writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const;
+    void writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot, Mode mode);
+    bool checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId);
+
+    std::function<perfetto::protos::LayersSnapshotProto(uint32_t)> mTakeLayersSnapshotProto;
+    TransactionTracing* mTransactionTracing;
+
+    std::atomic<bool> mIsActiveTracingStarted{false};
+    std::atomic<uint32_t> mActiveTracingFlags{0};
+    std::atomic<std::int64_t> mLastVsyncIdWrittenToPerfetto{-1};
+    std::optional<std::reference_wrapper<std::ostream>> mOutStream;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/tools/Android.bp b/services/surfaceflinger/Tracing/tools/Android.bp
index b6435a8..2ff09c3 100644
--- a/services/surfaceflinger/Tracing/tools/Android.bp
+++ b/services/surfaceflinger/Tracing/tools/Android.bp
@@ -31,7 +31,6 @@
     srcs: [
         ":libsurfaceflinger_sources",
         ":libsurfaceflinger_mock_sources",
-        ":layertracegenerator_sources",
         "main.cpp",
     ],
     static_libs: [
@@ -41,15 +40,3 @@
         "libsurfaceflinger_mocks_headers",
     ],
 }
-
-filegroup {
-    name: "layertracegenerator_sources",
-    srcs: [
-        "LayerTraceGenerator.cpp",
-    ],
-}
-
-cc_library_headers {
-    name: "layertracegenerator_headers",
-    export_include_dirs: ["."],
-}
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 9471e95..62c362e 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -41,7 +41,9 @@
 using namespace ftl::flag_operators;
 
 bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile,
-                                   const char*, bool onlyLastEntry) {
+                                   std::uint32_t traceFlags,
+                                   std::optional<std::reference_wrapper<std::ostream>> outStream,
+                                   bool onlyLastEntry) {
     if (traceFile.entry_size() == 0) {
         ALOGD("Trace file is empty");
         return false;
@@ -49,6 +51,11 @@
 
     TransactionProtoParser parser(std::make_unique<TransactionProtoParser::FlingerDataMapper>());
 
+    LayerTracing layerTracing;
+    if (outStream) {
+        layerTracing.setOutputStream(outStream->get());
+    }
+
     // frontend
     frontend::LayerLifecycleManager lifecycleManager;
     frontend::LayerHierarchyBuilder hierarchyBuilder{{}};
@@ -60,18 +67,10 @@
     property_get("ro.surface_flinger.supports_background_blur", value, "0");
     bool supportsBlur = atoi(value);
 
-    LayerTracing layerTracing;
-    layerTracing.setTraceFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
-    // 10MB buffer size (large enough to hold a single entry)
-    layerTracing.setBufferSize(10 * 1024 * 1024);
-    layerTracing.enable();
-    layerTracing.writeToFile(outputLayersTracePath);
-    std::ofstream out(outputLayersTracePath, std::ios::binary | std::ios::app);
-
     ALOGD("Generating %d transactions...", traceFile.entry_size());
     for (int i = 0; i < traceFile.entry_size(); i++) {
         // parse proto
-        proto::TransactionTraceEntry entry = traceFile.entry(i);
+        perfetto::protos::TransactionTraceEntry entry = traceFile.entry(i);
         ALOGV("    Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
               " layers +%d -%d handles -%d transactions=%d",
               i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
@@ -154,19 +153,26 @@
 
         lifecycleManager.commitChanges();
 
-        LayersProto layersProto = LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {},
-                                                                  layerTracing.getFlags())
-                                          .generate(hierarchyBuilder.getHierarchy());
+        auto layersProto =
+                LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {}, traceFlags)
+                        .generate(hierarchyBuilder.getHierarchy());
         auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos);
         if (!onlyLastEntry || (i == traceFile.entry_size() - 1)) {
-            layerTracing.notify(visibleRegionsDirty, entry.elapsed_realtime_nanos(),
-                                entry.vsync_id(), &layersProto, {}, &displayProtos);
-            layerTracing.appendToStream(out);
+            perfetto::protos::LayersSnapshotProto snapshotProto{};
+            snapshotProto.set_vsync_id(entry.vsync_id());
+            snapshotProto.set_elapsed_realtime_nanos(entry.elapsed_realtime_nanos());
+            snapshotProto.set_where(visibleRegionsDirty ? "visibleRegionsDirty" : "bufferLatched");
+            *snapshotProto.mutable_layers() = std::move(layersProto);
+            if ((traceFlags & LayerTracing::TRACE_COMPOSITION) == 0) {
+                snapshotProto.set_excludes_composition_state(true);
+            }
+            *snapshotProto.mutable_displays() = std::move(displayProtos);
+
+            layerTracing.addProtoSnapshotToOstream(std::move(snapshotProto),
+                                                   LayerTracing::Mode::MODE_GENERATED);
         }
     }
-    layerTracing.disable("", /*writeToFile=*/false);
-    out.close();
-    ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
+    ALOGD("End of generating trace file");
     return true;
 }
 
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
index a1e5fc8..2bb6f51 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
@@ -18,10 +18,19 @@
 
 #include <Tracing/TransactionTracing.h>
 
+#include <functional>
+#include <optional>
+#include <ostream>
+#include <string>
+
 namespace android {
+
+class LayerTracing;
+
 class LayerTraceGenerator {
 public:
-    bool generate(const perfetto::protos::TransactionTraceFile&, const char* outputLayersTracePath,
-                  bool onlyLastEntry);
+    bool generate(const perfetto::protos::TransactionTraceFile&, std::uint32_t traceFlags,
+                  std::optional<std::reference_wrapper<std::ostream>> outStream = std::nullopt,
+                  bool onlyLastEntry = false);
 };
 } // namespace android
diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp
index 0ff8f98..a8ac36a 100644
--- a/services/surfaceflinger/Tracing/tools/main.cpp
+++ b/services/surfaceflinger/Tracing/tools/main.cpp
@@ -21,6 +21,7 @@
 #include <iostream>
 #include <string>
 
+#include <Tracing/LayerTracing.h>
 #include "LayerTraceGenerator.h"
 
 using namespace android;
@@ -47,19 +48,22 @@
         return -1;
     }
 
-    const char* outputLayersTracePath =
-            (argc >= 3) ? argv[2] : "/data/misc/wmtrace/layers_trace.winscope";
+    const auto* outputLayersTracePath =
+            (argc == 3) ? argv[2] : "/data/misc/wmtrace/layers_trace.winscope";
+    auto outStream = std::ofstream{outputLayersTracePath, std::ios::binary | std::ios::app};
 
     const bool generateLastEntryOnly =
             argc >= 4 && std::string_view(argv[3]) == "--last-entry-only";
 
+    auto traceFlags = LayerTracing::Flag::TRACE_INPUT | LayerTracing::Flag::TRACE_BUFFERS;
+
     ALOGD("Generating %s...", outputLayersTracePath);
     std::cout << "Generating " << outputLayersTracePath << "\n";
 
-    if (!LayerTraceGenerator().generate(transactionTraceFile, outputLayersTracePath,
+    if (!LayerTraceGenerator().generate(transactionTraceFile, traceFlags, outStream,
                                         generateLastEntryOnly)) {
         std::cout << "Error: Failed to generate layers trace " << outputLayersTracePath;
         return -1;
     }
     return 0;
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/tracing/Android.bp b/services/surfaceflinger/tests/tracing/Android.bp
index 21ebaea..b6cd7b8 100644
--- a/services/surfaceflinger/tests/tracing/Android.bp
+++ b/services/surfaceflinger/tests/tracing/Android.bp
@@ -35,7 +35,6 @@
     srcs: [
         ":libsurfaceflinger_sources",
         ":libsurfaceflinger_mock_sources",
-        ":layertracegenerator_sources",
         "TransactionTraceTestSuite.cpp",
     ],
     static_libs: [
@@ -43,7 +42,6 @@
     ],
     header_libs: [
         "libsurfaceflinger_mocks_headers",
-        "layertracegenerator_headers",
     ],
     data: ["testdata/*"],
 }
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index 333768a..7a07634 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -23,8 +23,8 @@
 #include <unordered_map>
 
 #include <LayerProtoHelper.h>
-#include <LayerTraceGenerator.h>
 #include <Tracing/TransactionProtoParser.h>
+#include <Tracing/tools/LayerTraceGenerator.h>
 #include <layerproto/LayerProtoHeader.h>
 #include <log/log.h>
 
@@ -40,9 +40,9 @@
     static constexpr std::string_view sLayersTracePrefix = "layers_trace_";
     static constexpr std::string_view sTracePostfix = ".winscope";
 
-    proto::TransactionTraceFile mTransactionTrace;
-    LayersTraceFileProto mExpectedLayersTraceProto;
-    LayersTraceFileProto mActualLayersTraceProto;
+    perfetto::protos::TransactionTraceFile mTransactionTrace;
+    perfetto::protos::LayersTraceFileProto mExpectedLayersTraceProto;
+    perfetto::protos::LayersTraceFileProto mActualLayersTraceProto;
 
 protected:
     void SetUp() override {
@@ -56,18 +56,23 @@
         EXPECT_TRUE(std::filesystem::exists(std::filesystem::path(expectedLayersTracePath)));
         parseLayersTraceFromFile(expectedLayersTracePath.c_str(), mExpectedLayersTraceProto);
         TemporaryDir temp_dir;
+
         std::string actualLayersTracePath =
                 std::string(temp_dir.path) + "/" + expectedLayersFilename + "_actual";
+        {
+            auto traceFlags = LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS;
+            std::ofstream outStream{actualLayersTracePath, std::ios::binary | std::ios::app};
+            EXPECT_TRUE(LayerTraceGenerator().generate(mTransactionTrace, traceFlags, outStream,
+                                                       /*onlyLastEntry=*/true))
+                    << "Failed to generate layers trace from " << transactionTracePath;
+        }
 
-        EXPECT_TRUE(LayerTraceGenerator().generate(mTransactionTrace, actualLayersTracePath.c_str(),
-                                                   /*onlyLastEntry=*/true))
-                << "Failed to generate layers trace from " << transactionTracePath;
         EXPECT_TRUE(std::filesystem::exists(std::filesystem::path(actualLayersTracePath)));
         parseLayersTraceFromFile(actualLayersTracePath.c_str(), mActualLayersTraceProto);
     }
 
     void parseTransactionTraceFromFile(const char* transactionTracePath,
-                                       proto::TransactionTraceFile& outProto) {
+                                       perfetto::protos::TransactionTraceFile& outProto) {
         ALOGD("Parsing file %s...", transactionTracePath);
         std::fstream input(transactionTracePath, std::ios::in | std::ios::binary);
         EXPECT_TRUE(input) << "Error could not open " << transactionTracePath;
@@ -75,7 +80,8 @@
                 << "Failed to parse " << transactionTracePath;
     }
 
-    void parseLayersTraceFromFile(const char* layersTracePath, LayersTraceFileProto& outProto) {
+    void parseLayersTraceFromFile(const char* layersTracePath,
+                                  perfetto::protos::LayersTraceFileProto& outProto) {
         ALOGD("Parsing file %s...", layersTracePath);
         std::fstream input(layersTracePath, std::ios::in | std::ios::binary);
         EXPECT_TRUE(input) << "Error could not open " << layersTracePath;
@@ -124,7 +130,7 @@
     bool operator()(LayerInfo const& m) const { return m.id == id; }
 };
 
-static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& proto) {
+static LayerInfo getLayerInfoFromProto(perfetto::protos::LayerProto& proto) {
     Rect touchableRegionBounds = Rect::INVALID_RECT;
     // ignore touchable region for layers without buffers, the new fe aggressively avoids
     // calculating state for layers that are not visible which could lead to mismatches
@@ -148,8 +154,7 @@
             touchableRegionBounds};
 }
 
-static std::vector<LayerInfo> getLayerInfosFromProto(
-        perfetto::protos::pbzero::LayersSnapshotProto& entry) {
+static std::vector<LayerInfo> getLayerInfosFromProto(perfetto::protos::LayersSnapshotProto& entry) {
     std::unordered_map<uint64_t /* snapshotId*/, uint64_t /*layerId*/> snapshotIdToLayerId;
     std::vector<LayerInfo> layers;
     layers.reserve(static_cast<size_t>(entry.layers().layers_size()));