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

Commit 46bf7490 authored by Peter Kalauskas's avatar Peter Kalauskas Committed by Android (Google) Code Review
Browse files

Merge "Move coroutine tracing feature to sysprop" into main

parents 20bc27df 0adffcb2
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