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

Commit 0adffcb2 authored by Peter Kalauskas's avatar Peter Kalauskas
Browse files

Move coroutine tracing feature to sysprop

Test: atest tracinglib-robo-test
Test: setprop persist.debug.coroutine_tracing 1
Flag: com.android.systemui.coroutine_tracing
Bug: 289353932
Change-Id: I85a6cc8b11328edc9cd509d680cf1592559919fa
parent 345dac54
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -93,7 +93,8 @@ Coroutine tracing is flagged off by default. To enable coroutine tracing on a de
and restart the user-space system:

```
adb shell device_config override systemui com.android.systemui.coroutine_tracing true
adb shell aflags enable com.android.systemui.coroutine_tracing
adb shell setprop persist.debug.coroutine_tracing 1
adb shell am restart
```

@@ -101,8 +102,8 @@ adb shell am restart

The behavior of coroutine tracing can be further fine-tuned using the following sysprops:

 - `debug.coroutine_tracing.walk_stack_override`
 - `debug.coroutine_tracing.count_continuations_override`
 - `persist.debug.coroutine_tracing.walk_stack_override`
 - `persist.debug.coroutine_tracing.count_continuations_override`

See [`createCoroutineTracingContext()`](core/src/coroutines/TraceContextElement.kt) for
documentation.
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ java_library {
    static_libs: [
        "kotlinx_coroutines_android",
        "com_android_systemui_flags_lib",
        "compilelib",
    ],
    kotlincflags: [
        "-Xjvm-default=all",
+29 −9
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@

package com.android.app.tracing.coroutines

import com.android.app.tracing.coroutines.DebugSysProps.coroutineTracingEnabled
import com.android.app.tracing.traceSection
import com.android.systemui.util.Compile
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@@ -222,12 +224,20 @@ public inline fun <T, R> R.traceCoroutine(crossinline spanName: () -> String, bl
    // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the
    // coroutine resumes when tracing is active, we won't know its name.
    try {
        if (com.android.systemui.Flags.coroutineTracing()) {
        if (
            Compile.IS_DEBUG &&
                com.android.systemui.Flags.coroutineTracing() &&
                coroutineTracingEnabled
        ) {
            traceThreadLocal.get()?.beginCoroutineTrace(spanName())
        }
        return block()
    } finally {
        if (com.android.systemui.Flags.coroutineTracing()) {
        if (
            Compile.IS_DEBUG &&
                com.android.systemui.Flags.coroutineTracing() &&
                coroutineTracingEnabled
        ) {
            traceThreadLocal.get()?.endCoroutineTrace()
        }
    }
@@ -242,12 +252,20 @@ public inline fun <T> traceCoroutine(crossinline spanName: () -> String, block:
    // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the
    // coroutine resumes when tracing is active, we won't know its name.
    try {
        if (com.android.systemui.Flags.coroutineTracing()) {
        if (
            Compile.IS_DEBUG &&
                com.android.systemui.Flags.coroutineTracing() &&
                coroutineTracingEnabled
        ) {
            traceThreadLocal.get()?.beginCoroutineTrace(spanName())
        }
        return block()
    } finally {
        if (com.android.systemui.Flags.coroutineTracing()) {
        if (
            Compile.IS_DEBUG &&
                com.android.systemui.Flags.coroutineTracing() &&
                coroutineTracingEnabled
        ) {
            traceThreadLocal.get()?.endCoroutineTrace()
        }
    }
@@ -266,10 +284,10 @@ public inline fun <T> traceCoroutine(spanName: String, block: () -> T): T {
}

/**
 * Returns the passed context if [com.android.systemui.Flags.coroutineTracing] is false. Otherwise,
 * returns a new context by adding [CoroutineTraceName] to the given context. The
 * [CoroutineTraceName] in the passed context will take precedence over the new
 * [CoroutineTraceName].
 * Returns the given `CoroutineContext` if coroutine tracing is disabled. Otherwise, returns a new
 * context by adding [CoroutineTraceName] to the given context. If the given [CoroutineTraceName]
 * already has a [CoroutineTraceName], it will be used instead of the one that would have been
 * created here, and it will preserve its original name.
 */
@PublishedApi
internal inline fun addName(
@@ -277,7 +295,9 @@ internal inline fun addName(
    context: CoroutineContext,
): CoroutineContext {
    contract { callsInPlace(spanName, InvocationKind.AT_MOST_ONCE) }
    return if (com.android.systemui.Flags.coroutineTracing()) {
    return if (
        Compile.IS_DEBUG && com.android.systemui.Flags.coroutineTracing() && coroutineTracingEnabled
    ) {
        CoroutineTraceName(spanName()) + context
    } else {
        context
+28 −9
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.os.PerfettoTrace
import android.os.SystemProperties
import android.os.Trace
import android.util.Log
import com.android.app.tracing.coroutines.DebugSysProps.coroutineTracingEnabled
import com.android.systemui.util.Compile
import java.lang.StackWalker.StackFrame
import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.atomic.AtomicInteger
@@ -51,14 +53,28 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
 */
@PublishedApi internal val traceThreadLocal: TraceDataThreadLocal = TraceDataThreadLocal()

@PublishedApi
internal object DebugSysProps {
    @JvmField
    val alwaysEnableStackWalker =
        SystemProperties.getBoolean("debug.coroutine_tracing.walk_stack_override", false)
    val coroutineTracingEnabled =
        Compile.IS_DEBUG &&
            com.android.systemui.Flags.coroutineTracing() &&
            SystemProperties.getBoolean("persist.debug.coroutine_tracing", false)

    @JvmField
    val stackWalkerAlwaysEnabled =
        Compile.IS_DEBUG &&
            com.android.systemui.Flags.coroutineTracing() &&
            SystemProperties.getBoolean("persist.debug.coroutine_tracing.walk_stack", true)

    @JvmField
    val alwaysEnableContinuationCounting =
        SystemProperties.getBoolean("debug.coroutine_tracing.count_continuations_override", false)
    val continuationCountingAlwaysEnabled =
        Compile.IS_DEBUG &&
            com.android.systemui.Flags.coroutineTracing() &&
            SystemProperties.getBoolean(
                "persist.debug.coroutine_tracing.count_continuations",
                false,
            )
}

/**
@@ -84,8 +100,8 @@ internal object DebugSysProps {
 * }
 * ```
 *
 * **NOTE:** The sysprops `debug.coroutine_tracing.walk_stack_override` and
 * `debug.coroutine_tracing.count_continuations_override` can be used to override the parameters
 * **NOTE:** The sysprops `persist.debug.coroutine_tracing.walk_stack` and
 * `persist.debug.coroutine_tracing.count_continuations` can be used to override the parameters
 * `walkStackForDefaultNames` and `countContinuations` respectively, forcing them to always be
 * `true`. If the sysprop is `false` (or does not exist), the value of the parameter is passed here
 * is used. If `true`, all calls to [createCoroutineTracingContext] will be overwritten with that
@@ -120,14 +136,17 @@ public fun createCoroutineTracingContext(
    walkStackForDefaultNames: Boolean = false,
    shouldIgnoreClassName: ((String) -> Boolean)? = null,
): CoroutineContext {
    return if (com.android.systemui.Flags.coroutineTracing()) {
    return if (
        Compile.IS_DEBUG && com.android.systemui.Flags.coroutineTracing() && coroutineTracingEnabled
    ) {
        TraceContextElement(
            name = name,
            isRoot = true,
            countContinuations =
                !testMode && (countContinuations || DebugSysProps.alwaysEnableContinuationCounting),
                !testMode &&
                    (countContinuations || DebugSysProps.continuationCountingAlwaysEnabled),
            walkStackForDefaultNames =
                walkStackForDefaultNames || DebugSysProps.alwaysEnableStackWalker,
                walkStackForDefaultNames || DebugSysProps.stackWalkerAlwaysEnabled,
            shouldIgnoreClassName = shouldIgnoreClassName,
            parentId = null,
            inheritedTracePrefix = if (testMode) "" else null,
+7 −1
Original line number Diff line number Diff line
@@ -20,7 +20,9 @@ package com.android.app.tracing.coroutines

import android.os.Trace
import com.android.app.tracing.beginSlice
import com.android.app.tracing.coroutines.DebugSysProps.coroutineTracingEnabled
import com.android.app.tracing.endSlice
import com.android.systemui.util.Compile
import java.util.ArrayDeque
import kotlin.contracts.ExperimentalContracts
import kotlin.math.max
@@ -38,7 +40,11 @@ private typealias TraceSection = String
@PublishedApi
internal class TraceDataThreadLocal : ThreadLocal<TraceStorage?>() {
    override fun initialValue(): TraceStorage? {
        return if (com.android.systemui.Flags.coroutineTracing()) {
        return if (
            Compile.IS_DEBUG &&
                com.android.systemui.Flags.coroutineTracing() &&
                coroutineTracingEnabled
        ) {
            TraceStorage(null)
        } else {
            null
Loading