Add traceAsync to TraceUtils

This utility is useful to trace coroutine code, as the beginning and the
end of the event might end up in different threads.

Note that stacks are maintained as long as the same trackName is used.

When no stackName is used, "AsyncTraces" default is used.

Test: New track appearing in a perfetto trace
Bug: 289353932
Change-Id: I0fbf745d058e6a329d6b2229178a52af21e84033
This commit is contained in:
Nicolo' Mazzucato
2023-07-04 12:46:00 +00:00
parent 1748418e24
commit 0a72a6db31
2 changed files with 49 additions and 12 deletions

View File

@@ -18,22 +18,23 @@ package com.android.systemui.util
import android.os.Trace
import android.os.TraceNameSupplier
import java.util.concurrent.atomic.AtomicInteger
/**
* Run a block within a [Trace] section.
* Calls [Trace.beginSection] before and [Trace.endSection] after the passed block.
* Run a block within a [Trace] section. Calls [Trace.beginSection] before and [Trace.endSection]
* after the passed block.
*/
inline fun <T> traceSection(tag: String, block: () -> T): T =
if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
Trace.traceBegin(Trace.TRACE_TAG_APP, tag)
try {
block()
} finally {
Trace.traceEnd(Trace.TRACE_TAG_APP)
}
} else {
if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
Trace.traceBegin(Trace.TRACE_TAG_APP, tag)
try {
block()
} finally {
Trace.traceEnd(Trace.TRACE_TAG_APP)
}
} else {
block()
}
class TraceUtils {
companion object {
@@ -43,6 +44,7 @@ class TraceUtils {
/**
* Helper function for creating a Runnable object that implements TraceNameSupplier.
*
* This is useful for posting Runnables to Handlers with meaningful names.
*/
inline fun namedRunnable(tag: String, crossinline block: () -> Unit): Runnable {
@@ -51,5 +53,37 @@ class TraceUtils {
override fun run() = block()
}
}
/**
* Cookie used for async traces. Shouldn't be public, but to use it inside inline methods
* there is no other way around.
*/
val lastCookie = AtomicInteger(0)
/**
* Creates an async slice in a track called "AsyncTraces".
*
* This can be used to trace coroutine code. Note that all usages of this method will appear
* under a single track.
*/
inline fun <T> traceAsync(method: String, block: () -> T): T =
traceAsync(method, "AsyncTraces", block)
/**
* Creates an async slice in a track with [trackName] while [block] runs.
*
* This can be used to trace coroutine code. [method] will be the name of the slice,
* [trackName] of the track. The track is one of the rows visible in a perfetto trace inside
* SystemUI process.
*/
inline fun <T> traceAsync(method: String, trackName: String, block: () -> T): T {
val cookie = lastCookie.incrementAndGet()
Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, trackName, method, cookie)
try {
return block()
} finally {
Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, trackName, cookie)
}
}
}
}

View File

@@ -49,6 +49,7 @@ import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.TraceUtils.Companion.traceAsync
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -442,8 +443,10 @@ constructor(
}
private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
withContext(backgroundDispatcher) {
devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
traceAsync("isFeatureDisabledByDevicePolicy", TAG) {
withContext(backgroundDispatcher) {
devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
}
}
companion object {