This page shows how to record a system trace using the ProfilingManager
API.
Add dependencies
For the best experience with the ProfilingManager
API, add the following
Jetpack libraries to your build.gradle.kts
file.
Kotlin
dependencies { implementation("androidx.tracing:tracing:1.3.0") implementation("androidx.core:core:1.16.0") }
Groovy
dependencies { implementation 'androidx.tracing:tracing:1.3.0' implementation 'androidx.core:core:1.16.0' }
Record a system trace
After adding the required dependencies, use the following code to record a
system trace. This example shows a basic setup within an Activity
to start and
manage a profiling session.
Kotlin
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) fun sampleRecordSystemTrace() { val mainExecutor: Executor = Dispatchers.IO.asExecutor() // Your choice of executor for the callback to occur on. val resultCallback = Consumer<ProfilingResult> { profilingResult -> if (profilingResult.errorCode == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.resultFilePath ) } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.errorCode + " errormsg=" + profilingResult.errorMessage ) } } val stopSignal = CancellationSignal() val requestBuilder = SystemTraceRequestBuilder() requestBuilder.setCancellationSignal(stopSignal) requestBuilder.setTag("FOO") // Caller supplied tag for identification requestBuilder.setDurationMs(60000) requestBuilder.setBufferFillPolicy(BufferFillPolicy.RING_BUFFER) requestBuilder.setBufferSizeKb(20971520) requestProfiling(applicationContext, requestBuilder.build(), mainExecutor, resultCallback) // Wait some time for profiling to start. Trace.beginSection("MyApp:HeavyOperation") heavyOperation() Trace.endSection() // Once the interesting code section is profiled, stop profile stopSignal.cancel() } fun heavyOperation() { // Computations you want to profile }
Java
void heavyOperation() { // Computations you want to profile } void sampleRecordSystemTrace() { Executor mainExecutor = Executors.newSingleThreadExecutor(); Consumer<ProfilingResult> resultCallback = new Consumer<ProfilingResult>() { @Override public void accept(ProfilingResult profilingResult) { if (profilingResult.getErrorCode() == ProfilingResult.ERROR_NONE) { Log.d( "ProfileTest", "Received profiling result file=" + profilingResult.getResultFilePath()); } else { Log.e( "ProfileTest", "Profiling failed errorcode=" + profilingResult.getErrorCode() + " errormsg=" + profilingResult.getErrorMessage()); } } }; CancellationSignal stopSignal = new CancellationSignal(); SystemTraceRequestBuilder requestBuilder = new SystemTraceRequestBuilder(); requestBuilder.setCancellationSignal(stopSignal); requestBuilder.setTag("FOO"); requestBuilder.setDurationMs(60000); requestBuilder.setBufferFillPolicy(BufferFillPolicy.RING_BUFFER); requestBuilder.setBufferSizeKb(20971520); Profiling.requestProfiling(getApplicationContext(), requestBuilder.build(), mainExecutor, resultCallback); // Wait some time for profiling to start. Trace.beginSection("MyApp:HeavyOperation"); heavyOperation(); Trace.endSection(); // Once the interesting code section is profiled, stop profile stopSignal.cancel(); }
The sample code sets up and manages the profiling session by going through the following steps:
Set up the executor. Create an
Executor
to define the thread that will receive the profiling results. Profiling happens in the background. Using a non-UI thread executor helps prevent Application Not Responding (ANR) errors if you add more processing to the callback later.Handle profiling results. Create a
Consumer<ProfilingResult>
object. The system uses this object to send profiling results fromProfilingManager
back to your app.Build the profiling request. Create a
SystemTraceRequestBuilder
to set up your profiling session. This builder lets you customizeProfilingManager
trace settings. Customizing the builder is optional; if you don't, the system uses default settings.- Define a tag. Use
setTag()
to add a tag to the trace name. This tag helps you identify the trace. - Optional: Set the duration. Use
setDurationMs()
to specify how long to profile in milliseconds. For example,60000
sets a 60-second trace. The trace automatically ends after the specified duration ifCancellationSignal
isn't triggered before that. - Choose a buffer policy. Use
setBufferFillPolicy()
to define how trace data is stored.BufferFillPolicy.RING_BUFFER
means that when the buffer is full, new data overwrites the oldest data, keeping a continuous record of recent activity. - Set a buffer size. Use
setBufferSizeKb()
to specify a buffer size for tracing which you can use to control the size of the output trace file.
- Define a tag. Use
Optional: Manage the session lifecycle. Create a
CancellationSignal
. This object lets you stop the profiling session whenever you want, giving you precise control over its length.Start and receive results. When you call
requestProfiling()
,ProfilingManager
starts a profiling session in the background. Once profiling is done, it sends theProfilingResult
to yourresultCallback#accept
method. If profiling finishes successfully, theProfilingResult
provides the path where the trace was saved on your device throughProfilingResult#getResultFilePath
. You can get this file programmatically or, for local profiling, by runningadb pull <trace_path>
from your computer.Add custom trace points. You can add custom trace points in your app's code. In the previous code example, a trace slice named
MyApp:HeavyOperation
is added usingTrace.beginSection()
andTrace.endSection()
. This custom slice appears in the generated profile, highlighting specific operations within your app.