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

Commit 8b5c6bd0 authored by Kean Mariotti's avatar Kean Mariotti
Browse files

Add layer tracing's MODE_GENERATED_BUGREPORT_ONLY

The generated layers trace can be quite large (100-400 MB), which is way above
the perfetto's field upload budget.

On the field (AOT) we want the layers trace to be generated only when a bugreport
is taken and not when a perfetto's field upload happens. We achieve it as follows:
- In the AOT configuration, enable the 'android.surfaceflinger_layers' data source
  with MODE_GENERATED_BUGREPORT_ONLY.
- When LayerTracing receives perfetto's OnFlush event and MODE_GENERATED_BUGREPORT_ONLY is enabled,
  generate the layers trace only if the OnFlush event is due to a bugreport being taken:
    args.flush_flags.reason() == perfetto::FlushFlags::Reason::kTraceClone &&
    args.flush_flags.clone_target() == perfetto::FlushFlags::CloneTarget::kBugreport

In a test environment instead, we can use MODE_GENERATED to test the layers trace generation
without having to take a bugreport.

Bug: b/293429094
Test: 1. Manually start the perfetto's android.surfaceflinger_layers data source
         with MODE_GENERATED_BUGREPORT_ONLY setting a high bugreport_score (e.g. 50000)
      2. Take a bugreport (adb bugreport)
      3. Verify that FS/data/misc/perfetto-traces/bugreport/systrace.pftrace (in the bugreport)
         contains the generated layers trace. E.g. inspect bugreport with go/winscope.
Change-Id: I5b3ce59cc762fd5a22170e677e48be987380c94e
parent 3feea1b9
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -51,8 +51,9 @@ void LayerDataSource::OnSetup(const LayerDataSource::SetupArgs& args) {
    if (config.has_mode() && config.mode() != LayerTracing::Mode::MODE_UNSPECIFIED) {
        mMode = static_cast<LayerTracing::Mode>(config.mode());
    } else {
        mMode = LayerTracing::Mode::MODE_GENERATED;
        ALOGD("Received config with unspecified 'mode'. Using 'GENERATED' as default");
        mMode = LayerTracing::Mode::MODE_GENERATED_BUGREPORT_ONLY;
        ALOGD("Received config with unspecified 'mode'."
              " Using 'MODE_GENERATED_BUGREPORT_ONLY' as default");
    }

    mFlags = 0;
@@ -68,10 +69,16 @@ void LayerDataSource::OnStart(const LayerDataSource::StartArgs&) {
    }
}

void LayerDataSource::OnFlush(const LayerDataSource::FlushArgs&) {
    ALOGD("Received OnFlush event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
void LayerDataSource::OnFlush(const LayerDataSource::FlushArgs& args) {
    ALOGD("Received OnFlush event"
          " (mode = 0x%02x, flags = 0x%02x, reason = 0x%" PRIx64 ", clone_target = 0x%0" PRIx64 ")",
          mMode, mFlags, args.flush_flags.reason(), args.flush_flags.clone_target());

    bool isBugreport = args.flush_flags.reason() == perfetto::FlushFlags::Reason::kTraceClone &&
            args.flush_flags.clone_target() == perfetto::FlushFlags::CloneTarget::kBugreport;

    if (auto* p = mLayerTracing.load()) {
        p->onFlush(mMode, mFlags);
        p->onFlush(mMode, mFlags, isBugreport);
    }
}

+42 −7
Original line number Diff line number Diff line
@@ -67,9 +67,27 @@ void LayerTracing::onStart(Mode mode, uint32_t flags) {
            break;
        }
        case Mode::MODE_GENERATED: {
            // This tracing mode processes the buffer of transactions (owned by TransactionTracing),
            // generates layers snapshots and writes them to perfetto. This happens every time an
            // OnFlush event is received.
            ALOGD("Started generated tracing (waiting for OnFlush event to generated layers)");
            break;
        }
        case Mode::MODE_GENERATED_BUGREPORT_ONLY: {
            // Same as MODE_GENERATED, but only when the received OnFlush event is due to a
            // bugreport being taken. This mode exists because the generated layers trace is very
            // large (hundreds of MB), hence we want to include it only in bugreports and not in
            // field uploads.
            //
            // Note that perfetto communicates only whether the OnFlush event is due to a bugreport
            // or not, hence we need an additional "bugreport only" tracing mode.
            // If perfetto had communicated when the OnFlush is due to a field upload, then we could
            // have had a single "generated" tracing mode that would have been a noop in case of
            // field uploads.
            ALOGD("Started 'generated bugreport only' tracing"
                  " (waiting for bugreport's OnFlush event to generate layers)");
            break;
        }
        case Mode::MODE_DUMP: {
            auto snapshot = mTakeLayersSnapshotProto(flags);
            addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
@@ -82,10 +100,18 @@ void LayerTracing::onStart(Mode mode, uint32_t flags) {
    }
}

void LayerTracing::onFlush(Mode mode, uint32_t flags) {
void LayerTracing::onFlush(Mode mode, uint32_t flags, bool isBugreport) {
    // 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) {
    // generate layers snapshots and write them to perfetto.
    if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
        ALOGD("Skipping layers trace generation (not a 'generated' tracing session)");
        return;
    }

    // In "generated bugreport only" mode skip the layers snapshot generation
    // if the perfetto's OnFlush event is not due to a bugreport being taken.
    if (mode == Mode::MODE_GENERATED_BUGREPORT_ONLY && !isBugreport) {
        ALOGD("Skipping layers trace generation (not a bugreport OnFlush event)");
        return;
    }

@@ -147,14 +173,23 @@ void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&&
}

void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
                                           Mode mode) {
                                           Mode srcMode) {
    const auto snapshotBytes = snapshot.SerializeAsString();

    LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
        if (mode != context.GetCustomTlsState()->mMode) {
        auto dstMode = context.GetCustomTlsState()->mMode;
        if (srcMode == Mode::MODE_GENERATED) {
            // Layers snapshots produced by LayerTraceGenerator have srcMode == MODE_GENERATED
            // and should be written to tracing sessions with MODE_GENERATED
            // or MODE_GENERATED_BUGREPORT_ONLY.
            if (dstMode != Mode::MODE_GENERATED && dstMode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
                return;
            }
        } else if (srcMode != dstMode) {
            return;
        }
        if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(mode, snapshot.vsync_id())) {

        if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(srcMode, snapshot.vsync_id())) {
            return;
        }
        {
@@ -176,7 +211,7 @@ bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::in
    // 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) {
    if (mode != Mode::MODE_GENERATED && mode != Mode::MODE_GENERATED_BUGREPORT_ONLY) {
        return true;
    }

+5 −3
Original line number Diff line number Diff line
@@ -55,7 +55,9 @@ class TransactionTracing;
 * and written to perfetto.
 *
 *
 * E.g. start active mode tracing:
 * E.g. start active mode tracing
 * (replace mode value with MODE_DUMP, MODE_GENERATED or MODE_GENERATED_BUGREPORT_ONLY to enable
 * different tracing modes):
 *
   adb shell -t perfetto \
     -c - --txt \
@@ -106,7 +108,7 @@ public:
    // 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);
    void onFlush(Mode mode, uint32_t flags, bool isBugreport);
    // Stop event from perfetto data source
    void onStop(Mode mode);