blob: 2f0c372cfb7159ed48c159ee1a75f9097d622a5d [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.benchmark.macro.perfetto
import android.os.Build
import android.os.Trace
/**
* Wrapper that uses standard app tracing above API 24, and forces trace sections via reflection
* on 23 and below.
*
* Prior to API 24, all apps with tracing enabled had to be listed in a single setprop, fully
* enumerated by package name. As a setprop can only be 91 chars long, it's easy to hit cases where
* a macrobenchmark and its target can't fit into this single setprop. For this reason, prior to 24,
* the macrobenchmark process doesn't rely on the app tracing tag, and instead forces trace sections
* via reflection, and the TRACE_TAG_ALWAYS tag.
*/
internal object ForceTracing {
private val traceBeginMethod = if (Build.VERSION.SDK_INT < 24) {
android.os.Trace::class.java.getMethod(
"traceBegin",
Long::class.javaPrimitiveType,
String::class.javaPrimitiveType
)
} else null
private val traceEndMethod = if (Build.VERSION.SDK_INT < 24) {
android.os.Trace::class.java.getMethod(
"traceEnd",
Long::class.javaPrimitiveType,
String::class.javaPrimitiveType
)
} else null
private const val TRACE_TAG_ALWAYS = 1L shl 0 // copied from android.os.Trace
fun begin(label: String) {
if (Build.VERSION.SDK_INT < 24) {
traceBeginMethod!!.invoke(null, TRACE_TAG_ALWAYS, label)
} else {
Trace.beginSection(label)
}
}
fun end() {
if (Build.VERSION.SDK_INT < 24) {
traceEndMethod!!.invoke(null, TRACE_TAG_ALWAYS)
} else {
Trace.endSection()
}
}
}
internal inline fun <T> forceTrace(label: String, block: () -> T): T {
ForceTracing.begin(label)
return try {
block()
} finally {
ForceTracing.end()
}
}