Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 639b54fb authored by Kean Mariotti's avatar Kean Mariotti
Browse files

Revert^2 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: Ic1b10a040ec4533f0b56a4c8087c5a2898e3e34d
parent 7941ecfe
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -198,9 +198,11 @@ filegroup {
        "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",
    ],
+66 −85
Original line number Diff line number Diff line
@@ -320,8 +320,6 @@ const String16 sWakeupSurfaceFlinger("android.permission.WAKEUP_SURFACE_FLINGER"

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 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI

    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 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
    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();

@@ -2378,11 +2388,6 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
        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)
@@ -2509,11 +2514,9 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
    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);
@@ -2735,10 +2738,8 @@ CompositeResultsPerDisplay SurfaceFlinger::composite(

    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());

@@ -6366,11 +6367,6 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp

    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");
@@ -6722,42 +6718,13 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
            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: {
@@ -6785,19 +6752,9 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
            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: {
@@ -6837,13 +6794,9 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                }
                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: {
                n = data.readInt32();
@@ -7002,9 +6955,6 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                if (mTransactionTracing) {
                    mTransactionTracing->writeToFile();
                }
                if (mLayerTracingEnabled) {
                    mLayerTracing.writeToFile();
                }
                reply->writeInt32(NO_ERROR);
                return NO_ERROR;
            }
@@ -8791,19 +8741,50 @@ frontend::Update SurfaceFlinger::flushLifecycleUpdates() {
    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);
    }
    *snapshot.mutable_layers() = std::move(layers);

    if (traceFlags & LayerTracing::Flag::TRACE_HWC) {
        std::string hwcDump;
    if (tracingFlags & LayerTracing::TRACE_HWC) {
        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;
}

// sfdo functions
+4 −5
Original line number Diff line number Diff line
@@ -368,7 +368,6 @@ private:
    friend class RefreshRateOverlay;
    friend class RegionSamplingThread;
    friend class LayerRenderArea;
    friend class LayerTracing;
    friend class SurfaceComposerAIDL;
    friend class DisplayRenderArea;

@@ -1096,7 +1095,10 @@ private:
    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
@@ -1261,10 +1263,7 @@ private:
    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;
+93 −0
Original line number Diff line number Diff line
/*
 * 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);
+77 −0
Original line number Diff line number Diff line
/*
 * 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);
Loading