This section shows how to debug an [Application Not Responding (ANR)](https://developer.android.com/topic/performance/anrs/keep-your-app-responsive) using
`ProfilingManager` with an example trace.

## Set up app to collect ANRs

Start by setting up an ANR trigger in your app:


```java
public void addANRTrigger() {
  ProfilingManager profilingManager = getApplicationContext().getSystemService(
      ProfilingManager.class);
  List<ProfilingTrigger> triggers = new ArrayList<>();
  ProfilingTrigger.Builder triggerBuilder = new ProfilingTrigger.Builder(
      ProfilingTrigger.TRIGGER_TYPE_ANR);
  triggers.add(triggerBuilder.build());
  Executor mainExecutor = Executors.newSingleThreadExecutor();
  Consumer<ProfilingResult> resultCallback =
      profilingResult -> {
        // Handle uploading trace to your back-end
      };
  profilingManager.registerForAllProfilingResults(mainExecutor, resultCallback);
  profilingManager.addProfilingTriggers(triggers);
}
```

<br />

After capturing and uploading an ANR trace, open it in the [Perfetto UI](https://ui.perfetto.dev/).

## Analyze the trace

Because the ANR triggered the trace, you know the trace ended when the system
detected unresponsiveness in your app's main thread. Figure 1 shows how to
navigate to your app's main thread which is tagged accordingly within the UI.
![Perfetto UI navigation to app main thread.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-main-thread.png) **Figure 1.** Navigation to app's main thread.

The end of the trace matches the ANR's timestamp, as shown in Figure 2.
![Perfetto UI showing the end of a trace, highlighting the ANR trigger
location.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-anr-trigger.png) **Figure 2.** ANR trigger location.

The trace also shows operations the app was running when the ANR occurred.
Specifically, the app ran code in the `handleNetworkResponse` trace slice. This
slice was inside the `MyApp:SubmitButton` slice. It used 1.48 seconds of CPU
time (Figure 3).
![Perfetto UI showing the CPU time consumed by the handleNetworkResponse
execution at the time of the ANR.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-execution-at-trigger.png) **Figure 3.** Execution at the time of ANR.

If you rely solely on stack traces at the moment of the ANR for debugging, you
might wrongly attribute the ANR entirely to the code running within
`handleNetworkResponse` trace slice which had not ended when the profile
finished recording. However,
1.48 seconds is insufficient to trigger an ANR on its own, even though it is an
expensive operation. You need to look further back in time to understand what
blocked the main thread before this method.
| **Tip:** We recommend you to [add custom trace slices](https://developer.android.com/topic/performance/tracing/custom-events) to identify long running operations and to identify important user journeys.

To grab a starting point to look for the cause for the ANR we start looking
after the last frame generated by the UI thread which corresponds to
`Choreographer#doFrame 551275` slice and there aren't big sources of delay prior
to starting the `MyApp:SubmitButton` slice that ended in the ANR (Figure 4).
![Perfetto UI showing last frame rendered by UI thread prior the ANR.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-last-frame-pre-anr.png) **Figure 4.** Last app frame generated before the ANR.

To understand the blockage, zoom out to inspect the full `MyApp:SubmitButton`
slice. You will notice a critical detail in the thread states, as shown in
Figure 4: the thread spent **75% of the time (6.7 seconds) in `Sleeping` state**
and only **24% of the time in `Running` state**.
![Perfetto UI showing thread states during an operation, highlighting 75%
sleeping and 24% running time.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-blockingop-thread-states.png) **Figure 5.** Thread states during \`MyApp:SubmitButton\` operation.

This indicates that the primary cause of the ANR was waiting, not computation.
Examine the individual sleep occurrences to find a pattern.
![Perfetto UI showing the first sleeping interval within the
MyAppSubmitButton trace slice.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-first-sleep.png) **Figure 6.** First sleeping time within \`MyAppSubmitButton\`. ![Perfetto UI showing the second sleeping interval within the
MyAppSubmitButton trace slice.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-second-sleep.png) **Figure 7.** Second sleeping time within \`MyAppSubmitButton\`. ![Perfetto UI showing the third sleeping interval within the
MyAppSubmitButton trace slice.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-third-sleep.png) **Figure 8.** Third sleeping time within \`MyAppSubmitButton\`. ![Perfetto UI showing the fourth sleeping interval within the
MyAppSubmitButton trace slice.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-fourth-sleep.png) **Figure 9.** Fourth sleeping time within \`MyAppSubmitButton\`.

The first three sleep intervals (Figures 6--8) are nearly identical,
approximately 2 seconds each. An outlier fourth sleep (Figure 9) is 0.7 seconds.
A duration of exactly 2 seconds is rarely a coincidence in a computing
environment. This strongly suggests a programmed timeout rather than random
resource contention. The last sleep might be caused by the thread finishing its
wait because the operation it was waiting on succeeded.

This hypothesis is that **the app was hitting a user-defined timeout of 2
seconds multiple times** and eventually succeeding, causing enough delay to
trigger an ANR.
![Perfetto UI showing a summary of delays during the MyApp:SubmitButton
trace slice, indicating multiple 2-second sleep intervals.](https://developer.android.com/static/topic/performance/images/tracing/debugging-anr-example-delay-summary.png) **Figure 10.** Summary of delays during \`MyApp:SubmitButton\` slice.

To verify this, inspect the code associated with the `MyApp:SubmitButton` trace
section:


```java
private static final int NETWORK_TIMEOUT_MILLISECS = 2000;
public void setupButtonCallback() {
  findViewById(R.id.submit).setOnClickListener(submitButtonView -> {
    Trace.beginSection("MyApp:SubmitButton");
    onClickSubmit();
    Trace.endSection();
  });
}

public void onClickSubmit() {
  prepareNetworkRequest();

  boolean networkRequestSuccess = false;
  int maxAttempts = 10;
  while (!networkRequestSuccess && maxAttempts > 0) {
    networkRequestSuccess = performNetworkRequest(NETWORK_TIMEOUT_MILLISECS);
    maxAttempts--;
  }

  if (networkRequestSuccess) {
    handleNetworkResponse();
  }
}

boolean performNetworkRequest(int timeoutMiliseconds) {
  // ...
}

  // ...
}

public void handleNetworkResponse() {
  Trace.beginSection("handleNetworkResponse");
  // ...
  Trace.endSection();
}
```

<br />

The code confirms this hypothesis. The `onClickSubmit` method executes a network
request on the UI thread with a hardcoded `NETWORK_TIMEOUT_MILLISECS` of 2000ms.
Crucially, it runs inside a `while` loop that retries up to 10 times.

In this specific trace, the user likely had poor network connectivity. The first
three attempts failed, causing three 2-second timeouts (a total of 6 seconds).
The fourth attempt succeeded after 0.7 seconds, allowing the code to proceed to
`handleNetworkResponse`. However, the accumulated wait time already triggered
the ANR.
| **Note:** When trace analysis leads to a hypothesis (for example, "this is a network timeout") but the trace data is insufficient to prove it, use an iterative approach. Add new trace slices around the suspected logic and collect new field data to validate the hypothesis.

Avoid this type of ANR by putting network-related operations that have varying
latencies into a background thread instead of executing them in the main thread.
This allows the UI to remain responsive even with poor connectivity, completely
eliminating this class of ANRs.