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

Commit 55014087 authored by Ryan Savitski's avatar Ryan Savitski
Browse files

PerfettoTrigger: use SDK directly if available

PerfettoTrigger is a utility class that currently fork-execs a system
binary to send a named trigger to the system tracing daemon. It's used
from a variety of processes through classes like InteractionJankMonitor
and LatencyTracker. Calling processes include system_server, systemui,
launcher, settings, etc.

Nowadays, system_server and systemui register with a perfetto SDK
library (through os.PerfettoTrace), which enables sending the triggers
without fork-exec.

This patch adds a way to dynamically figure out whether the calling
process is "using" the SDK, and if so redirecting PerfettoTrigger to the
latter's method.

Note that robustly figuring out that the SDK is usable would require a
lot of plumbing since the registration with the tracing daemon is
asynchronous (though there is an expectation that it will succeed
eventually for platform processes). So we instead do a simpler check
that the calling process initiated the registration. This should be
sufficient for practical uses of PerfettoTrigger.

Beyond lower overhead when triggering, this also fixes a long-standing
limitation where PerfettoTrigger calls from within system_server would
actually fail on selinux denials on fork-execing the trigger binary.

I've kept the rate-limiting done by PerfettoTrigger even if using the
SDK to preserve current triggering rates. We'd need to evaluate
unlimiting the triggers separately.

Flag: android.os.perfetto_sdk_tracing_v2
Test: manually with the local device_config overrides documented in
      InteractionJankMonitor's javadoc. Confirmed that systemui was
      using the SDK while nexuslauncher was fork-execing.
Fixes: 186213514
Change-Id: Ia911dccf619922b430de5026cac14cc34bf6f96d
parent 0e62272f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import dalvik.annotation.optimization.FastNative;

import libcore.util.NativeAllocationRegistry;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**
@@ -51,6 +52,8 @@ public final class PerfettoTrace {
    public static final boolean IS_USE_SDK_TRACING_API_V3 =
            IS_FLAG_ENABLED && android.os.Flags.perfettoSdkTracingV3();

    private static final AtomicBoolean sAttemptedSystemRegistration = new AtomicBoolean(false);

    /**
     * For fetching the next flow event id in a process.
     */
@@ -380,6 +383,9 @@ public final class PerfettoTrace {
    /** Registers the process with Perfetto. */
    @android.ravenwood.annotation.RavenwoodReplace
    public static void register(boolean isBackendInProcess) {
        if (!isBackendInProcess) {
            sAttemptedSystemRegistration.set(true);
        }
        if (IS_USE_SDK_TRACING_API_V3) {
            com.android.internal.dev.perfetto.sdk.PerfettoTrace.register(isBackendInProcess);
        } else {
@@ -406,4 +412,13 @@ public final class PerfettoTrace {
    public static void registerCategories$ravenwood() {
        // Tracing currently completely disabled under Ravenwood
    }

    /**
     * Returns whether the calling process attempted to register with the system backend of perfetto
     * by calling {@code register(false)}. A true return does not mean that the registration is
     * already completed, as that is an asynchronous operation.
     */
    public static boolean getAttempedSystemRegistration() {
        return sAttemptedSystemRegistration.get();
    }
}
+14 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.util;

import android.os.PerfettoTrace;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseLongArray;
@@ -23,7 +24,13 @@ import android.util.SparseLongArray;
import java.io.IOException;

/**
 * A trigger implementation with perfetto backend.
 * Sends a named trigger to the central perfetto tracing service, which may activate or stop
 * preconfigured tracing.
 *
 * <p>The historical codepath is to fork-exec a system binary that performs the task. However, for
 * processes that are now registering with perfetto through the {@code PerfettoTrace} SDK, they can
 * use the SDK for sending the trigger.
 *
 * @hide
 */
public class PerfettoTrigger {
@@ -53,6 +60,12 @@ public class PerfettoTrigger {
            sLastInvocationPerTrigger.put(triggerName.hashCode(), SystemClock.elapsedRealtime());
        }

        // If we are registering with the SDK, use it directly.
        if (PerfettoTrace.getAttempedSystemRegistration()) {
            PerfettoTrace.activateTrigger(triggerName, 0);
            return;
        }

        try {
            ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, triggerName);
            Log.v(TAG, "Triggering " + String.join(" ", pb.command()));